Skip to content
Permalink
Browse files
MDEV-16855 Fix fts_sync_synchronization in InnoDB
This is a backport of the following fix from MySQL 5.7.23.
Some code refactoring has been omitted, and the test case has
been adapted to MariaDB.

commit 7a689acaa65e9d602575f7aa53fe36a64a07460f
Author: Krzysztof Kapuścik <krzysztof.kapuscik@oracle.com>
Date:   Tue Mar 13 12:34:03 2018 +0100

Bug#27082268 Invalid FTS sync synchronization

The fix closes two issues:
Bug #27082268 - INNODB: FAILING ASSERTION: SYM_NODE->TABLE != NULL DURING FTS SYNC
Bug #27095935 - DEADLOCK BETWEEN FTS_DROP_INDEX AND FTS_OPTIMIZE_SYNC_TABLE

Both issues were related to a FTS cache sync being done during
operations that perfomed DDL actions on internal FTS tables
(ALTER TABLE, TRUNCATE). In some cases the FTS tables and/or
internal cache structures could get removed while still being
used to perform FTS synchronization leading to crashes. In other
the sync operations could not get finishes as it was waiting for
dict lock which was taken by thread waiting for the background
sync to be finished.

The changes done includes:
- Stopping background operations during ALTER TABLE and TRUNCATE.
- Removal of unused code in FTS.
- Cleanup of FTS sync related code to make it more readable and
easier to maintain.

RB#18262
  • Loading branch information
dr-m committed Jul 30, 2018
1 parent 5ed2da9 commit e52315a
Show file tree
Hide file tree
Showing 14 changed files with 450 additions and 440 deletions.
@@ -0,0 +1,117 @@
CREATE TABLE t1 (
id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
value VARCHAR(1024)
) ENGINE=InnoDB;
CREATE FULLTEXT INDEX idx1 ON t1(value);
Warnings:
Warning 124 InnoDB rebuilding table to add column FTS_DOC_ID
SET @save_debug = @@GLOBAL.debug_dbug;
SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_sync_before_syncing,ib_trunc_sleep_before_fts_cache_clear';
INSERT INTO t1 (value) VALUES
('By default or with the IN NATURAL LANGUAGE MODE modifier')
;
TRUNCATE TABLE t1;
DROP TABLE t1;
SET GLOBAL debug_dbug = @save_debug;
CREATE TABLE t1 (
id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
value VARCHAR(1024)
) ENGINE=InnoDB;
CREATE FULLTEXT INDEX idx1 ON t1(value);
Warnings:
Warning 124 InnoDB rebuilding table to add column FTS_DOC_ID
SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_write_words_before_select_index,ib_trunc_sleep_before_fts_cache_clear';
INSERT INTO t1 (value) VALUES
('By default or with the IN NATURAL LANGUAGE MODE modifier'),
('performs a natural language search for a string'),
('collection is a set of one or more columns included'),
('returns a relevance value; that is, a similarity measure'),
('and the text in that row in the columns named in'),
('By default, the search is performed in case-insensitive'),
('sensitive full-text search, use a binary collation '),
('example, a column that uses the latin1 character'),
('collation of latin1_bin to make it case sensitive')
;
TRUNCATE TABLE t1;
DROP TABLE t1;
SET GLOBAL debug_dbug = @save_debug;
CREATE TABLE t1 (
value VARCHAR(1024)
) ENGINE=InnoDB;
CREATE FULLTEXT INDEX idx1 ON t1(value);
Warnings:
Warning 124 InnoDB rebuilding table to add column FTS_DOC_ID
SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep';
INSERT INTO t1 (value) VALUES
('By default or with the IN NATURAL LANGUAGE MODE modifier'),
('performs a natural language search for a string'),
('collection is a set of one or more columns included'),
('returns a relevance value; that is, a similarity measure'),
('and the text in that row in the columns named in'),
('By default, the search is performed in case-insensitive'),
('sensitive full-text search, use a binary collation '),
('example, a column that uses the latin1 character'),
('collation of latin1_bin to make it case sensitive')
;
DROP INDEX idx1 ON t1;
DROP TABLE t1;
SET GLOBAL debug_dbug = @save_debug;
CREATE TABLE t1 (
value VARCHAR(1024)
) ENGINE=InnoDB;
CREATE FULLTEXT INDEX idx1 ON t1(value);
Warnings:
Warning 124 InnoDB rebuilding table to add column FTS_DOC_ID
SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep';
INSERT INTO t1 (value) VALUES
('By default or with the IN NATURAL LANGUAGE MODE modifier'),
('performs a natural language search for a string'),
('collection is a set of one or more columns included'),
('returns a relevance value; that is, a similarity measure'),
('and the text in that row in the columns named in'),
('By default, the search is performed in case-insensitive'),
('sensitive full-text search, use a binary collation '),
('example, a column that uses the latin1 character'),
('collation of latin1_bin to make it case sensitive')
;
ALTER TABLE t1
DROP INDEX idx1,
ALGORITHM=INPLACE;
DROP TABLE t1;
SET GLOBAL debug_dbug = @save_debug;
CREATE TABLE t1 (
value VARCHAR(1024)
) ENGINE=InnoDB;
CREATE FULLTEXT INDEX idx1 ON t1(value);
Warnings:
Warning 124 InnoDB rebuilding table to add column FTS_DOC_ID
SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep';
INSERT INTO t1 (value) VALUES
('example, a column that uses the latin1 character'),
('collation of latin1_bin to make it case sensitive')
;
ALTER TABLE t1
DROP INDEX idx1,
ALGORITHM=COPY;
DROP TABLE t1;
SET GLOBAL debug_dbug = @save_debug;
CREATE TABLE t1 (
id1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
value VARCHAR(1024)
) ENGINE=InnoDB;
CREATE FULLTEXT INDEX idx1 ON t1(value);
Warnings:
Warning 124 InnoDB rebuilding table to add column FTS_DOC_ID
SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep';
INSERT INTO t1 (value) VALUES
('example, a column that uses the latin1 character'),
('collation of latin1_bin to make it case sensitive')
;
ALTER TABLE t1
DROP COLUMN id1,
ADD COLUMN id2 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
DROP INDEX idx1,
ADD FULLTEXT INDEX idx2(value),
ALGORITHM=INPLACE;
DROP TABLE t1;
SET GLOBAL debug_dbug = @save_debug;
@@ -0,0 +1,177 @@
#
# BUG#27082268 FTS synchronization issues
#

