mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
MDEV-28461 semisync-slave server recovery fails to rollback prepared transaction
that is not in binlog. Post-crash recovery of --rpl-semi-sync-slave-enabled server failed to recognize a transaction in-doubt that needed rolled back. A prepared-but-not-in-binlog transaction gets committed instead to possibly create inconsistency with a master (e.g the way it was observed in the bug report). The semisync recovery is corrected now with initializing binlog coordinates of any transaction in-doubt to the maximum offset which is unreachable. In effect when a prepared transaction that is not found in binlog it will be decided to rollback because it's guaranteed to reside in a truncated tail area of binlog. Mtr tests are reinforced to cover the described scenario.
This commit is contained in:
@@ -4,11 +4,13 @@ RESET MASTER;
|
||||
SET @@global.sync_binlog=1;
|
||||
CREATE TABLE t (f INT) ENGINE=INNODB;
|
||||
CREATE TABLE t2 (f INT) ENGINE=INNODB;
|
||||
CREATE TABLE t4 (f INT) ENGINE=INNODB;
|
||||
CREATE TABLE tm (f INT) ENGINE=Aria;
|
||||
# Case A.
|
||||
connect master1,localhost,root,,;
|
||||
connect master2,localhost,root,,;
|
||||
connect master3,localhost,root,,;
|
||||
connect master4,localhost,root,,;
|
||||
connection default;
|
||||
INSERT INTO t VALUES (10);
|
||||
INSERT INTO tm VALUES (10);
|
||||
@@ -23,14 +25,23 @@ connection master3;
|
||||
SET DEBUG_SYNC= "now WAIT_FOR master2_ready";
|
||||
SELECT @@global.gtid_binlog_pos as 'Before the crash';
|
||||
Before the crash
|
||||
0-1-7
|
||||
0-1-8
|
||||
connection master4;
|
||||
SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL master4_ready WAIT_FOR signal_never_arrives";
|
||||
INSERT INTO t4 VALUES (13);
|
||||
connection master3;
|
||||
SET DEBUG_SYNC= "now WAIT_FOR master4_ready";
|
||||
SELECT @@global.gtid_binlog_pos as 'Before the crash and never logged trx';
|
||||
Before the crash and never logged trx
|
||||
0-1-8
|
||||
connection default;
|
||||
# Kill the server
|
||||
disconnect master1;
|
||||
disconnect master2;
|
||||
disconnect master3;
|
||||
# restart: --rpl-semi-sync-slave-enabled=1 --sync-binlog=1
|
||||
FOUND 1 /Successfully truncated.*to remove transactions starting from GTID 0-1-6/ in mysqld.1.err
|
||||
disconnect master4;
|
||||
# restart: --rpl-semi-sync-slave-enabled=1 --sync-binlog=1 --log-warnings=3
|
||||
FOUND 1 /Successfully truncated.*to remove transactions starting from GTID 0-1-7/ in mysqld.1.err
|
||||
Pre-crash binlog file content:
|
||||
include/show_binlog_events.inc
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
@@ -39,6 +50,8 @@ master-bin.000001 # Query # # use `test`; CREATE TABLE t (f INT) ENGINE=INNODB
|
||||
master-bin.000001 # Gtid # # GTID #-#-#
|
||||
master-bin.000001 # Query # # use `test`; CREATE TABLE t2 (f INT) ENGINE=INNODB
|
||||
master-bin.000001 # Gtid # # GTID #-#-#
|
||||
master-bin.000001 # Query # # use `test`; CREATE TABLE t4 (f INT) ENGINE=INNODB
|
||||
master-bin.000001 # Gtid # # GTID #-#-#
|
||||
master-bin.000001 # Query # # use `test`; CREATE TABLE tm (f INT) ENGINE=Aria
|
||||
master-bin.000001 # Gtid # # BEGIN GTID #-#-#
|
||||
master-bin.000001 # Query # # use `test`; INSERT INTO t VALUES (10)
|
||||
@@ -48,16 +61,20 @@ master-bin.000001 # Query # # use `test`; INSERT INTO tm VALUES (10)
|
||||
master-bin.000001 # Query # # COMMIT
|
||||
SELECT @@global.gtid_binlog_pos as 'After the crash';
|
||||
After the crash
|
||||
0-1-5
|
||||
0-1-6
|
||||
"One row should be present in table 't'"
|
||||
SELECT * FROM t;
|
||||
f
|
||||
10
|
||||
"No row should be present in table 't4'"
|
||||
SELECT * FROM t4;
|
||||
f
|
||||
DELETE FROM t;
|
||||
# Case B.
|
||||
connect master1,localhost,root,,;
|
||||
connect master2,localhost,root,,;
|
||||
connect master3,localhost,root,,;
|
||||
connect master4,localhost,root,,;
|
||||
connection default;
|
||||
INSERT INTO t VALUES (10);
|
||||
INSERT INTO tm VALUES (10);
|
||||
@@ -72,14 +89,23 @@ connection master3;
|
||||
SET DEBUG_SYNC= "now WAIT_FOR master2_ready";
|
||||
SELECT @@global.gtid_binlog_pos as 'Before the crash';
|
||||
Before the crash
|
||||
0-1-10
|
||||
0-1-11
|
||||
connection master4;
|
||||
SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL master4_ready WAIT_FOR signal_never_arrives";
|
||||
INSERT INTO t4 VALUES (13);
|
||||
connection master3;
|
||||
SET DEBUG_SYNC= "now WAIT_FOR master4_ready";
|
||||
SELECT @@global.gtid_binlog_pos as 'Before the crash and never logged trx';
|
||||
Before the crash and never logged trx
|
||||
0-1-11
|
||||
connection default;
|
||||
# Kill the server
|
||||
disconnect master1;
|
||||
disconnect master2;
|
||||
disconnect master3;
|
||||
# restart: --rpl-semi-sync-slave-enabled=1 --sync-binlog=1
|
||||
FOUND 1 /Successfully truncated.*to remove transactions starting from GTID 0-1-10/ in mysqld.1.err
|
||||
disconnect master4;
|
||||
# restart: --rpl-semi-sync-slave-enabled=1 --sync-binlog=1 --log-warnings=3
|
||||
FOUND 1 /Successfully truncated.*to remove transactions starting from GTID 0-1-11/ in mysqld.1.err
|
||||
Pre-crash binlog file content:
|
||||
include/show_binlog_events.inc
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
@@ -97,11 +123,14 @@ master-bin.000002 # Query # # use `test`; DELETE FROM t2 WHERE f = 0
|
||||
master-bin.000002 # Query # # COMMIT
|
||||
SELECT @@global.gtid_binlog_pos as 'After the crash';
|
||||
After the crash
|
||||
0-1-9
|
||||
0-1-10
|
||||
"One row should be present in table 't'"
|
||||
SELECT * FROM t;
|
||||
f
|
||||
10
|
||||
"No row should be present in table 't4'"
|
||||
SELECT * FROM t4;
|
||||
f
|
||||
DELETE FROM t;
|
||||
# Case C.
|
||||
CREATE PROCEDURE sp_blank_xa()
|
||||
@@ -114,6 +143,7 @@ END|
|
||||
connect master1,localhost,root,,;
|
||||
connect master2,localhost,root,,;
|
||||
connect master3,localhost,root,,;
|
||||
connect master4,localhost,root,,;
|
||||
connection default;
|
||||
INSERT INTO t VALUES (10);
|
||||
INSERT INTO tm VALUES (10);
|
||||
@@ -128,14 +158,23 @@ connection master3;
|
||||
SET DEBUG_SYNC= "now WAIT_FOR master2_ready";
|
||||
SELECT @@global.gtid_binlog_pos as 'Before the crash';
|
||||
Before the crash
|
||||
0-1-15
|
||||
0-1-16
|
||||
connection master4;
|
||||
SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL master4_ready WAIT_FOR signal_never_arrives";
|
||||
INSERT INTO t4 VALUES (13);
|
||||
connection master3;
|
||||
SET DEBUG_SYNC= "now WAIT_FOR master4_ready";
|
||||
SELECT @@global.gtid_binlog_pos as 'Before the crash and never logged trx';
|
||||
Before the crash and never logged trx
|
||||
0-1-16
|
||||
connection default;
|
||||
# Kill the server
|
||||
disconnect master1;
|
||||
disconnect master2;
|
||||
disconnect master3;
|
||||
# restart: --rpl-semi-sync-slave-enabled=1 --sync-binlog=1
|
||||
FOUND 1 /Successfully truncated.*to remove transactions starting from GTID 0-1-14/ in mysqld.1.err
|
||||
disconnect master4;
|
||||
# restart: --rpl-semi-sync-slave-enabled=1 --sync-binlog=1 --log-warnings=3
|
||||
FOUND 1 /Successfully truncated.*to remove transactions starting from GTID 0-1-15/ in mysqld.1.err
|
||||
Pre-crash binlog file content:
|
||||
include/show_binlog_events.inc
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
@@ -158,11 +197,14 @@ master-bin.000003 # Query # # use `test`; INSERT INTO tm VALUES (10)
|
||||
master-bin.000003 # Query # # COMMIT
|
||||
SELECT @@global.gtid_binlog_pos as 'After the crash';
|
||||
After the crash
|
||||
0-1-13
|
||||
0-1-14
|
||||
"One row should be present in table 't'"
|
||||
SELECT * FROM t;
|
||||
f
|
||||
10
|
||||
"No row should be present in table 't4'"
|
||||
SELECT * FROM t4;
|
||||
f
|
||||
DELETE FROM t;
|
||||
DROP PROCEDURE sp_blank_xa;
|
||||
# Case D.
|
||||
@@ -176,6 +218,7 @@ END|
|
||||
connect master1,localhost,root,,;
|
||||
connect master2,localhost,root,,;
|
||||
connect master3,localhost,root,,;
|
||||
connect master4,localhost,root,,;
|
||||
connection default;
|
||||
INSERT INTO t VALUES (10);
|
||||
INSERT INTO tm VALUES (10);
|
||||
@@ -190,14 +233,23 @@ connection master3;
|
||||
SET DEBUG_SYNC= "now WAIT_FOR master2_ready";
|
||||
SELECT @@global.gtid_binlog_pos as 'Before the crash';
|
||||
Before the crash
|
||||
0-1-20
|
||||
0-1-21
|
||||
connection master4;
|
||||
SET DEBUG_SYNC= "ha_commit_trans_before_log_and_order SIGNAL master4_ready WAIT_FOR signal_never_arrives";
|
||||
INSERT INTO t4 VALUES (13);
|
||||
connection master3;
|
||||
SET DEBUG_SYNC= "now WAIT_FOR master4_ready";
|
||||
SELECT @@global.gtid_binlog_pos as 'Before the crash and never logged trx';
|
||||
Before the crash and never logged trx
|
||||
0-1-21
|
||||
connection default;
|
||||
# Kill the server
|
||||
disconnect master1;
|
||||
disconnect master2;
|
||||
disconnect master3;
|
||||
# restart: --rpl-semi-sync-slave-enabled=1 --sync-binlog=1
|
||||
FOUND 1 /Successfully truncated.*to remove transactions starting from GTID 0-1-20/ in mysqld.1.err
|
||||
disconnect master4;
|
||||
# restart: --rpl-semi-sync-slave-enabled=1 --sync-binlog=1 --log-warnings=3
|
||||
FOUND 1 /Successfully truncated.*to remove transactions starting from GTID 0-1-21/ in mysqld.1.err
|
||||
Pre-crash binlog file content:
|
||||
include/show_binlog_events.inc
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
@@ -226,11 +278,14 @@ master-bin.000004 # Query # # XA END X'786964',X'',1
|
||||
master-bin.000004 # XA_prepare # # XA PREPARE X'786964',X'',1
|
||||
SELECT @@global.gtid_binlog_pos as 'After the crash';
|
||||
After the crash
|
||||
0-1-19
|
||||
0-1-20
|
||||
"One row should be present in table 't'"
|
||||
SELECT * FROM t;
|
||||
f
|
||||
10
|
||||
"No row should be present in table 't4'"
|
||||
SELECT * FROM t4;
|
||||
f
|
||||
DELETE FROM t;
|
||||
DROP PROCEDURE sp_xa;
|
||||
# Cleanup
|
||||
|
Reference in New Issue
Block a user