diff options
author | Andrei Elkin <andrei.elkin@mariadb.com> | 2018-10-08 21:47:53 +0300 |
---|---|---|
committer | Andrei Elkin <andrei.elkin@mariadb.com> | 2018-10-16 12:42:57 +0300 |
commit | d8974ebd677f97cf80bf0cd1446e60631895a5d7 (patch) | |
tree | 4a4bab7b1ef39ffe193aaaa0d6e0ed525c841efa | |
parent | 5a5bc21a65eb28f22b2896d96bd5fad0557b5719 (diff) | |
download | mariadb-git-d8974ebd677f97cf80bf0cd1446e60631895a5d7.tar.gz |
MDEV-14431 binlog.binlog_flush_binlogs_delete_domain failed in buildbot
The test and also rpl_gtid_delete_domain failed on PPC64 platform
due to an incorrectly specified actual key for searching
in a gtid domain system hash. While the correct size is 32 bits
the supplied value was 8 bytes of long int size on the platform.
The problem became evident thanks to the big endiness which
cut off the *least* significant part of the value field.
Fixed with correcting a dynamic array initialization to hold
now uint32 values as well as the values extraction for
searching in the gtid domain system hash.
A new added test ensures no overflowed values are accepted
for deletion which prevents inadvertent action. Notice though
MariaDB [test]> set @@session.gtid_domain_id=(1 << 32) + 1;
MariaDB [test]> show warnings;
+---------+------+--------------------------------------------------------+
| Level | Code | Message |
+---------+------+--------------------------------------------------------+
| Warning | 1292 | Truncated incorrect gtid_domain_id value: '4294967297' |
+---------+------+--------------------------------------------------------+
MariaDB [test]> select @@session.gtid_domain_id;
+--------------------------+
| @@session.gtid_domain_id |
+--------------------------+
| 4294967295 |
+--------------------------+
-rw-r--r-- | mysql-test/suite/binlog/r/binlog_flush_binlogs_delete_domain.result | 12 | ||||
-rw-r--r-- | mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test | 19 | ||||
-rw-r--r-- | sql/rpl_gtid.cc | 6 | ||||
-rw-r--r-- | sql/sql_lex.cc | 2 | ||||
-rw-r--r-- | sql/sql_lex.h | 2 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 13 |
6 files changed, 47 insertions, 7 deletions
diff --git a/mysql-test/suite/binlog/r/binlog_flush_binlogs_delete_domain.result b/mysql-test/suite/binlog/r/binlog_flush_binlogs_delete_domain.result index 99f2a57835f..fdcfb4bfa01 100644 --- a/mysql-test/suite/binlog/r/binlog_flush_binlogs_delete_domain.result +++ b/mysql-test/suite/binlog/r/binlog_flush_binlogs_delete_domain.result @@ -17,6 +17,12 @@ master-bin.000002 # SET @@SESSION.gtid_domain_id=1; SET @@SESSION.server_id=1; CREATE TABLE t (a int); +SELECT @@GLOBAL.gtid_binlog_state, @@GLOBAL.gtid_binlog_pos; +@@GLOBAL.gtid_binlog_state @@GLOBAL.gtid_binlog_pos +1-1-1 1-1-1 +include/show_binlog_events.inc +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 # Rotate # # master-bin.000002;pos=POS FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1); ERROR HY000: Could not delete gtid domain. Reason: binlog files may contain gtids from the domain ('1') being deleted. Make sure to first purge those files. FLUSH BINARY LOGS; @@ -74,5 +80,11 @@ the following command succeeds with warnings FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1); Warnings: Warning 1076 The current gtid binlog state is incompatible with a former one having a gtid '11-11-1' which is less than the '11-11-11' of the gtid list describing an earlier state. The state may have been affected by manually injecting a lower sequence number gtid or via replication. +RESET MASTER; +FLUSH BINARY LOGS DELETE_DOMAIN_ID = (4294967296); +ERROR HY000: The value of gtid domain being deleted ('4294967296') exceeds its maximum size of 32 bit unsigned integer +FLUSH BINARY LOGS DELETE_DOMAIN_ID = (4294967295); +Warnings: +Warning 1076 The gtid domain being deleted ('4294967295') is not in the current binlog state DROP TABLE t; RESET MASTER; diff --git a/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test b/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test index 0faafa35a1b..8311f4bd800 100644 --- a/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test +++ b/mysql-test/suite/binlog/t/binlog_flush_binlogs_delete_domain.test @@ -28,6 +28,9 @@ FLUSH BINARY LOGS DELETE_DOMAIN_ID = (99); SET @@SESSION.gtid_domain_id=1; SET @@SESSION.server_id=1; CREATE TABLE t (a int); +SELECT @@GLOBAL.gtid_binlog_state, @@GLOBAL.gtid_binlog_pos; +--let $binlog_start= +--source include/show_binlog_events.inc --error ER_BINLOG_CANT_DELETE_GTID_DOMAIN FLUSH BINARY LOGS DELETE_DOMAIN_ID = (1); @@ -129,6 +132,22 @@ SELECT @gtid_binlog_state_saved "as original state", @@GLOBAL.gtid_binlog_state --echo the following command succeeds with warnings --eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($del_d_id) +# cleanup: forget the out-of-order +RESET MASTER; + +# +# MDEV-14431 +# Check rejection to delete a domain with value exceeding its range's maximum +# +--let $d_max_plus_1=`SELECT 1 << 32` +--error ER_BINLOG_CANT_DELETE_GTID_DOMAIN +--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($d_max_plus_1) + +# accepted maximum: +--let $d_max=`SELECT (1 << 32) - 1` +--error 0 +--eval FLUSH BINARY LOGS DELETE_DOMAIN_ID = ($d_max) + # # Cleanup # diff --git a/sql/rpl_gtid.cc b/sql/rpl_gtid.cc index 955763fe195..2d4acde03fc 100644 --- a/sql/rpl_gtid.cc +++ b/sql/rpl_gtid.cc @@ -1846,10 +1846,10 @@ rpl_binlog_state::drop_domain(DYNAMIC_ARRAY *ids, for (ulong i= 0; i < ids->elements; i++) { rpl_binlog_state::element *elem= NULL; - ulong *ptr_domain_id; + uint32 *ptr_domain_id; bool not_match; - ptr_domain_id= (ulong*) dynamic_array_ptr(ids, i); + ptr_domain_id= (uint32*) dynamic_array_ptr(ids, i); elem= (rpl_binlog_state::element *) my_hash_search(&hash, (const uchar *) ptr_domain_id, 0); if (!elem) @@ -1870,7 +1870,7 @@ rpl_binlog_state::drop_domain(DYNAMIC_ARRAY *ids, if (not_match) { - sprintf(errbuf, "binlog files may contain gtids from the domain ('%lu') " + sprintf(errbuf, "binlog files may contain gtids from the domain ('%u') " "being deleted. Make sure to first purge those files", *ptr_domain_id); errmsg= errbuf; diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 085ad1a4b3b..1e6abf74a85 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -2882,7 +2882,7 @@ LEX::LEX() INITIAL_LEX_PLUGIN_LIST_SIZE, 0); reset_query_tables_list(TRUE); mi.init(); - init_dynamic_array2(&delete_gtid_domain, sizeof(ulong*), + init_dynamic_array2(&delete_gtid_domain, sizeof(uint32), gtid_domain_static_buffer, initial_gtid_domain_buffer_size, initial_gtid_domain_buffer_size, 0); diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 05e31c28277..f1edc809579 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -2752,7 +2752,7 @@ public: */ DYNAMIC_ARRAY delete_gtid_domain; static const ulong initial_gtid_domain_buffer_size= 16; - ulong gtid_domain_static_buffer[initial_gtid_domain_buffer_size]; + uint32 gtid_domain_static_buffer[initial_gtid_domain_buffer_size]; inline void set_limit_rows_examined() { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 6ae65e0c50f..af1d67fb2cf 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -12829,9 +12829,18 @@ delete_domain_id_list: ; delete_domain_id: - ulong_num + ulonglong_num { - insert_dynamic(&Lex->delete_gtid_domain, (uchar*) &($1)); + uint32 value= (uint32) $1; + if ($1 > UINT_MAX32) + { + my_printf_error(ER_BINLOG_CANT_DELETE_GTID_DOMAIN, + "The value of gtid domain being deleted ('%llu') " + "exceeds its maximum size " + "of 32 bit unsigned integer", MYF(0), $1); + MYSQL_YYABORT; + } + insert_dynamic(&Lex->delete_gtid_domain, (uchar*) &value); } ; |