--source include/have_innodb.inc
--source include/have_debug.inc

#--------------------------------------
# Check FTS_sync vs TRUNCATE (1)
#--------------------------------------

CREATE TABLE t1 (
id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
value VARCHAR(1024)
) ENGINE=InnoDB;

CREATE FULLTEXT INDEX idx1 ON t1(value);

SET @save_debug = @@GLOBAL.debug_dbug;
SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_sync_before_syncing,ib_trunc_sleep_before_fts_cache_clear';

INSERT INTO t1 (value) VALUES
('By default or with the IN NATURAL LANGUAGE MODE modifier')
;

TRUNCATE TABLE t1;

DROP TABLE t1;

SET GLOBAL debug_dbug = @save_debug;

#--------------------------------------
# Check FTS sync vs DROP INDEX (2)
#--------------------------------------

CREATE TABLE t1 (
id INT AUTO_INCREMENT NOT NULL PRIMARY KEY,
value VARCHAR(1024)
) ENGINE=InnoDB;

CREATE FULLTEXT INDEX idx1 ON t1(value);

SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_write_words_before_select_index,ib_trunc_sleep_before_fts_cache_clear';

INSERT INTO t1 (value) VALUES
('By default or with the IN NATURAL LANGUAGE MODE modifier'),
('performs a natural language search for a string'),
('collection is a set of one or more columns included'),
('returns a relevance value; that is, a similarity measure'),
('and the text in that row in the columns named in'),
('By default, the search is performed in case-insensitive'),
('sensitive full-text search, use a binary collation '),
('example, a column that uses the latin1 character'),
('collation of latin1_bin to make it case sensitive')
;

TRUNCATE TABLE t1;

DROP TABLE t1;

SET GLOBAL debug_dbug = @save_debug;

#--------------------------------------
# Check FTS sync vs DROP INDEX
#--------------------------------------

CREATE TABLE t1 (
value VARCHAR(1024)
) ENGINE=InnoDB;

CREATE FULLTEXT INDEX idx1 ON t1(value);

SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep';

INSERT INTO t1 (value) VALUES
('By default or with the IN NATURAL LANGUAGE MODE modifier'),
('performs a natural language search for a string'),
('collection is a set of one or more columns included'),
('returns a relevance value; that is, a similarity measure'),
('and the text in that row in the columns named in'),
('By default, the search is performed in case-insensitive'),
('sensitive full-text search, use a binary collation '),
('example, a column that uses the latin1 character'),
('collation of latin1_bin to make it case sensitive')
;

DROP INDEX idx1 ON t1;

DROP TABLE t1;

SET GLOBAL debug_dbug = @save_debug;

