From e46d0aead03c2c719a05c97d2ce7f94eee51a9f6 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 30 Nov 2010 10:47:08 +0100 Subject: [PATCH 1/2] Bug#54201: "SET INSERT_ID" event must be ignored if corresponding event is ignored An INSERT query log event is preceeded by an INSERT_ID intvar event if the INSERT allocates a new auto_increment value. But if we ignore the INSERT due to --replicate-ignore-table or similar, then the INSERT_ID event is still executed, and the set value of INSERT_ID lingers around in the slave sql thread THD object indefinitely until the next INSERT that happens to need allocation of a new auto_increment value. Normally this does not cause problems as such following INSERT would normally come with its own INSERT_ID event. In this bug, the user had a trigger on the slave which was missing on the master, and this trigger had an INSERT which could be affected. In any case, it seems better to not leave a stray INSERT_ID hanging around in the sql thread THD indefinitely. Note that events can also be skipped from apply_event_and_update_pos(); however it is not possible in that code to skip the INSERT without also skipping the INSERT_ID event. --- .../extra/rpl_tests/rpl_auto_increment.test | 56 +++++++++++++++++++ .../suite/rpl/r/rpl_auto_increment.result | 29 ++++++++++ .../suite/rpl/t/rpl_auto_increment-slave.opt | 1 + sql/log_event.cc | 13 +++++ 4 files changed, 99 insertions(+) create mode 100644 mysql-test/suite/rpl/t/rpl_auto_increment-slave.opt diff --git a/mysql-test/extra/rpl_tests/rpl_auto_increment.test b/mysql-test/extra/rpl_tests/rpl_auto_increment.test index 86885a14f94..06e3a154bc3 100644 --- a/mysql-test/extra/rpl_tests/rpl_auto_increment.test +++ b/mysql-test/extra/rpl_tests/rpl_auto_increment.test @@ -241,3 +241,59 @@ DROP TABLE t1; DROP TABLE t2; SET SQL_MODE=''; sync_slave_with_master; + +# +# Bug#54201: "SET INSERT_ID" event must be ignored if corresponding event is +# ignored. +# +connection master; + +CREATE TABLE t1(s VARCHAR(10)) ENGINE=myisam; +# -slave.opt has --replicate-ignore-table=test.t_ignored1 +CREATE TABLE t_ignored1(id INT AUTO_INCREMENT PRIMARY KEY) ENGINE=myisam; + +connection slave; + +CREATE TABLE test.slave_only(id INT AUTO_INCREMENT PRIMARY KEY) ENGINE=myisam; +INSERT INTO slave_only VALUES(NULL); +CREATE TRIGGER t1_update AFTER UPDATE ON t1 FOR EACH ROW INSERT INTO slave_only VALUES(NULL); + +connection master; + +INSERT INTO t_ignored1 VALUES(NULL); +INSERT INTO t1 VALUES('s'); +UPDATE t1 SET s='s1'; + +# With Bug#54201, slave stops with duplicate key error here due to trigger +# using the insert_id from insert on master into t1_ignored1 +sync_slave_with_master; +connection slave; +SELECT * FROM t1; + +connection master; +CREATE TABLE t_ignored2(id INT AUTO_INCREMENT PRIMARY KEY) ENGINE=myisam; +sync_slave_with_master; + +connection slave; +STOP SLAVE; +# Ignore the next INSERT into t_ignored2 and the INSERT_ID event just before it. +SET GLOBAL sql_slave_skip_counter = 2; +START SLAVE; + +connection master; +INSERT INTO t_ignored2 VALUES(NULL); +UPDATE t1 SET s='s2'; +sync_slave_with_master; + +connection slave; +SELECT * FROM t1; +SHOW TABLES LIKE 't\_ignored_'; +SELECT * FROM t_ignored2; +DROP TABLE slave_only; + +connection master; +DROP TABLE t1; +DROP TABLE t_ignored1; +DROP TABLE t_ignored2; + +sync_slave_with_master; diff --git a/mysql-test/suite/rpl/r/rpl_auto_increment.result b/mysql-test/suite/rpl/r/rpl_auto_increment.result index 831e9b5c8b5..9fcd9bbd54c 100644 --- a/mysql-test/suite/rpl/r/rpl_auto_increment.result +++ b/mysql-test/suite/rpl/r/rpl_auto_increment.result @@ -312,3 +312,32 @@ Comparing tables master:test.t2 and slave:test.t2 DROP TABLE t1; DROP TABLE t2; SET SQL_MODE=''; +CREATE TABLE t1(s VARCHAR(10)) ENGINE=myisam; +CREATE TABLE t_ignored1(id INT AUTO_INCREMENT PRIMARY KEY) ENGINE=myisam; +CREATE TABLE test.slave_only(id INT AUTO_INCREMENT PRIMARY KEY) ENGINE=myisam; +INSERT INTO slave_only VALUES(NULL); +CREATE TRIGGER t1_update AFTER UPDATE ON t1 FOR EACH ROW INSERT INTO slave_only VALUES(NULL); +INSERT INTO t_ignored1 VALUES(NULL); +INSERT INTO t1 VALUES('s'); +UPDATE t1 SET s='s1'; +SELECT * FROM t1; +s +s1 +CREATE TABLE t_ignored2(id INT AUTO_INCREMENT PRIMARY KEY) ENGINE=myisam; +STOP SLAVE; +SET GLOBAL sql_slave_skip_counter = 2; +START SLAVE; +INSERT INTO t_ignored2 VALUES(NULL); +UPDATE t1 SET s='s2'; +SELECT * FROM t1; +s +s2 +SHOW TABLES LIKE 't\_ignored_'; +Tables_in_test (t\_ignored_) +t_ignored2 +SELECT * FROM t_ignored2; +id +DROP TABLE slave_only; +DROP TABLE t1; +DROP TABLE t_ignored1; +DROP TABLE t_ignored2; diff --git a/mysql-test/suite/rpl/t/rpl_auto_increment-slave.opt b/mysql-test/suite/rpl/t/rpl_auto_increment-slave.opt new file mode 100644 index 00000000000..79ed6f96a4a --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_auto_increment-slave.opt @@ -0,0 +1 @@ +--replicate-ignore-table=test.t_ignored1 diff --git a/sql/log_event.cc b/sql/log_event.cc index 3969b6b6f4d..c3e5a831ab3 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -3307,6 +3307,19 @@ START SLAVE; . Query: '%s'", expected_error, thd->query()); /* If the query was not ignored, it is printed to the general log */ if (!thd->is_error() || thd->main_da.sql_errno() != ER_SLAVE_IGNORED_TABLE) general_log_write(thd, COM_QUERY, thd->query(), thd->query_length()); + else + { + /* + Bug#54201: If we skip an INSERT query that uses auto_increment, then we + should reset any @@INSERT_ID set by an Intvar_log_event associated with + the query; otherwise the @@INSERT_ID will linger until the next INSERT + that uses auto_increment and may affect extra triggers on the slave etc. + + We reset INSERT_ID unconditionally; it is probably cheaper than + checking if it is necessary. + */ + thd->auto_inc_intervals_forced.empty(); + } compare_errors: From 34fa79e9b11873d97f6e0088989cc8408c6578c5 Mon Sep 17 00:00:00 2001 From: Michael Widenius Date: Wed, 1 Dec 2010 22:18:03 +0200 Subject: [PATCH 2/2] Fixed failures in buildbot mysql-test/suite/innodb_plugin/t/innodb_bug38231.test: Sometimes you get a timeout here; Disable the not fatal error message. storage/xtradb/sync/sync0rw.c: Disable compiler warning --- mysql-test/suite/innodb_plugin/t/innodb_bug38231.test | 1 + storage/xtradb/sync/sync0rw.c | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/mysql-test/suite/innodb_plugin/t/innodb_bug38231.test b/mysql-test/suite/innodb_plugin/t/innodb_bug38231.test index be588474bc1..05e39cc16ea 100644 --- a/mysql-test/suite/innodb_plugin/t/innodb_bug38231.test +++ b/mysql-test/suite/innodb_plugin/t/innodb_bug38231.test @@ -73,6 +73,7 @@ UNLOCK TABLES; -- connection con2 -- reap +-- error 0, 1205 UNLOCK TABLES; -- connection con3 diff --git a/storage/xtradb/sync/sync0rw.c b/storage/xtradb/sync/sync0rw.c index 5dc6b28d4bf..f1018522fdf 100644 --- a/storage/xtradb/sync/sync0rw.c +++ b/storage/xtradb/sync/sync0rw.c @@ -247,10 +247,11 @@ rw_lock_create_func( lock->mutex.cmutex_name = cmutex_name; ut_d(lock->mutex.mutex_type = 1); -#else /* INNODB_RW_LOCKS_USE_ATOMICS */ +#endif /* INNODB_RW_LOCKS_USE_ATOMICS */ +#if defined(INNODB_RW_LOCKS_USE_ATOMICS) || !defined(UNIV_DEBUG) (void) cfile_name; (void) cline; -#endif /* INNODB_RW_LOCKS_USE_ATOMICS */ +#endif lock->lock_word = X_LOCK_DECR; lock->waiters = 0;