Description:
Query tables such as innodb_ft_* concurrently with operations such as drop and truncate may cause deadlock.
Simple analysis:
For example, let's analyze the function `i_s_fts_index_table_fill` (query INNODB_FT_INDEX_TABLE)
We can see that [dict_operation_lock] will be held first, and then dict_table_t will be obtained. The process of obtaining dict_table_t requires requesting [MDL].
When performing operations such as drop or truncate, we will first hold the [MDL]and then request [dict_operation_lock]. Therefore, deadlock occurs.
How to repeat:
1. Add DEBUG_SYNC_C in function `i_s_fts_index_table_fill` like:
diff --git a/storage/innobase/handler/i_s.cc b/storage/innobase/handler/i_s.cc
index 97dbc906fd7..f760b637d1f 100644
--- a/storage/innobase/handler/i_s.cc
+++ b/storage/innobase/handler/i_s.cc
@@ -3131,6 +3131,8 @@ static int i_s_fts_index_table_fill(
/* Prevent DDL to drop fts aux tables. */
rw_lock_s_lock(dict_operation_lock, UT_LOCATION_HERE);
+ DEBUG_SYNC_C("i_s_fts_acquire_dict_opt_lock");
+
user_table =
dd_table_open_on_name(thd, &mdl, local_name, false, DICT_ERR_IGNORE_NONE);
2. Run mtr with the follow case:
--connect(con1,localhost,root)
--connect(con2,localhost,root)
connection con1;
CREATE TABLE t1 (
id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
title VARCHAR(200),
content TEXT, FULLTEXT INDEX ft_content (content) ) ENGINE=InnoDB;
set global innodb_ft_aux_table='test/t1';
set debug_sync='i_s_fts_acquire_dict_opt_lock wait_for c1';
--send select * from information_schema.INNODB_FT_INDEX_TABLE
connection con2;
--send DROP TABLE t1;
connection default;
set debug_sync='now signal c1';
--echo deadlock happen