From 3d211f39819db045c4992dcf1aab1c2473b56c66 Mon Sep 17 00:00:00 2001 From: Luis Soares Date: Sun, 27 Sep 2009 22:02:47 +0100 Subject: [PATCH] BUG#47312: RBR: Disabling key on slave breaks replication: HA_ERR_WRONG_INDEX In RBR, disabling keys on slave table will break replication when updating or deleting a record. When the slave thread tries to find the row, by searching in the storage engine, it checks whether the table has a key or not. If it has one, then the slave thread uses it to search the record. Nonetheless, the slave only checks whether the key exists or not, it does not verify if it is active. Should the key be disabled (eg, DBA has issued an ALTER TABLE ... DISABLE KEYS) then it will result in error: HA_ERR_WRONG_INDEX. This patch addresses this issue by making the slave thread also check whether the key is active or not before actually using it. --- .../rpl/r/rpl_row_disabled_slave_key.result | 26 +++++++ .../rpl/t/rpl_row_disabled_slave_key.test | 73 +++++++++++++++++++ sql/log_event.cc | 4 +- 3 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 mysql-test/suite/rpl/r/rpl_row_disabled_slave_key.result create mode 100644 mysql-test/suite/rpl/t/rpl_row_disabled_slave_key.test diff --git a/mysql-test/suite/rpl/r/rpl_row_disabled_slave_key.result b/mysql-test/suite/rpl/r/rpl_row_disabled_slave_key.result new file mode 100644 index 00000000000..01e3dfd6508 --- /dev/null +++ b/mysql-test/suite/rpl/r/rpl_row_disabled_slave_key.result @@ -0,0 +1,26 @@ +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +SET SQL_LOG_BIN=0; +CREATE TABLE t (a int, b int, c int, key(b)); +SET SQL_LOG_BIN=1; +CREATE TABLE t (a int, b int, c int); +INSERT INTO t VALUES (1,2,4); +INSERT INTO t VALUES (4,3,4); +DELETE FROM t; +DROP TABLE t; +stop slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +reset master; +reset slave; +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +start slave; +CREATE TABLE t (a int, b int, c int, key(b)); +ALTER TABLE t DISABLE KEYS; +INSERT INTO t VALUES (1,2,4); +INSERT INTO t VALUES (4,3,4); +DELETE FROM t; +DROP TABLE t; diff --git a/mysql-test/suite/rpl/t/rpl_row_disabled_slave_key.test b/mysql-test/suite/rpl/t/rpl_row_disabled_slave_key.test new file mode 100644 index 00000000000..1d7e134f4f4 --- /dev/null +++ b/mysql-test/suite/rpl/t/rpl_row_disabled_slave_key.test @@ -0,0 +1,73 @@ +# BUG#47312: RBR: Disabling key on slave breaks replication: +# HA_ERR_WRONG_INDEX +# +# Description +# =========== +# +# This test case checks whether disabling a key on a slave breaks +# replication or not. +# +# Case #1, shows that while not using ALTER TABLE... DISABLE KEYS and +# the slave has no key defined while the master has one, replication +# won't break. +# +# Case #2, shows that before patch for BUG#47312, if defining key on +# slave table, and later disable it, replication would break. This +# has been fixed. +# + +-- source include/master-slave.inc +-- source include/have_binlog_format_row.inc + +# +# Case #1: master has key, but slave has not. +# Replication does not break. +# + +SET SQL_LOG_BIN=0; +CREATE TABLE t (a int, b int, c int, key(b)); +SET SQL_LOG_BIN=1; + +-- connection slave + +CREATE TABLE t (a int, b int, c int); + +-- connection master + +INSERT INTO t VALUES (1,2,4); +INSERT INTO t VALUES (4,3,4); +DELETE FROM t; + +-- sync_slave_with_master + +-- connection master +DROP TABLE t; + +-- sync_slave_with_master + +# +# Case #2: master has key, slave also has one, +# but it gets disabled sometime. +# Replication does not break anymore. +# +-- source include/master-slave-reset.inc +-- connection master + +CREATE TABLE t (a int, b int, c int, key(b)); + +-- sync_slave_with_master + +ALTER TABLE t DISABLE KEYS; + +-- connection master + +INSERT INTO t VALUES (1,2,4); +INSERT INTO t VALUES (4,3,4); +DELETE FROM t; + +-- sync_slave_with_master + +-- connection master +DROP TABLE t; + +-- sync_slave_with_master diff --git a/sql/log_event.cc b/sql/log_event.cc index 08fe3aba8ed..3c584011bfb 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -8835,11 +8835,11 @@ int Rows_log_event::find_row(const Relay_log_info *rli) */ store_record(table,record[1]); - if (table->s->keys > 0) + if (table->s->keys > 0 && table->s->keys_in_use.is_set(0)) { DBUG_PRINT("info",("locating record using primary key (index_read)")); - /* We have a key: search the table using the index */ + /* The 0th key is active: search the table using the index */ if (!table->file->inited && (error= table->file->ha_index_init(0, FALSE))) { DBUG_PRINT("info",("ha_index_init returns error %d",error));