From 4e289806b2b0aca7e37057511843e18be1041eb0 Mon Sep 17 00:00:00 2001 From: Andrei Elkin Date: Thu, 10 Jan 2019 16:32:56 +0200 Subject: MDEV-17803 Row-based event is not applied when table map id is greater 32 bit int Row-based slave applier could not parse correctly the table id when the value exceeded the max of 32 bit unsigned int. The reason turns out in that the being parsed value placeholder was sized as 4 bytes. The type is fixed to ulonglong. Additionally the patch works around Rows_log_event::m_table_id 4 bytes size on 32 bits platforms. In case of last_table_id value overflows the 4 byte max, there won't be the zero value for m_table_id generated and the first wrapped-around value is one, this is thanks to excluding UINT_MAX32 + 1 from TABLE_SHARE::table_map_id. --- .../suite/rpl/r/rpl_row_big_table_id_32bit.result | 38 +++++++++++++++ .../suite/rpl/r/rpl_row_big_table_id_64bit.result | 38 +++++++++++++++ mysql-test/suite/rpl/t/rpl_row_big_table_id.inc | 56 ++++++++++++++++++++++ .../suite/rpl/t/rpl_row_big_table_id_32bit.test | 11 +++++ .../suite/rpl/t/rpl_row_big_table_id_64bit.test | 11 +++++ sql/table.h | 2 +- sql/table_cache.cc | 5 +- 7 files changed, 159 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_row_big_table_id_32bit.result create mode 100644 mysql-test/suite/rpl/r/rpl_row_big_table_id_64bit.result create mode 100644 mysql-test/suite/rpl/t/rpl_row_big_table_id.inc create mode 100644 mysql-test/suite/rpl/t/rpl_row_big_table_id_32bit.test create mode 100644 mysql-test/suite/rpl/t/rpl_row_big_table_id_64bit.test diff --git a/mysql-test/suite/rpl/r/rpl_row_big_table_id_32bit.result b/mysql-test/suite/rpl/r/rpl_row_big_table_id_32bit.result new file mode 100644 index 00000000000..f84f02cc416 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_row_big_table_id_32bit.result @@ -0,0 +1,38 @@ +include/master-slave.inc +[connection master] +include/rpl_restart_server.inc [server_number=1] +SET @@debug_dbug="d,simulate_big_table_id"; +CREATE TABLE t (a int); +INSERT INTO t SET a= 0; +ALTER TABLE t comment ''; +INSERT INTO t SET a= 1; +ALTER TABLE t comment ''; +INSERT INTO t SET a= 2; +ALTER TABLE t comment ''; +INSERT INTO t SET a= 3; +show binlog events in from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000002 # Gtid 1 # BEGIN GTID #-#-# +master-bin.000002 # Table_map 1 # table_id: 4294967294 (test.t) +master-bin.000002 # Write_rows_v1 1 # table_id: 4294967294 flags: STMT_END_F +master-bin.000002 # Query 1 # COMMIT +master-bin.000002 # Gtid 1 # GTID #-#-# +master-bin.000002 # Query 1 # use `test`; ALTER TABLE t comment '' +master-bin.000002 # Gtid 1 # BEGIN GTID #-#-# +master-bin.000002 # Table_map 1 # table_id: 1 (test.t) +master-bin.000002 # Write_rows_v1 1 # table_id: 1 flags: STMT_END_F +master-bin.000002 # Query 1 # COMMIT +master-bin.000002 # Gtid 1 # GTID #-#-# +master-bin.000002 # Query 1 # use `test`; ALTER TABLE t comment '' +master-bin.000002 # Gtid 1 # BEGIN GTID #-#-# +master-bin.000002 # Table_map 1 # table_id: 2 (test.t) +master-bin.000002 # Write_rows_v1 1 # table_id: 2 flags: STMT_END_F +master-bin.000002 # Query 1 # COMMIT +master-bin.000002 # Gtid 1 # GTID #-#-# +master-bin.000002 # Query 1 # use `test`; ALTER TABLE t comment '' +master-bin.000002 # Gtid 1 # BEGIN GTID #-#-# +master-bin.000002 # Table_map 1 # table_id: 3 (test.t) +master-bin.000002 # Write_rows_v1 1 # table_id: 3 flags: STMT_END_F +master-bin.000002 # Query 1 # COMMIT +DROP TABLE t; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/r/rpl_row_big_table_id_64bit.result b/mysql-test/suite/rpl/r/rpl_row_big_table_id_64bit.result new file mode 100644 index 00000000000..d8ecadc61d1 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_row_big_table_id_64bit.result @@ -0,0 +1,38 @@ +include/master-slave.inc +[connection master] +include/rpl_restart_server.inc [server_number=1] +SET @@debug_dbug="d,simulate_big_table_id"; +CREATE TABLE t (a int); +INSERT INTO t SET a= 0; +ALTER TABLE t comment ''; +INSERT INTO t SET a= 1; +ALTER TABLE t comment ''; +INSERT INTO t SET a= 2; +ALTER TABLE t comment ''; +INSERT INTO t SET a= 3; +show binlog events in from ; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000002 # Gtid 1 # BEGIN GTID #-#-# +master-bin.000002 # Table_map 1 # table_id: 4294967294 (test.t) +master-bin.000002 # Write_rows_v1 1 # table_id: 4294967294 flags: STMT_END_F +master-bin.000002 # Query 1 # COMMIT +master-bin.000002 # Gtid 1 # GTID #-#-# +master-bin.000002 # Query 1 # use `test`; ALTER TABLE t comment '' +master-bin.000002 # Gtid 1 # BEGIN GTID #-#-# +master-bin.000002 # Table_map 1 # table_id: 4294967295 (test.t) +master-bin.000002 # Write_rows_v1 1 # table_id: 4294967295 flags: STMT_END_F +master-bin.000002 # Query 1 # COMMIT +master-bin.000002 # Gtid 1 # GTID #-#-# +master-bin.000002 # Query 1 # use `test`; ALTER TABLE t comment '' +master-bin.000002 # Gtid 1 # BEGIN GTID #-#-# +master-bin.000002 # Table_map 1 # table_id: 4294967296 (test.t) +master-bin.000002 # Write_rows_v1 1 # table_id: 4294967296 flags: STMT_END_F +master-bin.000002 # Query 1 # COMMIT +master-bin.000002 # Gtid 1 # GTID #-#-# +master-bin.000002 # Query 1 # use `test`; ALTER TABLE t comment '' +master-bin.000002 # Gtid 1 # BEGIN GTID #-#-# +master-bin.000002 # Table_map 1 # table_id: 4294967297 (test.t) +master-bin.000002 # Write_rows_v1 1 # table_id: 4294967297 flags: STMT_END_F +master-bin.000002 # Query 1 # COMMIT +DROP TABLE t; +include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_big_table_id.inc b/mysql-test/suite/rpl/t/rpl_row_big_table_id.inc new file mode 100644 index 00000000000..926b6e8b0ac --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_big_table_id.inc @@ -0,0 +1,56 @@ +################################################################## +# rpl_row_big_table_id +# +# MDEV-17803 Row-based event is not applied when +# table map id is greater 32 bit int +# +# Verify row-based events applying when table map id value is about and greater +# than 1 << 32. +################################################################## +--source include/have_debug.inc +--source include/have_binlog_format_row.inc +--source include/master-slave.inc + +--connection master +# To reset last table id +--let $rpl_server_number= 1 +--source include/rpl_restart_server.inc + +SET @@debug_dbug="d,simulate_big_table_id"; +CREATE TABLE t (a int); + +--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1) +--let $binlog_pos= query_get_value(SHOW MASTER STATUS, Position, 1) +INSERT INTO t SET a= 0; +ALTER TABLE t comment ''; +INSERT INTO t SET a= 1; +ALTER TABLE t comment ''; +INSERT INTO t SET a= 2; +ALTER TABLE t comment ''; +INSERT INTO t SET a= 3; + +# display simulated big table_id +--let $_in_from=in '$binlog_file' from $binlog_pos +--replace_result "$_in_from" "in from " +--replace_column 2 # 5 # +--replace_regex /\/\* xid=.* \*\//\/* XID *\// /file_id=[0-9]+/file_id=#/ /GTID [0-9]+-[0-9]+-[0-9]+/GTID #-#-#/ +--eval show binlog events in '$binlog_file' from $binlog_pos + + +--sync_slave_with_master + +if (`SELECT sum(a) != 6 FROM t`) +{ + --echo *** unexpected result; check slave applier *** + --die +} + + +# Cleanup + +--connection master +DROP TABLE t; + +--sync_slave_with_master + +--source include/rpl_end.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_big_table_id_32bit.test b/mysql-test/suite/rpl/t/rpl_row_big_table_id_32bit.test new file mode 100644 index 00000000000..08e1827c4c6 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_big_table_id_32bit.test @@ -0,0 +1,11 @@ +################################################################## +# rpl_row_big_table_id +# +# MDEV-17803 Row-based event is not applied when +# table map id is greater 32 bit int +# +# Verify row-based events applying when table map id value is about and greater +# than 1 << 32. +################################################################## +--source include/have_32bit.inc +--source rpl_row_big_table_id.inc diff --git a/mysql-test/suite/rpl/t/rpl_row_big_table_id_64bit.test b/mysql-test/suite/rpl/t/rpl_row_big_table_id_64bit.test new file mode 100644 index 00000000000..f9e021cdd2c --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_big_table_id_64bit.test @@ -0,0 +1,11 @@ +################################################################## +# rpl_row_big_table_id +# +# MDEV-17803 Row-based event is not applied when +# table map id is greater 32 bit int +# +# Verify row-based events applying when table map id value is about and greater +# than 1 << 32. +################################################################## +--source include/have_64bit.inc +--source rpl_row_big_table_id.inc diff --git a/sql/table.h b/sql/table.h index 4a1552f8c0d..10c1d1bc68e 100644 --- a/sql/table.h +++ b/sql/table.h @@ -1816,7 +1816,7 @@ struct TABLE_LIST /* Index names in a "... JOIN ... USE/IGNORE INDEX ..." clause. */ List *index_hints; TABLE *table; /* opened table */ - uint table_id; /* table id (from binlog) for opened table */ + ulonglong table_id; /* table id (from binlog) for opened table */ /* select_result for derived table to pass it from table creation to table filling procedure diff --git a/sql/table_cache.cc b/sql/table_cache.cc index f13d7183a99..1154017d8d5 100644 --- a/sql/table_cache.cc +++ b/sql/table_cache.cc @@ -1206,6 +1206,9 @@ void tdc_assign_new_table_id(TABLE_SHARE *share) DBUG_ASSERT(share); DBUG_ASSERT(tdc_inited); + DBUG_EXECUTE_IF("simulate_big_table_id", + if (last_table_id < UINT_MAX32) + last_table_id= UINT_MAX32 - 1;); /* There is one reserved number that cannot be used. Remember to change this when 6-byte global table id's are introduced. @@ -1215,7 +1218,7 @@ void tdc_assign_new_table_id(TABLE_SHARE *share) my_atomic_rwlock_wrlock(&LOCK_tdc_atomics); tid= my_atomic_add64(&last_table_id, 1); my_atomic_rwlock_wrunlock(&LOCK_tdc_atomics); - } while (unlikely(tid == ~0UL)); + } while (unlikely(tid == ~0UL || tid == 0)); share->table_map_id= tid; DBUG_PRINT("info", ("table_id= %lu", share->table_map_id)); -- cgit v1.2.1