Bug #118797 Contribution by Tencent: previous gtids may loss xa commit/rollback gtids
Submitted: 7 Aug 2:08 Modified: 7 Aug 9:10
Reporter: yewei Xu (OCA) Email Updates:
Status: Verified Impact on me:
None 
Category:MySQL Server: Replication Severity:S2 (Serious)
Version:8.4, 8.4.6, 9.4.0 OS:Any
Assigned to: CPU Architecture:Any
Tags: binlolg

[7 Aug 2:08] yewei Xu
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';
[7 Aug 9:10] MySQL Verification Team
Hello  Yewei Xu,

Thank you for the report and test case.
Verified as described.

regards,
Umesh