summaryrefslogtreecommitdiff
path: root/sql/sql_class.cc
diff options
context:
space:
mode:
authorNikita Malyavin <nikitamalyavin@gmail.com>2021-04-06 21:31:00 +0300
committerNikita Malyavin <nikitamalyavin@gmail.com>2021-04-27 11:51:17 +0300
commit6ba5f81c7dcb133d2f4fabb7f24b76286fa868a3 (patch)
tree270cd95e7973d2d51797563b6a0c510e5d343276 /sql/sql_class.cc
parent300253acf12bf66fdea8e64abae5d717c289e559 (diff)
downloadmariadb-git-6ba5f81c7dcb133d2f4fabb7f24b76286fa868a3.tar.gz
MDEV-16962 Assertion failed in open_purge_table upon concurrent ALTER/FLUSH
So we are having a race condition of three of threads, resulting in a deadlock backoff in purge, which is unexpected. More precisely, the following happens: T1: NOCOPY ALTER TABLE begins, and eventually it holds MDL_SHARED_NO_WRITE lock; T2: FLUSH TABLES begins. it sets share->tdc->flushed = true T3: purge on a record with virtual column begins. it is going to open a table. MDL_SHARED_READ lock is acquired therefore. Since share->tdc->flushed is set, it waits for a TDC purge end. T1: is going to elevate MDL LOCK to exclusive and therefore has to set other waiters to back off. T3: receives VICTIM status, reports a DEADLOCK, sets OT_BACKOFF_AND_RETRY to Open_table_context::m_action My fix is to allow opening table in purge while flushing. It is already done the same way in other maintainance facilities like REPAIR TABLE. Another way would be making an actual backoff, but Open_table_context does not allow to distinguish it from other failure types, which still seem to be unexpected. Making this would require hacking into Open_table_context interface for no benefit, in comparison to passing MYSQL_OPEN_IGNORE_FLUSH during table open.
Diffstat (limited to 'sql/sql_class.cc')
-rw-r--r--sql/sql_class.cc2
1 files changed, 1 insertions, 1 deletions
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 047d6517a4b..ac9df47dd47 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -4424,7 +4424,7 @@ TABLE *open_purge_table(THD *thd, const char *db, size_t dblen,
DBUG_ASSERT(thd->open_tables == NULL);
DBUG_ASSERT(thd->locked_tables_mode < LTM_PRELOCKED);
- Open_table_context ot_ctx(thd, 0);
+ Open_table_context ot_ctx(thd, MYSQL_OPEN_IGNORE_FLUSH);
TABLE_LIST *tl= (TABLE_LIST*)thd->alloc(sizeof(TABLE_LIST));
tl->init_one_table(db, dblen, tb, tblen, tb, TL_READ);