[MDEV-31140] FLUSH BINARY LOGS DELETE_DOMAIN_ID=(D) can errorneously delete active domains Created: 2023-04-27  Updated: 2023-06-07  Resolved: 2023-05-03

Status: Closed
Project: MariaDB Server
Component/s: Replication
Affects Version/s: 10.1.30, 10.2.11, 10.3.10, 10.4.0, 10.5.0, 10.6.0, 10.8.1, 10.9.1, 10.10.1, 10.11.1, 11.0.1, 10.7
Fix Version/s: 10.11.5, 11.0.3, 11.1.2

Type: Bug Priority: Major
Reporter: Kristian Nielsen Assignee: Kristian Nielsen
Resolution: Fixed Votes: 0
Labels: None


 Description   

Suppose the binlog contains the following:

GTID_LIST [1-1-1, 1-2-2]
START TRANSACTION GTID=1-2-3

The gtid_binlog_state is "1-1-1,1-2-3". Then the following statement will
errorneously succeed:

FLUSH BINARY LOGS DELETE_DOMAIN_ID=(1)

This will leave the binlog in a corrupt state with empty gtid_binlog_state
and empty GTID_LIST in the rotated binlog even though a GTID 1-2-21 in the
domain_id=1 is present in the active binlog.

The problem is that this code in drop_domain() implements the wrong test (it
checks that any GTID in gtid_binlog_state is in the first GTID_LIST event,
where the correct test is that all GTIDs are in the GTID_LIST):

    for (not_match= true, k= 0; k < elem->hash.records; k++) {
      rpl_gtid *d_gtid= (rpl_gtid *)my_hash_element(&elem->hash, k);
      for (ulong l= 0; l < glev->count && not_match; l++)
        not_match= !(*d_gtid == glev->list[l]);
    }
    if (not_match) {
      sprintf(errbuf, "binlog files may contain gtids from the domain ('%u') "
              "being deleted. Make sure to first purge those files", *ptr_domain_id);

I will implement a patch for review.

Test case:

--source include/have_binlog_format_mixed.inc
RESET MASTER;
SET @@SESSION.gtid_domain_id = 1;
SET @@SESSION.server_id = 1;
CREATE TABLE t1 (a INT PRIMARY KEY);
SET @@SESSION.server_id = 2;
INSERT INTO t1 VALUES (1);
# Rotate to get a new GTID_LIST event with the new binlog state.
FLUSH BINARY LOGS;
# Purge to make the oldest GTID_LIST contain the new binlog state.
--let $purge_to_binlog= query_get_value(SHOW MASTER STATUS, File, 1)
eval PURGE BINARY LOGS TO '$purge_to_binlog';
# Now make one entry not match.
SET @@SESSION.server_id = 2;
INSERT INTO t1 VALUES (2);
SELECT @@gtid_binlog_state;
--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN
eval FLUSH BINARY LOGS DELETE_DOMAIN_ID=(1);
 
SHOW BINLOG EVENTS IN "master-bin.000002";
SHOW BINLOG EVENTS IN "master-bin.000003";
# Cleanup.
DROP TABLE t1;



 Comments   
Comment by Kristian Nielsen [ 2023-05-03 ]

Pushed to 10.11

Generated at Thu Feb 08 10:21:35 UTC 2024 using Jira 8.20.16#820016-sha1:9d11dbea5f4be3d4cc21f03a88dd11d8c8687422.