-
Notifications
You must be signed in to change notification settings - Fork 72
Description
TDLR: the prepare: :unnamed
setting seems to have no effect.
We have read through related tickets like #92 and #83 but still want to create a new one.
Our use case is as follows: users can upload xlsx files that contain a large number of rows (+3000) to process. Processing in our case means doing some data cleansing and then insert and or update multiple records across tables.
To execute the queries we use the regular Ecto API, being all/2
, one/2
, update/2
, etc. For each row to be processed, we execute 10 to 15 queries, depending on the flow.
Whilst developing we always used stub files with a very limited amount of rows. Now the client is using actual files with said number of rows, meaning that the number of executed queries quickly ramps up.
Upon the first report of a crash and after seeing the uploaded file, we quickly reasoned that it probably was a timeout on the GET request or something like that. Instead, we saw the error described in the other related issue reports:
MyXQL.Connection (#PID<0.2375.0>) disconnected: ** (DBConnection.ConnectionError) client #PID<0.2952.0> exited
After that, we ran the process again whilst looking at the :observer
and grabbed the messages from the exited PID, where we could read:
#{'__struct__' => 'Elixir.MyXQL.Connection',
client =>
#{'__struct__' => 'Elixir.MyXQL.Client',connection_id => 2275,
sock => {gen_tcp,#Port<0.129>}},
cursors => #{},
disconnect_on_error_codes => ['ER_MAX_PREPARED_STMT_COUNT_REACHED'],
last_ref => nil,ping_timeout => 15000,prepare => unnamed,
queries => #Ref<0.3597155187.3075080195.95704>,transaction_status => idle}
A bit surprising, since we did not realize we were using prepared statements, but it made perfect sense, considering the amount of queries. We ran it again and while running kept an eye on the server stats for the prepared statement count and although it increased, it was never near the maximum allowed on the server...
Still, it kind of made sense as a possible root cause. We then first tried chunking all rows into smaller lists and processing those with a Process.sleep/1
after each row, to allow the connections to be cleaned up, but the error persisted.
We also tried applying the prepare: :unnamed
in our config, but that seemed to do 'nothing' (as in: the count of prepared statements went up none the less). Here is how we provided the option inside config.exs
config :the_app, TheApp.Repo,
username: System.get_env("DB_USER"),
password: System.get_env("DB_PASSWORD"),
database: System.get_env("DB_NAME"),
hostname: System.get_env("DB_HOST"),
pool_size: 5,
pool_overflow: 20,
timeout: 120_000,
prepare: :unnamed
As you can see we also tried playing with the pool_size
and the pool_overflow
variable, the latter which is an unknown option we assume now, it probably should be max_overflow
?
With a very low pool size it seems to work, but we still don't understand why the prepared statement count goes up. Also we would prefer to have a pool_size
of 10, since that is what we use on all our projects. But then again, none of the other projects with myxql
perform that many queries. We have only one other user case that does that, and it worked fine, but it using mariaex
. And reverting our current app to mariaex
does not seem feasible now, too many deps on myxql
and/or Ecto 3.