diff options
author | Nikita Malyavin <nikitamalyavin@gmail.com> | 2021-04-06 21:31:00 +0300 |
---|---|---|
committer | Nikita Malyavin <nikitamalyavin@gmail.com> | 2021-04-27 11:51:17 +0300 |
commit | 6ba5f81c7dcb133d2f4fabb7f24b76286fa868a3 (patch) | |
tree | 270cd95e7973d2d51797563b6a0c510e5d343276 /sql/sql_class.cc | |
parent | 300253acf12bf66fdea8e64abae5d717c289e559 (diff) | |
download | mariadb-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.cc | 2 |
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); |