mysql2 icon indicating copy to clipboard operation
mysql2 copied to clipboard

"Commands out of sync" exceptions with threads and prepared statements.

Open Math2 opened this issue 1 year ago • 2 comments

The problem was happening with a connection pool shared by many threads, but I found a simple way to reproduce it:

conf = { ... }

clients = 10.times.map { Mysql2::Client.new(**conf) }

loop do
  clients.map do |client|
    Thread.new { client.prepare("SELECT 123").execute }
  end.each(&:join)
end

This immediately fails with "Commands out of sync; you can't run this command now (Mysql2::Error)" here (after 50 or so iterations of the outer loop).

With #query it works fine. It only fails with prepared statements.

Math2 avatar Nov 22 '23 13:11 Math2

Oops, actually if you #close the statements, this works fine.

I believe I'm seeing a problem with threads and prepared statements that happens without prepared statements accumulating endlessly like this, but this isn't a way to reproduce it...

Math2 avatar Nov 22 '23 13:11 Math2

Very curious. This one fails with "Commands out of sync" exceptions while reusing the same prepared statements, but apparently only if the query returns 0 rows!

conf = { ... }

clients = 10.times.map { Mysql2::Client.new(**conf) }
stmts = clients.map { |client| client.prepare("SELECT 123 WHERE FALSE") }

loop do
  stmts.map do |stmt|
    Thread.new { stmt.execute }
  end.each(&:join)
end

Math2 avatar Nov 22 '23 13:11 Math2