1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

Backport of revno: 2617.71.1

Bug#42546 Backup: RESTORE fails, thinking it finds an existing table

The problem occured when a MDL locking conflict happened for a non-existent 
table between a CREATE and a INSERT statement. The code for CREATE 
interpreted this lock conflict to mean that the table existed, 
which meant that the statement failed when it should not have.
The problem could occur for CREATE TABLE, CREATE TABLE LIKE and
ALTER TABLE RENAME.

This patch fixes the problem for CREATE TABLE and CREATE TABLE LIKE.
It is based on code backported from the mysql-6.1-fk tree written
by Dmitry Lenev. CREATE now uses normal open_and_lock_tables() code 
to acquire exclusive locks. This means that for the test case in the bug 
description, CREATE will wait until INSERT completes so that it can 
get the exclusive lock. This resolves the reported bug.

The patch also prohibits CREATE TABLE and CREATE TABLE LIKE under 
LOCK TABLES. Note that this is an incompatible change and must 
be reflected in the documentation. Affected test cases have been
updated.

mdl_sync.test contains tests for CREATE TABLE and CREATE TABLE LIKE.

Fixing the issue for ALTER TABLE RENAME is beyond the scope of this
patch. ALTER TABLE cannot be prohibited from working under LOCK TABLES
as this could seriously impact customers and a proper fix would require
a significant rewrite.
This commit is contained in:
Jon Olav Hauglid
2009-12-10 11:53:20 +01:00
parent 6c25664eb3
commit b20a409c38
21 changed files with 465 additions and 415 deletions

View File

@ -4175,39 +4175,22 @@ bool mysql_unpack_partition(THD *thd,
ha_resolve_storage_engine_name(default_db_type)));
if (is_create_table_ind && old_lex->sql_command == SQLCOM_CREATE_TABLE)
{
if (old_lex->create_info.options & HA_LEX_CREATE_TABLE_LIKE)
{
/*
This code is executed when we create table in CREATE TABLE t1 LIKE t2.
old_lex->query_tables contains table list element for t2 and the table
we are opening has name t1.
*/
if (partition_default_handling(table, part_info, FALSE,
old_lex->query_tables->table->s->path.str))
{
result= TRUE;
goto end;
}
}
else
{
/*
When we come here we are doing a create table. In this case we
have already done some preparatory work on the old part_info
object. We don't really need this new partition_info object.
Thus we go back to the old partition info object.
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.
*/
thd->free_items();
part_info= thd->work_part_info;
table->s->version= 0UL;
*work_part_info_used= true;
}
/*
When we come here we are doing a create table. In this case we
have already done some preparatory work on the old part_info
object. We don't really need this new partition_info object.
Thus we go back to the old partition info object.
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.
*/
thd->free_items();
part_info= thd->work_part_info;
table->s->version= 0UL;
*work_part_info_used= true;
}
table->part_info= part_info;
table->file->set_part_info(part_info);