Description:
If we start a XA transaction and prepared it. then, if we do 'XA rollback' with the wrong xid, the "XA rollback" will execute failed. but the "XA rollback" has been recorded into the binlog with the right xid. If in the replication, the master do the 'xa rollback' with the wrong xid, rollback failed, but on slave, maybe rollback succeed.
How to repeat:
create table t(id int primary key)engine=innodb;
start a session to do like below:
xa start '1';
insert into t values(1);
xa end '1';
xa prepare '1';
xa rollback '2'; //xa rollback with the wrong xid
after doing above, the "xa rollback '2'" execute failed, but this operation is recorded into the binlog with the xid '1', use another session to do: show binlog events, the result is:
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| Log_name | Pos | Event_type | Server_id | End_log_pos | Info |
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
| mysql-bin.000001 | 4 | Format_desc | 11 | 123 | Server ver: 5.7.19-log, Binlog ver: 4 |
| mysql-bin.000001 | 123 | Previous_gtids | 11 | 150 | |
| mysql-bin.000001 | 150 | Anonymous_Gtid | 11 | 211 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000001 | 211 | Query | 11 | 294 | XA START X'31',X'',1 |
| mysql-bin.000001 | 294 | Table_map | 11 | 334 | table_id: 220 (mydb.t) |
| mysql-bin.000001 | 334 | Write_rows | 11 | 370 | table_id: 220 flags: STMT_END_F |
| mysql-bin.000001 | 370 | Query | 11 | 451 | XA END X'31',X'',1 |
| mysql-bin.000001 | 451 | XA_prepare | 11 | 484 | XA PREPARE X'31',X'',1 |
| mysql-bin.000001 | 484 | Anonymous_Gtid | 11 | 545 | SET @@SESSION.GTID_NEXT= 'ANONYMOUS' |
| mysql-bin.000001 | 545 | Query | 11 | 631 | XA ROLLBACK X'31',X'',1 |
+------------------+-----+----------------+-----------+-------------+---------------------------------------+
also you can use mysqlbinlog -v to check it in the binlog file:
XA START X'31',X'',1
/*!*/;
# at 294
#170811 16:21:02 server id 11 end_log_pos 334 Table_map: `mydb`.`t` mapped to number 220
# at 334
#170811 16:21:02 server id 11 end_log_pos 370 Write_rows: table id 220 flags: STMT_END_F
BINLOG '
7miNWRMLAAAAKAAAAE4BAAAAANwAAAAAAAEABG15ZGIAAXQAAQMAAA==
7miNWR4LAAAAJAAAAHIBAAAAANwAAAAAAAEAAgAB//4BAAAA
'/*!*/;
### INSERT INTO `mydb`.`t`
### SET
### @1=1
# at 370
#170811 16:21:16 server id 11 end_log_pos 451 Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1502439676/*!*/;
XA END X'31',X'',1
/*!*/;
# at 451
#170811 16:21:16 server id 11 end_log_pos 484 XA PREPARE X'31',X'',1
XA PREPARE X'31',X'',1
/*!*/;
# at 484
#170811 16:21:27 server id 11 end_log_pos 545 Anonymous_GTID last_committed=1 sequence_number=2 rbr_only=no
SET @@SESSION.GTID_NEXT= 'ANONYMOUS'/*!*/;
# at 545
#170811 16:21:27 server id 11 end_log_pos 631 Query thread_id=3 exec_time=0 error_code=0
SET TIMESTAMP=1502439687/*!*/;
XA ROLLBACK X'31',X'',1
/*!*/;
SET @@SESSION.GTID_NEXT= 'AUTOMATIC' /* added by mysqlbinlog */ /*!*/;
DELIMITER ;
# End of log file
The last log event is: XA ROLLBACK X'31',X'',1, this log event maybe incorrect!!
Suggested fix:
if the xa rollback with wrong xid, it will not be recorded into binlog.
maybe modify the function binlog.cc:MYSQL_BIN_LOG::rollback, when do the SQLCOM_XA_ROLLBACK command, check the xid is the same or not, if not the same, do not write the binlog.