Skip to content

Commit 20ddf64

Browse files
committed
Mysql2Adapter: gracefully handle Unknown prepared statement handler errors
The source of this error is really unclear, I suspect `mysql2` or `libmysqlclient` sometimes silently reconnect, which cause all handlers to be invalidated, but I have no proof of that. However, if we get this precise error code, we know it's safe to retry as there was no side effect.
1 parent 4ee81ca commit 20ddf64

File tree

1 file changed

+14
-2
lines changed

1 file changed

+14
-2
lines changed

activerecord/lib/active_record/connection_adapters/mysql2/database_statements.rb

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,12 +58,24 @@ def perform_query(raw_connection, sql, binds, type_casted_binds, prepare:, notif
5858
# of hitting the bug.
5959
@affected_rows_before_warnings = result&.size || raw_connection.affected_rows
6060
elsif prepare
61-
stmt = @statements[sql] ||= raw_connection.prepare(sql)
61+
retry_count = 1
6262
begin
63+
stmt = @statements[sql] ||= raw_connection.prepare(sql)
6364
result = stmt.execute(*type_casted_binds)
6465
@affected_rows_before_warnings = stmt.affected_rows
65-
rescue ::Mysql2::Error
66+
rescue ::Mysql2::Error => error
6667
@statements.delete(sql)
68+
# Sometimes for an unknown reason, we get that error.
69+
# It suggest somehow that the prepared statement was deallocated
70+
# but the client doesn't know it.
71+
# But we know that this error is safe to retry, so we do so after
72+
# getting rid of the originally cached statement.
73+
if error.error_number == 1243 # ER_UNKNOWN_STMT_HANDLER
74+
if retry_count.positive?
75+
retry_count -= 1
76+
retry
77+
end
78+
end
6779
raise
6880
end
6981
else

0 commit comments

Comments
 (0)