From 2a2019e199c5bd9575e1a65369654c39453cdb35 Mon Sep 17 00:00:00 2001 From: Kristian Nielsen Date: Sun, 5 May 2024 19:01:22 +0200 Subject: [PATCH] MDEV-33798: Follow-up patch Don't deadlock kill event groups in other domains if they are not SPECULATE_OPTIMISTIC. Such event groups may not be able to safely roll back and retry (eg. DDL). But do deadlock kill a transaction T2 from a blocked transaction U in another domain, even if T2 has lower sub_id than U. Otherwise, in case of a cycle T2->T1->U->T2, we might not break the cycle if U is not SPECULATE_OPTIMISTIC Signed-off-by: Kristian Nielsen --- sql/sql_class.cc | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/sql/sql_class.cc b/sql/sql_class.cc index a9203a80c10..7b3c81a381d 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -5400,31 +5400,32 @@ thd_rpl_deadlock_check(MYSQL_THD thd, MYSQL_THD other_thd) return 0; if (!rgi->is_parallel_exec) return 0; - if (rgi->rli == other_rgi->rli) + if (rgi->rli == other_rgi->rli && + rgi->current_gtid.domain_id == other_rgi->current_gtid.domain_id) { /* - Within the same master connection, we can compare transaction order on - the GTID sub_id, and rollback the later transaction to allow the earlier - transaction to commit first. + Within the same master connection and domain, we can compare transaction + order on the GTID sub_id, and rollback the later transaction to allow the + earlier transaction to commit first. */ - if (!rgi->gtid_sub_id || !other_rgi->gtid_sub_id) - return 0; - if (rgi->gtid_sub_id > other_rgi->gtid_sub_id) + if (!rgi->gtid_sub_id || !other_rgi->gtid_sub_id || + rgi->gtid_sub_id > other_rgi->gtid_sub_id) return 0; } else { /* - Lock conflicts between different master connection should usually not - occur, but could still happen if user is running some special setup that - tolerates conflicting updates (or in case of user error). We do not have a - pre-defined ordering of transactions in this case, but we still need to - handle conflicts in _some_ way to avoid undetected deadlocks and hangs. + Lock conflicts between different master connections or domains should + usually not occur, but could still happen if user is running some + special setup that tolerates conflicting updates (or in case of user + error). We do not have a pre-defined ordering of transactions in this + case, but we still need to handle conflicts in _some_ way to avoid + undetected deadlocks and hangs. We do this by rolling back and retrying any transaction that is being _optimistically_ applied. This can be overly conservative in some cases, - but should be fine as conflicts between different master connections are - not expected to be common. And it ensures that we won't end up in a + but should be fine as conflicts between different master connections / + domains are not common. And it ensures that we won't end up in a deadlock and hang due to a transaction doing wait_for_prior_commit while holding locks that block something in another master connection. */