1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-08 11:22:35 +03:00

Backport of revno: 2617.68.37

Bug #46654 False deadlock on concurrent DML/DDL with partitions, 
           inconsistent behavior

The problem was that if one connection is running a multi-statement 
transaction which involves a single partitioned table, and another 
connection attempts to alter the table, the first connection gets 
ER_LOCK_DEADLOCK and cannot proceed anymore, even when the ALTER TABLE 
statement in another connection has timed out or failed.

The reason for this was that the prepare phase for ALTER TABLE for 
partitioned tables removed all instances of the table from the table 
definition cache before it started waiting on the lock. The transaction 
running in the first connection would notice this and report ER_LOCK_DEADLOCK. 

This patch changes the prep_alter_part_table() ALTER TABLE code so that 
tdc_remove_table() is no longer called. Instead, only the TABLE instance
changed by prep_alter_part_table() is marked as needing reopen.

The patch also removes an unnecessary call to tdc_remove_table() from 
mysql_unpack_partition() as the changed TABLE object is destroyed by the 
caller at a later point.

Test case added in partition_sync.test.
This commit is contained in:
Jon Olav Hauglid
2009-12-10 14:26:00 +01:00
parent 28b0eeff28
commit 2945f773f2
8 changed files with 112 additions and 24 deletions

View File

@@ -4183,15 +4183,13 @@ bool mysql_unpack_partition(THD *thd,
We need to free any memory objects allocated on item_free_list
by the parser since we are keeping the old info from the first
parser call in CREATE TABLE.
We'll ensure that this object isn't put into table cache also
just to ensure we don't get into strange situations with the
item objects.
This table object can not be used any more. However, since
this is CREATE TABLE, we know that it will be destroyed by the
caller, and rely on that.
*/
thd->free_items();
part_info= thd->work_part_info;
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
table->s->db.str,
table->s->table_name.str);
*work_part_info_used= true;
}
table->part_info= part_info;
@@ -4484,17 +4482,11 @@ uint prep_alter_part_table(THD *thd, TABLE *table, Alter_info *alter_info,
/*
We are going to manipulate the partition info on the table object
so we need to ensure that the table instances cached and all other
instances are properly closed.
so we need to ensure that the table instance is removed from the
table cache.
*/
if (table->part_info)
{
pthread_mutex_lock(&LOCK_open);
tdc_remove_table(thd, TDC_RT_REMOVE_UNUSED,
table->s->db.str,
table->s->table_name.str);
pthread_mutex_unlock(&LOCK_open);
}
table->m_needs_reopen= TRUE;
thd->work_part_info= thd->lex->part_info;
if (thd->work_part_info &&