Description:
During binlog rotation, LOCK_log is acquired to prevent new binlog writes. It then waits for m_atomic_prep_xids to decrement to zero, ensuring all in-flight committing transactions are completed. However, for XA COMMIT/XA ROLLBACK statements, binlog entries are generated without an XID. Consequently, binlog rotation does not wait for these transactions to complete. This may result in rotation occurring before their commits finish, causing the previous gtids captured during rotation to miss their GTIDs.
How to repeat:
run mtr test below, thd result may like this:
show binlog events in 'mysql-bin.000002';
Log_name Pos Event_type Server_id End_log_pos Info
mysql-bin.000002 4 Format_desc 1 127 Server ver: 8.4.5-debug, Binlog ver: 4
mysql-bin.000002 127 Previous_gtids 1 198 3e5af6a9-7332-11f0-ad1f-5254009b6854:1-5
mysql-bin.000002 198 Gtid 1 275 SET @@SESSION.GTID_NEXT= '3e5af6a9-7332-11f0-ad1f-5254009b6854:7'
mysql-bin.000002 275 Query 1 402 use `test`; DROP TABLE `t1` /* generated by server */ /* xid=70 */
Previous_gtids contains [3e5af6a9-7332-11f0-ad1f-5254009b6854:1-5], while the new SQL statement carries GTID [3e5af6a9-7332-11f0-ad1f-5254009b6854:7]. GTID [3e5af6a9-7332-11f0-ad1f-5254009b6854:6] is missing.
-------------------------------------opt-----------------------------------------
--log-bin=mysql-bin
--gtid_mode=ON
--enforce-gtid-consistency
-------------------------------------mtr-----------------------------------------
--source include/have_log_bin.inc
--source include/have_debug.inc
--connect(conn1,localhost,root,,test)
--connect(conn2,localhost,root,,test)
--connect(conn3,localhost,root,,test)
create table t1 (id int primary key auto_increment);
create table t2 (id int primary key auto_increment);
insert into t1 values();
--let $rpl_connection_name= conn1
--source include/connection.inc
xa start '1';insert into t1 values();xa end '1';xa prepare '1';
--let $rpl_connection_name= conn2
--source include/connection.inc
SET SESSION debug="+d,force_rotate";
SET debug_sync="bgc_after_commit_stage_before_rotation WAIT_FOR conn2_wait";
--send insert into t2 values();
sleep 1;
--let $rpl_connection_name= conn1
--source include/connection.inc
SET debug_sync="update_gtid_state_before_global_tsid_lock WAIT_FOR conn1_wait";
--send xa commit '1';
--let $rpl_connection_name= conn3
--source include/connection.inc
SET debug_sync = "now SIGNAL conn2_wait";
sleep 2;
SET debug_sync = "now SIGNAL conn1_wait";
drop table t1;
show binlog events in 'mysql-bin.000002';