MDEV-15855 Deadlock between purge thread and DDL statement

Problem:
========
Truncate operation holds MDL on the table (t1) and tries to
acquire InnoDB dict_operation_lock. Purge holds dict_operation_lock
and tries to acquire MDL on the table (t1) to evaluate virtual
column expressions for indexed virtual columns.
It leads to deadlock of purge and truncate table (DDL).

Solution:
=========
If purge tries to acquire MDL on the table then it should do the following:

i) Purge should release all innodb latches (including dict_operation_lock)
before acquiring metadata lock on the table.

ii) After acquiring metadata lock on the table, it should check whether the
table was dropped or renamed. If the table is dropped then purge should
ignore the undo log record. If the table is renamed then it should
release the old MDL and acquire MDL on the new name.

iii) Once purge acquires MDL, it should use the SQL table handle for all
the remaining virtual index for the purge record.

purge_node_t: Introduce new virtual column information to know whether
the MDL was acquired successfully.

This is joint work with Marko Mäkelä.
This commit is contained in:
Thirunarayanan Balathandayuthapani 2018-07-06 17:13:53 +03:00 committed by Marko Mäkelä
commit 8b0d4cff07
14 changed files with 633 additions and 164 deletions

View file

@ -389,6 +389,32 @@ btr_pcur_commit_specify_mtr(
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
}
/** Commits the mtr and sets the clustered index pcur and secondary index
pcur latch mode to BTR_NO_LATCHES, that is, the cursor becomes detached.
Function btr_pcur_store_position should be used for both cursor before
calling this, if restoration of cursor is wanted later.
@param[in] pcur persistent cursor
@param[in] sec_pcur secondary index persistent cursor
@param[in] mtr mtr to commit */
UNIV_INLINE
void
btr_pcurs_commit_specify_mtr(
btr_pcur_t* pcur,
btr_pcur_t* sec_pcur,
mtr_t* mtr)
{
ut_ad(pcur->pos_state == BTR_PCUR_IS_POSITIONED);
ut_ad(sec_pcur->pos_state == BTR_PCUR_IS_POSITIONED);
pcur->latch_mode = BTR_NO_LATCHES;
sec_pcur->latch_mode = BTR_NO_LATCHES;
mtr_commit(mtr);
pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
sec_pcur->pos_state = BTR_PCUR_WAS_POSITIONED;
}
/**************************************************************//**
Sets the old_rec_buf field to NULL. */
UNIV_INLINE