Skip to content

Commit 6693e5f

Browse files
committed
Deadlocks inside transactions are functionally not retryable
Even if we think the deadlocking query could be retried, the original deadlock will have either broken or already rolled back our transaction.
1 parent 3cc2f8a commit 6693e5f

File tree

2 files changed

+11
-8
lines changed

2 files changed

+11
-8
lines changed

activerecord/lib/active_record/connection_adapters/abstract_adapter.rb

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -921,8 +921,13 @@ def retryable_connection_error?(exception)
921921
end
922922

923923
def retryable_query_error?(exception)
924-
exception.is_a?(Deadlocked) ||
925-
exception.is_a?(LockWaitTimeout)
924+
# We definitely can't retry if we were inside a transaction that was instantly
925+
# rolled back by this error
926+
if exception.is_a?(TransactionRollbackError) && savepoint_errors_invalidate_transactions? && open_transactions > 0
927+
false
928+
else
929+
exception.is_a?(Deadlocked) || exception.is_a?(LockWaitTimeout)
930+
end
926931
end
927932

928933
def backoff(counter)

activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -711,12 +711,10 @@ def translate_exception(exception, message:, sql:, binds:)
711711
end
712712

713713
def retryable_query_error?(exception)
714-
end
715-
716-
def retryable_connection_error?(exception)
717-
case exception
718-
when PG::ConnectionBad; !exception.message.end_with?("\n")
719-
end
714+
# We cannot retry anything if we're inside a broken transaction; we need to at
715+
# least raise until the innermost savepoint is rolled back
716+
@raw_connection&.transaction_status != ::PG::PQTRANS_INERROR &&
717+
super
720718
end
721719

722720
def get_oid_type(oid, fmod, column_name, sql_type = "")

0 commit comments

Comments
 (0)