Skip to content

Commit 4407703

Browse files
committed
MDEV-37541 Race of rolling back and committing transaction to binlog
The 2nd commit of two contains the fixes. Two transactions could binlog their completions in opposite to how it is done in Engine. That is is rare situations ROLLBACK in Engine could be scheduled first by 2pc coordinator to leave by chance binlogging of the transaction and whatever might be dependent on it in execution time. This is fixed with ensuring the binlog rollback handlerton is always executed first in 2pc.
1 parent 473bdfa commit 4407703

File tree

3 files changed

+37
-13
lines changed

3 files changed

+37
-13
lines changed

mysql-test/suite/binlog/r/binlog_mdev37541.result

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,17 @@ insert into t_x values (1);
88
drop temporary table tt_tmp;
99
insert into t1 values (99, "gotta log first");
1010
SET DEBUG_SYNC= 'reset';
11-
SET DEBUG_SYNC= "before_group_commit_queue WAIT_FOR trx1_go";
11+
SET DEBUG_SYNC= "before_group_commit_queue SIGNAL trx1_at_log WAIT_FOR trx1_go";
1212
ROLLBACK;
13-
connection default;
13+
connect trx2_commit,localhost,root,,;
1414
insert into t1 values (99, "second best in binlog");
15+
connection default;
16+
SET DEBUG_SYNC= "now WAIT_FOR trx1_at_log";
17+
SET DEBUG_SYNC= "now SIGNAL trx1_go";
18+
connection trx2_commit;
1519
select * from t1;
1620
a b
1721
99 second best in binlog
18-
SET DEBUG_SYNC= "now SIGNAL trx1_go";
1922
# Prove the logging order is Trx1, Trx2
2023
include/show_binlog_events.inc
2124
Log_name Pos Event_type Server_id End_log_pos Info
@@ -25,13 +28,14 @@ master-bin.000001 # Table_map # # table_id: # (test.t_x)
2528
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
2629
master-bin.000001 # Query # # COMMIT
2730
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
28-
master-bin.000001 # Query # # use `test`; insert into t1 values (99, "second best in binlog")
29-
master-bin.000001 # Xid # # COMMIT /* XID */
30-
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
3131
master-bin.000001 # Annotate_rows # # insert into t1 values (99, "gotta log first")
3232
master-bin.000001 # Table_map # # table_id: # (test.t1)
3333
master-bin.000001 # Write_rows_v1 # # table_id: # flags: STMT_END_F
3434
master-bin.000001 # Query # # ROLLBACK
35+
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
36+
master-bin.000001 # Query # # use `test`; insert into t1 values (99, "second best in binlog")
37+
master-bin.000001 # Xid # # COMMIT /* XID */
3538
drop table t_x, t1;
3639
disconnect trx1_rollback;
40+
disconnect trx2_commit;
3741
# end of the tests

mysql-test/suite/binlog/t/binlog_mdev37541.test

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,34 @@ BEGIN;
1616
insert into t1 values (99, "gotta log first");
1717

1818
SET DEBUG_SYNC= 'reset';
19-
SET DEBUG_SYNC= "before_group_commit_queue WAIT_FOR trx1_go";
19+
SET DEBUG_SYNC= "before_group_commit_queue SIGNAL trx1_at_log WAIT_FOR trx1_go";
2020

2121
--send ROLLBACK
2222

23-
# trx2_commit
23+
connect(trx2_commit,localhost,root,,);
24+
--send insert into t1 values (99, "second best in binlog")
25+
2426
connection default;
25-
insert into t1 values (99, "second best in binlog");
26-
select * from t1;
2727

28+
# Make sure ROLLBACK is in the binlogging phase ..
29+
SET DEBUG_SYNC= "now WAIT_FOR trx1_at_log";
30+
# .. and the contender trx2 in the locking phase ..
31+
let $wait_condition=
32+
select count(*) = 1 from information_schema.innodb_trx
33+
where trx_state = "LOCK WAIT" and trx_query like "%insert into t1 values%";
34+
source include/wait_condition.inc;
35+
# .. when both provided unfreeze the trx:s ..
2836
SET DEBUG_SYNC= "now SIGNAL trx1_go";
2937

38+
connection trx2_commit;
39+
reap;
40+
select * from t1;
41+
42+
# .. to observe proper binlogging.
3043
--echo # Prove the logging order is Trx1, Trx2
3144
--source include/show_binlog_events.inc
3245

3346
drop table t_x, t1;
3447
disconnect trx1_rollback;
35-
48+
disconnect trx2_commit;
3649
--echo # end of the tests

sql/handler.cc

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2306,11 +2306,18 @@ int ha_rollback_trans(THD *thd, bool all)
23062306
if (is_real_trans) /* not a statement commit */
23072307
thd->stmt_map.close_transient_cursors();
23082308

2309+
int err;
2310+
if (has_binlog_hton(ha_info) &&
2311+
(err= binlog_hton->rollback(binlog_hton, thd, all)))
2312+
{
2313+
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
2314+
error= 1;
2315+
}
23092316
for (; ha_info; ha_info= ha_info_next)
23102317
{
2311-
int err;
23122318
handlerton *ht= ha_info->ht();
2313-
if ((err= ht->rollback(ht, thd, all)))
2319+
2320+
if (ht != binlog_hton && (err= ht->rollback(ht, thd, all)))
23142321
{
23152322
// cannot happen
23162323
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);

0 commit comments

Comments
 (0)