[Commits] a69004c65fe: MDEV-15373 engine gtid_slave_pos table name disobeys lower-case-table-names
revision-id: a69004c65fe33625ef6ff364e32792e4fc413b6b (mariadb-10.3.6-196-ga69004c65fe) parent(s): c2df4e9d624199db421f6fc1a58e354f3f5dbac8 author: Andrei Elkin committer: Andrei Elkin timestamp: 2018-05-16 21:11:07 +0300 message: MDEV-15373 engine gtid_slave_pos table name disobeys lower-case-table-names Replicated transaction extra gtid statement on slave failed to specify an engine gtid_slave_pos name correctly. In case lower-case-table-names > 0 the InnoDB table name was generated to reproduce the lower-case-table-names=0 version which is of mixed cases. In rpl.rpl_mdev12179 test run this triggered a failure to DROP table which was due to the innodb table handle was not closed: InnoDB: Waited XYZ seconds for ref-count on table: `mysql`.`gtid_slave_pos_innodb` on windows. The closing issue was caused by having the table registered twice in the table cache, for its lower- and mixed- case name versions. The DROP-table handler closed only only one of the cache item to leave the 2nd one active. (On Linux a failure occurs earlier at attempt to open an expected lower-cased table: Last_Error: Error during XID COMMIT: failed to update GTID state in mysql.gtid_slave_pos: 1146: Table 'mysql.gtid_slave_pos_InnoDB' doesn't exist but the table's name as the message shows is not in the right case). Fixed with consulting lower-case-table-names when the engine gtid-slave-pos table is created. Note the lower-case-table-names=a-value created table will not recognized when next the lower case option changes to a different value. In 10.4 a follow-up patch is going to lowercase gtid-slave-pos autocreated table at once at their origination, and a warning is issued in the 10.3 current patch. --- mysql-test/suite/rpl/r/rpl_mdev12179.result | 22 +++++++++++----- mysql-test/suite/rpl/t/rpl_mdev12179.test | 40 +++++++++++++++++++++++++++-- sql/rpl_rli.cc | 1 + sql/slave.cc | 18 +++++++++++++ 4 files changed, 73 insertions(+), 8 deletions(-) diff --git a/mysql-test/suite/rpl/r/rpl_mdev12179.result b/mysql-test/suite/rpl/r/rpl_mdev12179.result index 40059375356..bf8bda21211 100644 --- a/mysql-test/suite/rpl/r/rpl_mdev12179.result +++ b/mysql-test/suite/rpl/r/rpl_mdev12179.result @@ -1,5 +1,6 @@ include/rpl_init.inc [topology=1->2] connection server_2; +call mtr.add_suppression("The automatically created table.*name is not entirely in lowercase"); SET GLOBAL gtid_pos_auto_engines="innodb"; ERROR HY000: This operation cannot be performed as you have a running slave ''; run STOP SLAVE '' first include/stop_slave.inc @@ -152,12 +153,12 @@ a 1 2 *** Verify that mysql.gtid_slave_pos_InnoDB is auto-created *** -SELECT table_name, engine FROM information_schema.tables +SELECT lower(table_name), engine FROM information_schema.tables WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' ORDER BY table_name; -table_name engine +lower(table_name) engine gtid_slave_pos MyISAM -gtid_slave_pos_InnoDB InnoDB +gtid_slave_pos_innodb InnoDB include/stop_slave.inc SET sql_log_bin=0; INSERT INTO mysql.gtid_slave_pos SELECT * FROM mysql.gtid_slave_pos_InnoDB; @@ -245,15 +246,24 @@ a 3 4 *** Verify that mysql.gtid_slave_pos_InnoDB is auto-created *** -SELECT table_name, engine FROM information_schema.tables +SELECT lower(table_name), engine FROM information_schema.tables WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' ORDER BY table_name; -table_name engine +lower(table_name) engine gtid_slave_pos MyISAM -gtid_slave_pos_InnoDB InnoDB +gtid_slave_pos_innodb InnoDB SELECT domain_id, max(seq_no) FROM mysql.gtid_slave_pos GROUP BY domain_id; domain_id max(seq_no) 0 13 +connection server_2; +*** Restart the slave server to prove 'gtid_slave_pos_innodb' autodiscovery *** +connection server_2; +SELECT max(seq_no) FROM mysql.gtid_slave_pos_InnoDB into @seq_no; +connection server_1; +INSERT INTO t2(a) SELECT 1+MAX(a) FROM t2; +include/save_master_gtid.inc +connection server_2; +include/sync_with_master_gtid.inc include/stop_slave.inc SET GLOBAL gtid_pos_auto_engines=""; SET sql_log_bin=0; diff --git a/mysql-test/suite/rpl/t/rpl_mdev12179.test b/mysql-test/suite/rpl/t/rpl_mdev12179.test index a9113c91797..5169e709cd2 100644 --- a/mysql-test/suite/rpl/t/rpl_mdev12179.test +++ b/mysql-test/suite/rpl/t/rpl_mdev12179.test @@ -3,6 +3,8 @@ --source include/rpl_init.inc --connection server_2 +call mtr.add_suppression("The automatically created table.*name is not entirely in lowercase"); + --error ER_SLAVE_MUST_STOP SET GLOBAL gtid_pos_auto_engines="innodb"; --source include/stop_slave.inc @@ -161,7 +163,8 @@ let $wait_condition= SELECT EXISTS (SELECT * FROM information_schema.tables WHERE table_schema='mysql' AND table_name='gtid_slave_pos_InnoDB'); --source include/wait_condition.inc -SELECT table_name, engine FROM information_schema.tables +# MDEV-15373 lowercases 'table_name' to satisfy --lower-case-table-names options +SELECT lower(table_name), engine FROM information_schema.tables WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' ORDER BY table_name; @@ -225,7 +228,7 @@ let $wait_condition= SELECT EXISTS (SELECT * FROM information_schema.tables WHERE table_schema='mysql' AND table_name='gtid_slave_pos_InnoDB'); --source include/wait_condition.inc -SELECT table_name, engine FROM information_schema.tables +SELECT lower(table_name), engine FROM information_schema.tables WHERE table_schema='mysql' AND table_name LIKE 'gtid_slave_pos%' ORDER BY table_name; SELECT domain_id, max(seq_no) FROM mysql.gtid_slave_pos GROUP BY domain_id; @@ -265,6 +268,39 @@ while (!$done) # Note that at this point, the contents of table t2, as well as the GTID # position, is non-deterministic. +# MDEV-15373 engine gtid_slave_pos table name disobeys lower-case-table-names +# This snippet verifies that engine gtid_slave_pos table is found, +# its data are up-to-date. +--write_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +wait +EOF +--connection server_2 +--shutdown_server 30 +--source include/wait_until_disconnected.inc + +--echo *** Restart the slave server to prove 'gtid_slave_pos_innodb' autodiscovery *** +--append_file $MYSQLTEST_VARDIR/tmp/mysqld.2.expect +restart: --skip-slave-start=0 +EOF + +--connection server_2 +--enable_reconnect +--source include/wait_until_connected_again.inc +SELECT max(seq_no) FROM mysql.gtid_slave_pos_InnoDB into @seq_no; + +--connection server_1 +INSERT INTO t2(a) SELECT 1+MAX(a) FROM t2; +--source include/save_master_gtid.inc + +--connection server_2 +--source include/sync_with_master_gtid.inc +if (`SELECT max(seq_no) <> @seq_no + 1 FROM mysql.gtid_slave_pos_InnoDB`) +{ + SELECT * FROM mysql.gtid_slave_pos_InnoDB; + --die Inconsistent table +} +# +# end of MDEV-15373 #--connection server_2 --source include/stop_slave.inc diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc index 70b5832b274..05dffe2c462 100644 --- a/sql/rpl_rli.cc +++ b/sql/rpl_rli.cc @@ -1780,6 +1780,7 @@ gtid_pos_auto_create_tables(rpl_slave_state::gtid_pos_table **list_ptr) p= strmake(p, plugin_name(*auto_engines)->str, FN_REFLEN - (p - buf)); table_name.str= buf; table_name.length= p - buf; + table_case_convert(const_cast<char*>(table_name.str), table_name.length); entry= rpl_global_gtid_slave_state->alloc_gtid_pos_table (&table_name, hton, rpl_slave_state::GTID_POS_AUTO_CREATE); if (!entry) diff --git a/sql/slave.cc b/sql/slave.cc index 483c4675b3b..bfa4f24e0d1 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -317,6 +317,16 @@ build_gtid_pos_create_query(THD *thd, String *query, } +/* Helper function to issue a warning by gtid_pos_table_creation(). */ +inline bool is_lower_case(const char *name) +{ + char buf[SAFE_NAME_LEN]; + strmake_buf(buf, name); + my_casedn_str(files_charset_info, buf); + + return strcmp(name, buf) == 0; +} + static int gtid_pos_table_creation(THD *thd, plugin_ref engine, LEX_CSTRING *table_name) { @@ -346,6 +356,14 @@ gtid_pos_table_creation(THD *thd, plugin_ref engine, LEX_CSTRING *table_name) FALSE, FALSE); if (unlikely(thd->is_error())) err= 1; + /* The warning is relevant to 10.3 and earlier. */ + if (!is_lower_case(const_cast<char*>(table_name->str))) + sql_print_warning("The automatically created table '%s' name is not " + "entirely in lowercase. The table name will be converted " + "to lowercase to any future upgrade to 10.4.0 and later " + "version where it will be auto-created at once " + "in lowercase.", + table_name->str); end: thd->variables.option_bits= thd_saved_option; thd->reset_query();
participants (1)
-
andrei.elkin@pp.inet.fi