From 776e5acf73ae2517593f739fc4b553d6c816049e Mon Sep 17 00:00:00 2001 From: "George O. Lorch III" Date: Tue, 13 Nov 2018 12:03:54 -0700 Subject: [PATCH] PS-4744 : crash after alter table drop index is executed on slave - Under a specific situation on a slave, when binlog is off and log_slave_updates=0, rocksdb_prepare gets called after an external_lock(F_UNLCK) is called. During the F_UNLCK processing, the current Rdb_transaction is committed and cleared, leaving nothing to do or work with in the rocksdb_prepare call. - This change solves the issue by implementing the same behavior that TokuDB has. That is to check if there is an active transaction at the top of the prepare call and exit immediately with HA_EXIT_SUCCESS if there nothing to prepare. This prevents falling into code that assumes that there is an active transaction and tries to interact with the (missing) transaction instance. - Added new test that would segfault the slave when configured correctly and the slave applier exectues a specific ALTER TABLE. --- ...ksdb_row_alter_table_drop_index_slave.result | 11 +++++++++++ ..._row_alter_table_drop_index_slave-master.opt | 1 + ...b_row_alter_table_drop_index_slave-slave.opt | 1 + ...ocksdb_row_alter_table_drop_index_slave.test | 17 +++++++++++++++++ storage/rocksdb/ha_rocksdb.cc | 4 ++++ 5 files changed, 34 insertions(+) create mode 100644 mysql-test/suite/rocksdb.rpl/r/rpl_rocksdb_row_alter_table_drop_index_slave.result create mode 100644 mysql-test/suite/rocksdb.rpl/t/rpl_rocksdb_row_alter_table_drop_index_slave-master.opt create mode 100644 mysql-test/suite/rocksdb.rpl/t/rpl_rocksdb_row_alter_table_drop_index_slave-slave.opt create mode 100644 mysql-test/suite/rocksdb.rpl/t/rpl_rocksdb_row_alter_table_drop_index_slave.test diff --git a/mysql-test/suite/rocksdb.rpl/r/rpl_rocksdb_row_alter_table_drop_index_slave.result b/mysql-test/suite/rocksdb.rpl/r/rpl_rocksdb_row_alter_table_drop_index_slave.result new file mode 100644 index 000000000000..39b18613c988 --- /dev/null +++ b/mysql-test/suite/rocksdb.rpl/r/rpl_rocksdb_row_alter_table_drop_index_slave.result @@ -0,0 +1,11 @@ +include/master-slave.inc +Warnings: +Note #### Sending passwords in plain text without SSL/TLS is extremely insecure. +Note #### Storing MySQL user name or password information in the master info repository is not secure and is therefore not recommended. Please consider using the USER and PASSWORD connection options for START SLAVE; see the 'START SLAVE Syntax' in the MySQL Manual for more information. +[connection master] +CREATE TABLE t1(a INT PRIMARY KEY, b INT, KEY s_k(b)) ENGINE=ROCKSDB; +INSERT INTO t1 VALUES(1,2); +ALTER TABLE t1 DROP KEY s_k; +include/sync_slave_sql_with_master.inc +DROP TABLE t1; +include/rpl_end.inc diff --git a/mysql-test/suite/rocksdb.rpl/t/rpl_rocksdb_row_alter_table_drop_index_slave-master.opt b/mysql-test/suite/rocksdb.rpl/t/rpl_rocksdb_row_alter_table_drop_index_slave-master.opt new file mode 100644 index 000000000000..f1cd1aa27bc1 --- /dev/null +++ b/mysql-test/suite/rocksdb.rpl/t/rpl_rocksdb_row_alter_table_drop_index_slave-master.opt @@ -0,0 +1 @@ +--binlog_format=row --gtid_mode=ON --enforce_gtid_consistency=ON --log-slave-updates=0 diff --git a/mysql-test/suite/rocksdb.rpl/t/rpl_rocksdb_row_alter_table_drop_index_slave-slave.opt b/mysql-test/suite/rocksdb.rpl/t/rpl_rocksdb_row_alter_table_drop_index_slave-slave.opt new file mode 100644 index 000000000000..07806dd48e70 --- /dev/null +++ b/mysql-test/suite/rocksdb.rpl/t/rpl_rocksdb_row_alter_table_drop_index_slave-slave.opt @@ -0,0 +1 @@ +--gtid_mode=ON --enforce_gtid_consistency=ON --skip-log-bin --log-slave-updates=0 diff --git a/mysql-test/suite/rocksdb.rpl/t/rpl_rocksdb_row_alter_table_drop_index_slave.test b/mysql-test/suite/rocksdb.rpl/t/rpl_rocksdb_row_alter_table_drop_index_slave.test new file mode 100644 index 000000000000..b28cdccd2721 --- /dev/null +++ b/mysql-test/suite/rocksdb.rpl/t/rpl_rocksdb_row_alter_table_drop_index_slave.test @@ -0,0 +1,17 @@ +--source include/not_group_replication_plugin.inc +--source include/have_binlog_format_row.inc +--source include/have_rocksdb.inc +--source include/master-slave.inc + +connection master; +CREATE TABLE t1(a INT PRIMARY KEY, b INT, KEY s_k(b)) ENGINE=ROCKSDB; + +INSERT INTO t1 VALUES(1,2); + +ALTER TABLE t1 DROP KEY s_k; + +--source include/sync_slave_sql_with_master.inc +connection master; +DROP TABLE t1; + +--source include/rpl_end.inc diff --git a/storage/rocksdb/ha_rocksdb.cc b/storage/rocksdb/ha_rocksdb.cc index 905bc7bfda25..c21cb628fb6c 100644 --- a/storage/rocksdb/ha_rocksdb.cc +++ b/storage/rocksdb/ha_rocksdb.cc @@ -3068,6 +3068,10 @@ static bool rocksdb_flush_wal(handlerton *const hton static int rocksdb_prepare(handlerton *const hton, THD *const thd, bool prepare_tx) { Rdb_transaction *&tx = get_tx_from_thd(thd); + if (!tx->is_tx_started()) { + // nothing to prepare + return HA_EXIT_SUCCESS; + } if (!tx->can_prepare()) { return HA_EXIT_FAILURE; }