mirror of
https://github.com/MariaDB/server.git
synced 2026-02-01 08:19:08 +01:00
When using the InnoDB-implemented binlog with another transactional storage engine, or with explicit user XA transactions, recover such transactions consistently from the binlog at server startup. When a transaction is prepared with an XID, the binlog records a "prepare" record containing the XID and link to the out-of-band replication event data. When a previously prepared transaction is committed, the commit record links to the oob data referenced from the prepare record, and the record is preceeded by an "XA complete" record containing the XID. If instead a prepared transaction is rolled back, just an "XA complete" record is binlogged with the XID and a "rollback" flag. While any prepared XA transactions are active, maintain in-memory reference counts in each binlog file, and in each binlog file record the file_no of the earliest binlog file containing any XID records of still active transactions. When the server restarts (possibly after crash), look up the file_no of the earliest binlog file that may contain active XID records, if any. Scan the binlogs from that point and record any XID prepare or complete records. For any XID prepare record, record oob data and reference count, recovering the in-memory state present before the server restart. Return a hash to the server layer containing each active XID in the binlog and its state (prepared, committed, rolled back). On the server layer, ask each engine for a list of pending XID in prepared state. If the binlog state of an XID is committed, commit in the engine. If the binlog state is rolled back or is missing, roll back in the engine. If the binlog state is prepared, _and_ all participating engines have the transaction prepared also, then leave the transaction prepared. If a binlog prepared transaction is missing from an engine, then roll it back in any other engines and in the binlog (this is to handle a crash in the middle of an XA PREPARE). The result is that multi-engine (or non-InnoDB) transactions, as well as user XA transactions, will be recovered after a crash consisent with the binlog content. Signed-off-by: Kristian Nielsen <knielsen@knielsen-hq.org>
70 lines
2.6 KiB
Text
70 lines
2.6 KiB
Text
include/reset_master.inc
|
|
CREATE TABLE t1 (a INT PRIMARY KEY, b INT) ENGINE=InnoDB;
|
|
CREATE TABLE t2 (a INT PRIMARY KEY, b INT) ENGINE=RocksDB;
|
|
*** A simple multi-engine transaction.
|
|
BEGIN;
|
|
INSERT INTO t1 VALUES (1, 0);
|
|
INSERT INTO t2 VALUES (1, 0);
|
|
COMMIT;
|
|
include/show_binlog_events.inc
|
|
Log_name Pos Event_type Server_id End_log_pos Info
|
|
binlog-000000.ibb # Gtid # # BEGIN GTID #-#-#
|
|
binlog-000000.ibb # Query # # use `test`; INSERT INTO t1 VALUES (1, 0)
|
|
binlog-000000.ibb # Annotate_rows # # INSERT INTO t2 VALUES (1, 0)
|
|
binlog-000000.ibb # Table_map # # table_id: # (test.t2)
|
|
binlog-000000.ibb # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
|
binlog-000000.ibb # Xid # # COMMIT /* XID */
|
|
*** A couple multi-engine transactions where we crash in the middle.
|
|
connect con1,localhost,root,,;
|
|
BEGIN;
|
|
INSERT INTO t2 VALUES (2, 0);
|
|
INSERT INTO t2 VALUES (20, 1);
|
|
INSERT INTO t2 VALUES (21, 2);
|
|
SET debug_sync= 'ibb_after_commit_redo_log SIGNAL con1_rdy WAIT_FOR crash';
|
|
/* a */ COMMIT;
|
|
connection default;
|
|
SET debug_sync= 'now WAIT_FOR con1_rdy';
|
|
connect con2,localhost,root,,;
|
|
BEGIN;
|
|
INSERT INTO t1 VALUES (3, 0);
|
|
INSERT INTO t2 VALUES (3, 0);
|
|
SET debug_sync= 'ibb_after_group_commit_redo_log SIGNAL con2_rdy WAIT_FOR crash';
|
|
/* b */ COMMIT;
|
|
connection default;
|
|
SET debug_sync= 'now WAIT_FOR con2_rdy';
|
|
# restart
|
|
disconnect con1;
|
|
disconnect con2;
|
|
connection default;
|
|
include/show_binlog_events.inc
|
|
Log_name Pos Event_type Server_id End_log_pos Info
|
|
binlog-000000.ibb # Gtid # # BEGIN GTID #-#-#
|
|
binlog-000000.ibb # Annotate_rows # # INSERT INTO t2 VALUES (2, 0)
|
|
binlog-000000.ibb # Table_map # # table_id: # (test.t2)
|
|
binlog-000000.ibb # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
|
binlog-000000.ibb # Annotate_rows # # INSERT INTO t2 VALUES (20, 1)
|
|
binlog-000000.ibb # Table_map # # table_id: # (test.t2)
|
|
binlog-000000.ibb # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
|
binlog-000000.ibb # Annotate_rows # # INSERT INTO t2 VALUES (21, 2)
|
|
binlog-000000.ibb # Table_map # # table_id: # (test.t2)
|
|
binlog-000000.ibb # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
|
binlog-000000.ibb # Xid # # COMMIT /* XID */
|
|
binlog-000000.ibb # Gtid # # BEGIN GTID #-#-#
|
|
binlog-000000.ibb # Query # # use `test`; INSERT INTO t1 VALUES (3, 0)
|
|
binlog-000000.ibb # Annotate_rows # # INSERT INTO t2 VALUES (3, 0)
|
|
binlog-000000.ibb # Table_map # # table_id: # (test.t2)
|
|
binlog-000000.ibb # Write_rows_v1 # # table_id: # flags: STMT_END_F
|
|
binlog-000000.ibb # Xid # # COMMIT /* XID */
|
|
binlog-000000.ibb # Format_desc # # SERVER_VERSION, BINLOG_VERSION
|
|
SELECT * FROM t1 ORDER BY a;
|
|
a b
|
|
1 0
|
|
3 0
|
|
SELECT * FROM t2 ORDER BY a;
|
|
a b
|
|
1 0
|
|
2 0
|
|
3 0
|
|
20 1
|
|
21 2
|
|
DROP TABLE t1, t2;
|