diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2017-10-16 13:21:11 +0300 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2017-10-16 19:11:30 +0300 |
commit | 9a791c9c8d75116d3d15bebb4df198b122b98f97 (patch) | |
tree | 4bdb9372869bab3028df56bd4523a45b640b7d60 | |
parent | 1eee3a3fb79e809943ff9e37b022660d155ad486 (diff) | |
download | mariadb-git-9a791c9c8d75116d3d15bebb4df198b122b98f97.tar.gz |
MDEV-12676 MySQL#78423 InnoDB FTS duplicate key error
fts_get_next_doc_id(): Assign the first and subsequent FTS_DOC_ID
in the same way: by post-incrementing the cached value.
If there is a user-specified FTS_DOC_ID, do not touch the internal
sequence.
-rw-r--r-- | mysql-test/suite/innodb_fts/r/concurrent_insert.result | 8 | ||||
-rw-r--r-- | mysql-test/suite/innodb_fts/t/concurrent_insert.test | 20 | ||||
-rw-r--r-- | storage/innobase/fts/fts0fts.cc | 25 | ||||
-rw-r--r-- | storage/xtradb/fts/fts0fts.cc | 25 |
4 files changed, 54 insertions, 24 deletions
diff --git a/mysql-test/suite/innodb_fts/r/concurrent_insert.result b/mysql-test/suite/innodb_fts/r/concurrent_insert.result new file mode 100644 index 00000000000..b9798ca1a74 --- /dev/null +++ b/mysql-test/suite/innodb_fts/r/concurrent_insert.result @@ -0,0 +1,8 @@ +CREATE TABLE t1(a VARCHAR(5),FULLTEXT KEY(a)) ENGINE=InnoDB; +SET DEBUG_SYNC = 'get_next_FTS_DOC_ID SIGNAL prepared WAIT_FOR race'; +REPLACE INTO t1(a) values('aaa'); +SET DEBUG_SYNC = 'now WAIT_FOR prepared'; +REPLACE INTO t1(a) VALUES('aaa'); +SET DEBUG_SYNC = 'now SIGNAL race'; +SET DEBUG_SYNC = 'RESET'; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb_fts/t/concurrent_insert.test b/mysql-test/suite/innodb_fts/t/concurrent_insert.test new file mode 100644 index 00000000000..e5d61cd8b05 --- /dev/null +++ b/mysql-test/suite/innodb_fts/t/concurrent_insert.test @@ -0,0 +1,20 @@ +--source include/have_innodb.inc +--source include/have_debug.inc +--source include/have_debug_sync.inc + +CREATE TABLE t1(a VARCHAR(5),FULLTEXT KEY(a)) ENGINE=InnoDB; +SET DEBUG_SYNC = 'get_next_FTS_DOC_ID SIGNAL prepared WAIT_FOR race'; +--send +REPLACE INTO t1(a) values('aaa'); + +connect(dml, localhost, root, ,); +SET DEBUG_SYNC = 'now WAIT_FOR prepared'; +REPLACE INTO t1(a) VALUES('aaa'); +SET DEBUG_SYNC = 'now SIGNAL race'; +disconnect dml; + +connection default; +reap; +SET DEBUG_SYNC = 'RESET'; + +DROP TABLE t1; diff --git a/storage/innobase/fts/fts0fts.cc b/storage/innobase/fts/fts0fts.cc index bdc79203cb8..d7798f386a4 100644 --- a/storage/innobase/fts/fts0fts.cc +++ b/storage/innobase/fts/fts0fts.cc @@ -2644,22 +2644,23 @@ fts_get_next_doc_id( will consult the CONFIG table and user table to re-establish the initial value of the Doc ID */ - if (cache->first_doc_id != 0 || !fts_init_doc_id(table)) { - if (!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)) { - *doc_id = FTS_NULL_DOC_ID; - return(DB_SUCCESS); + if (!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)) { + if (cache->first_doc_id == FTS_NULL_DOC_ID) { + fts_init_doc_id(table); } + *doc_id = FTS_NULL_DOC_ID; + return(DB_SUCCESS); + } - /* Otherwise, simply increment the value in cache */ - mutex_enter(&cache->doc_id_lock); - *doc_id = ++cache->next_doc_id; - mutex_exit(&cache->doc_id_lock); - } else { - mutex_enter(&cache->doc_id_lock); - *doc_id = cache->next_doc_id; - mutex_exit(&cache->doc_id_lock); + if (cache->first_doc_id == FTS_NULL_DOC_ID) { + fts_init_doc_id(table); } + DEBUG_SYNC_C("get_next_FTS_DOC_ID"); + mutex_enter(&cache->doc_id_lock); + *doc_id = cache->next_doc_id++; + mutex_exit(&cache->doc_id_lock); + return(DB_SUCCESS); } diff --git a/storage/xtradb/fts/fts0fts.cc b/storage/xtradb/fts/fts0fts.cc index a88ff964202..27056a93dbe 100644 --- a/storage/xtradb/fts/fts0fts.cc +++ b/storage/xtradb/fts/fts0fts.cc @@ -2644,22 +2644,23 @@ fts_get_next_doc_id( will consult the CONFIG table and user table to re-establish the initial value of the Doc ID */ - if (cache->first_doc_id != 0 || !fts_init_doc_id(table)) { - if (!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)) { - *doc_id = FTS_NULL_DOC_ID; - return(DB_SUCCESS); + if (!DICT_TF2_FLAG_IS_SET(table, DICT_TF2_FTS_HAS_DOC_ID)) { + if (cache->first_doc_id == FTS_NULL_DOC_ID) { + fts_init_doc_id(table); } + *doc_id = FTS_NULL_DOC_ID; + return(DB_SUCCESS); + } - /* Otherwise, simply increment the value in cache */ - mutex_enter(&cache->doc_id_lock); - *doc_id = ++cache->next_doc_id; - mutex_exit(&cache->doc_id_lock); - } else { - mutex_enter(&cache->doc_id_lock); - *doc_id = cache->next_doc_id; - mutex_exit(&cache->doc_id_lock); + if (cache->first_doc_id == FTS_NULL_DOC_ID) { + fts_init_doc_id(table); } + DEBUG_SYNC_C("get_next_FTS_DOC_ID"); + mutex_enter(&cache->doc_id_lock); + *doc_id = cache->next_doc_id++; + mutex_exit(&cache->doc_id_lock); + return(DB_SUCCESS); } |