From a64991df9d86c57a597e012cbf04accb7a49defe Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Sun, 30 Jan 2022 15:32:56 -0700 Subject: [PATCH] MDEV-4989: Support for GTID in mysqlbinlog This patch fixes two issues: First, it fixes test failure due to GTID List events having inconsistent ordering of domain ids. In particular, this patch ensures that a GTID list log event will have its GTIDs ordered by domain id (ascending) followed by sequence number (ascending). Second, it fixes an assert which could use an unintialized variable. Reviewed By: ============ Andrei Elkin --- .../r/binlog_mysqlbinlog_glle_ordered.result | 19 ++++++++ ...binlog_mysqlbinlog_gtid_strict_mode.result | 6 +-- .../r/binlog_mysqlbinlog_gtid_window.result | 4 +- .../t/binlog_mysqlbinlog_glle_ordered.test | 43 +++++++++++++++++++ sql/log_event.cc | 14 ++++++ sql/log_event.h | 6 +++ sql/log_event_client.cc | 2 + sql/log_event_server.cc | 6 +++ sql/rpl_gtid.cc | 5 +-- sql/rpl_gtid.h | 12 ++++++ 10 files changed, 109 insertions(+), 8 deletions(-) create mode 100644 mysql-test/suite/binlog/r/binlog_mysqlbinlog_glle_ordered.result create mode 100644 mysql-test/suite/binlog/t/binlog_mysqlbinlog_glle_ordered.test diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_glle_ordered.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_glle_ordered.result new file mode 100644 index 00000000000..2826cba99ae --- /dev/null +++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_glle_ordered.result @@ -0,0 +1,19 @@ +RESET MASTER; +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 1; +CREATE TABLE t1 (a int); +SET @@session.gtid_domain_id= 1; +SET @@session.server_id= 2; +CREATE TABLE t2 (a int); +SET @@session.server_id= 1; +INSERT INTO t2 VALUES (1); +SET @@session.gtid_domain_id= 2; +SET @@session.server_id= 3; +CREATE TABLE t3 (a int); +FLUSH LOGS; +FLUSH LOGS; +# MYSQL_BINLOG MYSQLD_DATADIR/binlog_file > SEARCH_FILE +FOUND 1 /Gtid list \[0-1-1,\n# 1-2-1,\n# 1-1-2,\n# 2-3-1\]/ in tmp_binlog.out +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_gtid_strict_mode.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_gtid_strict_mode.result index 668c070b5ea..c2f7bac387c 100644 --- a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_gtid_strict_mode.result +++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_gtid_strict_mode.result @@ -272,7 +272,7 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin.000002 # Gtid_list 1 # [0-1-1] show binlog events in 'master-bin.000003' limit 1,1; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000003 # Gtid_list 1 # [1-2-1,0-1-2] +master-bin.000003 # Gtid_list 1 # [0-1-2,1-2-1] # MYSQL_BINLOG MYSQLD_DATADIR/BINLOG_FILE1 MYSQLD_DATADIR/BINLOG_FILE3 --gtid-strict-mode 2> log_error_ > OUT_FILE # We should have two warnings about missing data from domains 0 and 1 if # -vvv is specified @@ -578,7 +578,7 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin.000002 # Gtid_list 1 # [0-1-1] show binlog events in 'master-bin.000003' limit 1,1; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000003 # Gtid_list 1 # [1-2-1,0-1-2] +master-bin.000003 # Gtid_list 1 # [0-1-2,1-2-1] # MYSQL_BINLOG MYSQLD_DATADIR/BINLOG_FILE1 MYSQLD_DATADIR/BINLOG_FILE3 --skip-gtid-strict-mode -vvv 2> log_error_ > OUT_FILE # We should have two warnings about missing data from domains 0 and 1 if # -vvv is specified @@ -883,7 +883,7 @@ Log_name Pos Event_type Server_id End_log_pos Info master-bin.000002 # Gtid_list 1 # [0-1-1] show binlog events in 'master-bin.000003' limit 1,1; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000003 # Gtid_list 1 # [1-2-1,0-1-2] +master-bin.000003 # Gtid_list 1 # [0-1-2,1-2-1] # MYSQL_BINLOG MYSQLD_DATADIR/BINLOG_FILE1 MYSQLD_DATADIR/BINLOG_FILE3 --skip-gtid-strict-mode 2> log_error_ > OUT_FILE # We should have two warnings about missing data from domains 0 and 1 if # -vvv is specified diff --git a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_gtid_window.result b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_gtid_window.result index 63af0d20cc6..fce5f95ce82 100644 --- a/mysql-test/suite/binlog/r/binlog_mysqlbinlog_gtid_window.result +++ b/mysql-test/suite/binlog/r/binlog_mysqlbinlog_gtid_window.result @@ -41,7 +41,7 @@ FLUSH LOGS; # matched against --start-position in the following tests: show binlog events in 'master-bin.000002' limit 1,1; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000002 # Gtid_list 1 # [1-3-4,1-2-5,0-1-3] +master-bin.000002 # Gtid_list 1 # [0-1-3,1-3-4,1-2-5] DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; @@ -249,7 +249,7 @@ FLUSH LOGS; # matched against --start-position in the following tests: show binlog events in 'master-bin.000002' limit 1,1; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000002 # Gtid_list 1 # [1-3-4,1-2-5,0-1-3] +master-bin.000002 # Gtid_list 1 # [0-1-3,1-3-4,1-2-5] DROP TABLE t1; DROP TABLE t2; DROP TABLE t3; diff --git a/mysql-test/suite/binlog/t/binlog_mysqlbinlog_glle_ordered.test b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_glle_ordered.test new file mode 100644 index 00000000000..9c79925b4bd --- /dev/null +++ b/mysql-test/suite/binlog/t/binlog_mysqlbinlog_glle_ordered.test @@ -0,0 +1,43 @@ +# +# Purpose: +# This test validates that GTIDs are ordered when mysqlbinlog outputs +# Gtid_list events. +# +# Methodology: +# Write multiple events to the binlog with different domain ids and server +# ids, and ensure that the Gtid_list event GTIDs are ordered first by domain id +# (ascending), and then sequence number (ascending). +# +# References: +# MDEV-4989: Support for GTID in mysqlbinlog +# +--source include/have_log_bin.inc + +RESET MASTER; +SET @@session.gtid_domain_id= 0; +SET @@session.server_id= 1; +CREATE TABLE t1 (a int); +SET @@session.gtid_domain_id= 1; +SET @@session.server_id= 2; +CREATE TABLE t2 (a int); +SET @@session.server_id= 1; +INSERT INTO t2 VALUES (1); +SET @@session.gtid_domain_id= 2; +SET @@session.server_id= 3; +CREATE TABLE t3 (a int); +FLUSH LOGS; +FLUSH LOGS; + +--let $binlog_file= query_get_value(SHOW BINARY LOGS, Log_name, 2) +--let $MYSQLD_DATADIR=`select @@datadir` +--let SEARCH_FILE=$MYSQLTEST_VARDIR/tmp/tmp_binlog.out + +--echo # MYSQL_BINLOG MYSQLD_DATADIR/binlog_file > SEARCH_FILE +--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $SEARCH_FILE + +--let SEARCH_PATTERN= Gtid list \[0-1-1,\n# 1-2-1,\n# 1-1-2,\n# 2-3-1\] +--source include/search_pattern_in_file.inc + +DROP TABLE t1; +DROP TABLE t2; +DROP TABLE t3; diff --git a/sql/log_event.cc b/sql/log_event.cc index d3d44e8dc30..b3943760720 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2653,6 +2653,20 @@ Gtid_log_event::Gtid_log_event(const uchar *buf, uint event_len, buf_0[event_len - 1] == 0); } +int compare_glle_gtids(const void * _gtid1, const void *_gtid2) +{ + rpl_gtid *gtid1= (rpl_gtid *) _gtid1; + rpl_gtid *gtid2= (rpl_gtid *) _gtid2; + + int ret; + if (*gtid1 < *gtid2) + ret= -1; + else if (*gtid1 > *gtid2) + ret= 1; + else + ret= 0; + return ret; +} /* GTID list. */ diff --git a/sql/log_event.h b/sql/log_event.h index db80ca841a2..405b9a15003 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -5902,4 +5902,10 @@ int row_log_event_uncompress(const Format_description_log_event bool is_parallel_retry_error(rpl_group_info *rgi, int err); +/* + Compares two GTIDs to facilitate sorting a GTID list log event by domain id + (ascending) and sequence number (ascending) +*/ +int compare_glle_gtids(const void * _gtid1, const void *_gtid2); + #endif /* _log_event_h */ diff --git a/sql/log_event_client.cc b/sql/log_event_client.cc index 9e75d3f4c4c..e460fc17848 100644 --- a/sql/log_event_client.cc +++ b/sql/log_event_client.cc @@ -2342,6 +2342,8 @@ Gtid_list_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info) char buf[21]; uint32 i; + qsort(list, count, sizeof(rpl_gtid), compare_glle_gtids); + if (print_header(&cache, print_event_info, FALSE) || my_b_printf(&cache, "\tGtid list [")) goto err; diff --git a/sql/log_event_server.cc b/sql/log_event_server.cc index cf16d538744..ca988354205 100644 --- a/sql/log_event_server.cc +++ b/sql/log_event_server.cc @@ -4085,6 +4085,12 @@ Gtid_list_log_event::pack_info(Protocol *protocol) uint32 i; bool first; + /* + For output consistency and ease of reading, we sort the GTID list in + ascending order + */ + qsort(list, count, sizeof(rpl_gtid), compare_glle_gtids); + buf.length(0); buf.append(STRING_WITH_LEN("[")); first= true; diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 7b0e1e4a363..ae40fd46f4d 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -3398,9 +3398,8 @@ my_bool Window_gtid_event_filter::exclude(rpl_gtid *gtid) /* Assume result should be excluded to start */ my_bool should_exclude= TRUE; - DBUG_ASSERT((m_has_start || m_has_stop) && - (gtid->domain_id == m_start.domain_id || - gtid->domain_id == m_stop.domain_id)); + DBUG_ASSERT((m_has_start && gtid->domain_id == m_start.domain_id) || + (m_has_stop && gtid->domain_id == m_stop.domain_id)); if (!m_is_active && !m_has_passed) { diff --git a/sql/rpl_gtid.h b/sql/rpl_gtid.h index 8b8c3bb9c92..759e4e4eea3 100644 --- a/sql/rpl_gtid.h +++ b/sql/rpl_gtid.h @@ -48,6 +48,18 @@ inline bool operator==(const rpl_gtid& lhs, const rpl_gtid& rhs) lhs.seq_no == rhs.seq_no; }; +inline bool operator<(const rpl_gtid& lhs, const rpl_gtid& rhs) +{ + return (lhs.domain_id == rhs.domain_id) ? lhs.seq_no < rhs.seq_no + : lhs.domain_id < rhs.domain_id; +}; + +inline bool operator>(const rpl_gtid& lhs, const rpl_gtid& rhs) +{ + return (lhs.domain_id == rhs.domain_id) ? lhs.seq_no > rhs.seq_no + : lhs.domain_id > rhs.domain_id; +}; + enum enum_gtid_skip_type { GTID_SKIP_NOT, GTID_SKIP_STANDALONE, GTID_SKIP_TRANSACTION };