#--------------------------------------
# Check FTS sync vs ALTER TABLE DROP INDEX (INPLACE)
#--------------------------------------

CREATE TABLE t1 (
value VARCHAR(1024)
) ENGINE=InnoDB;

CREATE FULLTEXT INDEX idx1 ON t1(value);

SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep';

INSERT INTO t1 (value) VALUES
('By default or with the IN NATURAL LANGUAGE MODE modifier'),
('performs a natural language search for a string'),
('collection is a set of one or more columns included'),
('returns a relevance value; that is, a similarity measure'),
('and the text in that row in the columns named in'),
('By default, the search is performed in case-insensitive'),
('sensitive full-text search, use a binary collation '),
('example, a column that uses the latin1 character'),
('collation of latin1_bin to make it case sensitive')
;

ALTER TABLE t1
DROP INDEX idx1,
ALGORITHM=INPLACE;

DROP TABLE t1;

SET GLOBAL debug_dbug = @save_debug;

#--------------------------------------
# Check FTS sync vs ALTER TABLE DROP INDEX (COPY)
#--------------------------------------

CREATE TABLE t1 (
value VARCHAR(1024)
) ENGINE=InnoDB;

CREATE FULLTEXT INDEX idx1 ON t1(value);

SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep';

INSERT INTO t1 (value) VALUES
('example, a column that uses the latin1 character'),
('collation of latin1_bin to make it case sensitive')
;

ALTER TABLE t1
DROP INDEX idx1,
ALGORITHM=COPY;

DROP TABLE t1;

SET GLOBAL debug_dbug = @save_debug;

#--------------------------------------
# Check FTS sync vs ALTER TABLE (INPLACE, new cluster)
#--------------------------------------

CREATE TABLE t1 (
id1 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
value VARCHAR(1024)
) ENGINE=InnoDB;

CREATE FULLTEXT INDEX idx1 ON t1(value);

SET GLOBAL debug_dbug = '+d,fts_instrument_sync_request,fts_instrument_msg_sync_sleep';

INSERT INTO t1 (value) VALUES
('example, a column that uses the latin1 character'),
('collation of latin1_bin to make it case sensitive')
;

ALTER TABLE t1
DROP COLUMN id1,
ADD COLUMN id2 INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
DROP INDEX idx1,
ADD FULLTEXT INDEX idx2(value),
ALGORITHM=INPLACE;

DROP TABLE t1;

SET GLOBAL debug_dbug = @save_debug;
@@ -268,7 +268,7 @@ FTS auxiliary INDEX table and clear the cache at the end.
@param[in,out] sync sync state
@param[in] unlock_cache whether unlock cache lock when write node
@param[in] wait whether wait when a sync is in progress
@param[in] has_dict whether has dict operation lock
@param[in] has_dict whether has dict operation lock
@return DB_SUCCESS if all OK */
static
dberr_t
@@ -3961,6 +3961,9 @@ fts_sync_write_words(

word = rbt_value(fts_tokenizer_word_t, rbt_node);

DBUG_EXECUTE_IF("fts_instrument_write_words_before_select_index",
os_thread_sleep(300000););

selected = fts_select_index(
index_cache->charset, word->text.f_str,
word->text.f_len);
@@ -4525,7 +4528,7 @@ FTS auxiliary INDEX table and clear the cache at the end.
@param[in,out] sync sync state
@param[in] unlock_cache whether unlock cache lock when write node
@param[in] wait whether wait when a sync is in progress
@param[in] has_dict whether has dict operation lock
@param[in] has_dict whether has dict operation lock
@return DB_SUCCESS if all OK */
static
dberr_t
@@ -4587,15 +4590,13 @@ fts_sync(
continue;
}

DBUG_EXECUTE_IF("fts_instrument_sync_before_syncing",
os_thread_sleep(300000););
index_cache->index->index_fts_syncing = true;
DBUG_EXECUTE_IF("fts_instrument_sync_sleep_drop_waits",
os_thread_sleep(10000000);
);

error = fts_sync_index(sync, index_cache);

if (error != DB_SUCCESS && !sync->interrupted) {

if (error != DB_SUCCESS) {
goto end_sync;
}
}
@@ -4630,8 +4631,8 @@ fts_sync(
}

rw_lock_x_lock(&cache->lock);
/* Clear fts syncing flags of any indexes incase sync is
interrupeted */
/* Clear fts syncing flags of any indexes in case sync is
interrupted */
for (i = 0; i < ib_vector_size(cache->indexes); ++i) {
static_cast<fts_index_cache_t*>(
ib_vector_get(cache->indexes, i))

0 comments on commit e52315a

Please sign in to comment.