revision-id: 9fe7489a3bfd88628097e58f75516b5cad9f8dab parent(s): bd344d9f4ec384020f2133eb13f55272818340eb committer: Sergei Petrunia branch nick: mysql-5.6-rocksdb-spetrunia timestamp: 2018-06-11 19:03:40 +0300 message: Issue #834: Server crash in print_keydup_error / key_unpack or unexpected ER_DUP_KEY The issue is caused by a combination of two factors: 1. Rdb_ddl_manager::rename() loses the value of m_hidden_pk_val. new object used to get 0, which means "not loaded from the db yet". 2. ha_rocksdb::load_hidden_pk_value() uses current transaction (and its snapshot) when loading hidden PK value from disk. This may cause it to load an out-of-date value. This patch fixes #1, which is sufficient to fix the issue. (This is attempt 2, with review input addressed) --- .../suite/rocksdb/r/allow_no_primary_key.result | 25 +++++++++++++++++++ .../suite/rocksdb/t/allow_no_primary_key.test | 28 ++++++++++++++++++++++ storage/rocksdb/rdb_datadic.cc | 3 +++ 3 files changed, 56 insertions(+) diff --git a/mysql-test/suite/rocksdb/r/allow_no_primary_key.result b/mysql-test/suite/rocksdb/r/allow_no_primary_key.result index d86792a..5058934 100644 --- a/mysql-test/suite/rocksdb/r/allow_no_primary_key.result +++ b/mysql-test/suite/rocksdb/r/allow_no_primary_key.result @@ -262,3 +262,28 @@ SELECT * FROM t1; a b 36 foo DROP TABLE t1; +# +# Issue #834/MDEV-15304 ALTER TABLE table_with_hidden_pk causes Can't +# write; duplicate key in table error and/or crash +# +CREATE TABLE t1 (a INT, KEY(a)) ENGINE=RocksDB; +INSERT INTO t1 VALUES (1),(1+1); +create table t2 (a int) ENGINE=rocksdb; +insert into t2 values (10),(20),(30); +BEGIN; +select * from t2; +a +10 +20 +30 +alter table t1 force; +select * from t1; +a +insert into t1 values (100); +select * from t1; +a +1 +2 +100 +rollback; +drop table t1,t2; diff --git a/mysql-test/suite/rocksdb/t/allow_no_primary_key.test b/mysql-test/suite/rocksdb/t/allow_no_primary_key.test index 2a064dc..966a70d 100644 --- a/mysql-test/suite/rocksdb/t/allow_no_primary_key.test +++ b/mysql-test/suite/rocksdb/t/allow_no_primary_key.test @@ -96,3 +96,31 @@ DELETE FROM t1 WHERE a = 35 AND b = 'foo'; --sorted_result SELECT * FROM t1; DROP TABLE t1; + +--echo # +--echo # Issue #834/MDEV-15304 ALTER TABLE table_with_hidden_pk causes Can't +--echo # write; duplicate key in table error and/or crash +--echo # +CREATE TABLE t1 (a INT, KEY(a)) ENGINE=RocksDB; +INSERT INTO t1 VALUES (1),(1+1); +create table t2 (a int) ENGINE=rocksdb; +insert into t2 values (10),(20),(30); + +BEGIN; +select * from t2; + +connect (con1,localhost,root,,); +connection con1; +alter table t1 force; + +connection default; +select * from t1; + +connection con1; +insert into t1 values (100); +select * from t1; + +disconnect con1; +connection default; +rollback; +drop table t1,t2; diff --git a/storage/rocksdb/rdb_datadic.cc b/storage/rocksdb/rdb_datadic.cc index 2c1c97b..04c8a7c 100644 --- a/storage/rocksdb/rdb_datadic.cc +++ b/storage/rocksdb/rdb_datadic.cc @@ -4241,6 +4241,9 @@ bool Rdb_ddl_manager::rename(const std::string &from, const std::string &to, rec->m_auto_incr_val.load(std::memory_order_relaxed); new_rec->m_key_descr_arr = rec->m_key_descr_arr; + new_rec->m_hidden_pk_val = + rec->m_hidden_pk_val.load(std::memory_order_relaxed); + // so that it's not free'd when deleting the old rec rec->m_key_descr_arr = nullptr;