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

A pre-requisite patch for the fix for Bug#52044.

This patch also fixes Bug#55452 "SET PASSWORD is
replicated twice in RBR mode".

The goal of this patch is to remove the release of 
metadata locks from close_thread_tables().
This is necessary to not mistakenly release
the locks in the course of a multi-step
operation that involves multiple close_thread_tables()
or close_tables_for_reopen().

On the same token, move statement commit outside 
close_thread_tables().

Other cleanups:
Cleanup COM_FIELD_LIST.
Don't call close_thread_tables() in COM_SHUTDOWN -- there
are no open tables there that can be closed (we leave
the locked tables mode in THD destructor, and this
close_thread_tables() won't leave it anyway).

Make open_and_lock_tables() and open_and_lock_tables_derived()
call close_thread_tables() upon failure.
Remove the calls to close_thread_tables() that are now
unnecessary.

Simplify the back off condition in Open_table_context.

Streamline metadata lock handling in LOCK TABLES 
implementation.

Add asserts to ensure correct life cycle of 
statement transaction in a session.

Remove a piece of dead code that has also become redundant
after the fix for Bug 37521.
This commit is contained in:
Konstantin Osipov
2010-07-27 14:25:53 +04:00
parent c67cf159e9
commit ec2c3bf2c1
42 changed files with 590 additions and 468 deletions

View File

@ -2285,18 +2285,13 @@ err:
{
/*
Under LOCK TABLES we should release meta-data locks on the tables
which were dropped. Otherwise we can rely on close_thread_tables()
doing this. Unfortunately in this case we are likely to get more
false positives in try_acquire_lock() function. So
it makes sense to remove exclusive meta-data locks in all cases.
which were dropped.
Leave LOCK TABLES mode if we managed to drop all tables which were
locked. Additional check for 'non_temp_tables_count' is to avoid
leaving LOCK TABLES mode if we have dropped only temporary tables.
*/
if (! thd->locked_tables_mode)
thd->mdl_context.release_transactional_locks();
else
if (thd->locked_tables_mode)
{
if (thd->lock && thd->lock->table_count == 0 && non_temp_tables_count > 0)
{
@ -2305,7 +2300,8 @@ err:
}
for (table= tables; table; table= table->next_local)
{
if (table->mdl_request.ticket)
/* Drop locks for all successfully dropped tables. */
if (table->table == NULL && table->mdl_request.ticket)
{
/*
Under LOCK TABLES we may have several instances of table open
@ -2316,6 +2312,10 @@ err:
}
}
}
/*
Rely on the caller to implicitly commit the transaction
and release metadata locks.
*/
}
end:
@ -4214,8 +4214,14 @@ warn:
}
/*
Database and name-locking aware wrapper for mysql_create_table_no_lock(),
/**
Implementation of SQLCOM_CREATE_TABLE.
Take the metadata locks (including a shared lock on the affected
schema) and create the table. Is written to be called from
mysql_execute_command(), to which it delegates the common parts
with other commands (i.e. implicit commit before and after,
close of thread tables.
*/
bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
@ -4231,7 +4237,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
if (open_and_lock_tables(thd, thd->lex->query_tables, FALSE, 0))
{
result= TRUE;
goto unlock;
goto end;
}
/* Got lock. */
@ -4253,16 +4259,7 @@ bool mysql_create_table(THD *thd, TABLE_LIST *create_table,
!(create_info->options & HA_LEX_CREATE_TMP_TABLE))))
result= write_bin_log(thd, TRUE, thd->query(), thd->query_length());
if (!(create_info->options & HA_LEX_CREATE_TMP_TABLE))
{
/*
close_thread_tables() takes care about both closing open tables (which
might be still around in case of error) and releasing metadata locks.
*/
close_thread_tables(thd);
}
unlock:
end:
DBUG_RETURN(result);
}
@ -4752,6 +4749,7 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
trans_rollback_stmt(thd);
trans_rollback(thd);
close_thread_tables(thd);
thd->mdl_context.release_transactional_locks();
DBUG_PRINT("admin", ("simple error, admin next table"));
continue;
case -1: // error, message could be written to net
@ -5038,11 +5036,11 @@ send_result_message:
trans_commit_stmt(thd);
trans_commit(thd);
close_thread_tables(thd);
table->table= NULL;
thd->mdl_context.release_transactional_locks();
table->table= NULL;
if (!result_code) // recreation went ok
{
/* Clear the ticket released in close_thread_tables(). */
/* Clear the ticket released above. */
table->mdl_request.ticket= NULL;
DEBUG_SYNC(thd, "ha_admin_open_ltable");
table->mdl_request.set_type(MDL_SHARED_WRITE);
@ -6729,13 +6727,11 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
goto err;
DBUG_EXECUTE_IF("sleep_alter_enable_indexes", my_sleep(6000000););
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
/* COND_refresh will be signaled in close_thread_tables() */
break;
case DISABLE:
if (wait_while_table_is_used(thd, table, HA_EXTRA_FORCE_REOPEN))
goto err;
error=table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
/* COND_refresh will be signaled in close_thread_tables() */
break;
default:
DBUG_ASSERT(FALSE);
@ -6821,8 +6817,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
/*
Under LOCK TABLES we should adjust meta-data locks before finishing
statement. Otherwise we can rely on close_thread_tables() releasing
them.
statement. Otherwise we can rely on them being released
along with the implicit commit.
*/
if (new_name != table_name || new_db != db)
{
@ -7360,8 +7356,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
5) Write statement to the binary log.
6) If we are under LOCK TABLES and do ALTER TABLE ... RENAME we
remove placeholders and release metadata locks.
7) If we are not not under LOCK TABLES we rely on close_thread_tables()
call to remove placeholders and releasing metadata locks.
7) If we are not not under LOCK TABLES we rely on the caller
(mysql_execute_command()) to release metadata locks.
*/
thd_proc_info(thd, "rename result table");
@ -7990,7 +7986,13 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
}
}
thd->clear_error();
if (! thd->in_sub_stmt)
trans_rollback_stmt(thd);
close_thread_tables(thd);
/*
Don't release metadata locks, this will be done at
statement end.
*/
table->table=0; // For query cache
}
if (protocol->write())
@ -8000,10 +8002,7 @@ bool mysql_checksum_table(THD *thd, TABLE_LIST *tables,
my_eof(thd);
DBUG_RETURN(FALSE);
err:
close_thread_tables(thd); // Shouldn't be needed
if (table)
table->table=0;
err:
DBUG_RETURN(TRUE);
}