summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2017-10-16 13:21:11 +0300
committerMarko Mäkelä <marko.makela@mariadb.com>2017-10-16 19:11:30 +0300
commit9a791c9c8d75116d3d15bebb4df198b122b98f97 (patch)
tree4bdb9372869bab3028df56bd4523a45b640b7d60
parent1eee3a3fb79e809943ff9e37b022660d155ad486 (diff)
downloadmariadb-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.result8
-rw-r--r--mysql-test/suite/innodb_fts/t/concurrent_insert.test20
-rw-r--r--storage/innobase/fts/fts0fts.cc25
-rw-r--r--storage/xtradb/fts/fts0fts.cc25
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);
}