mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 10:14:19 +01:00
Bug #54905 Connection with WRITE lock cannot ALTER table due to
concurrent SHOW CREATE The problem was that a SHOW CREATE TABLE statement issued inside a transaction did not release its metadata locks at the end of the statement execution. This happened even if SHOW CREATE TABLE is an information statement. The consequence was that SHOW CREATE TABLE was able to block other connections from accessing the table (e.g. using ALTER TABLE). This patch fixes the problem by explicitly releasing any metadata locks taken by SHOW CREATE TABLE after the statement completes. Test case added to show_check.test.
This commit is contained in:
parent
131095149f
commit
e814e9ac1e
3 changed files with 77 additions and 9 deletions
|
@ -1466,3 +1466,24 @@ t1 CREATE TABLE `t1` (
|
|||
# Switching to connection 'default'.
|
||||
UNLOCK TABLES;
|
||||
DROP TABLE t1;
|
||||
#
|
||||
# Bug#54905 Connection with WRITE lock cannot ALTER table due to
|
||||
# concurrent SHOW CREATE
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
CREATE TABLE t1(a INT);
|
||||
# Connection con1
|
||||
LOCK TABLE t1 WRITE;
|
||||
# Connection default
|
||||
START TRANSACTION;
|
||||
SHOW CREATE TABLE t1;
|
||||
Table Create Table
|
||||
t1 CREATE TABLE `t1` (
|
||||
`a` int(11) DEFAULT NULL
|
||||
) ENGINE=MyISAM DEFAULT CHARSET=latin1
|
||||
# Connection con1
|
||||
ALTER TABLE t1 CHARACTER SET = utf8;
|
||||
UNLOCK TABLES;
|
||||
# Connection default
|
||||
COMMIT;
|
||||
DROP TABLE t1;
|
||||
|
|
|
@ -1246,6 +1246,39 @@ UNLOCK TABLES;
|
|||
DROP TABLE t1;
|
||||
|
||||
|
||||
--echo #
|
||||
--echo # Bug#54905 Connection with WRITE lock cannot ALTER table due to
|
||||
--echo # concurrent SHOW CREATE
|
||||
--echo #
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1(a INT);
|
||||
|
||||
--echo # Connection con1
|
||||
connect (con1,localhost,root);
|
||||
LOCK TABLE t1 WRITE;
|
||||
|
||||
--echo # Connection default
|
||||
connection default;
|
||||
START TRANSACTION;
|
||||
SHOW CREATE TABLE t1;
|
||||
|
||||
--echo # Connection con1
|
||||
connection con1;
|
||||
# Used to block
|
||||
ALTER TABLE t1 CHARACTER SET = utf8;
|
||||
UNLOCK TABLES;
|
||||
|
||||
--echo # Connection default
|
||||
connection default;
|
||||
COMMIT;
|
||||
disconnect con1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
# Wait till all disconnects are completed
|
||||
--source include/wait_until_count_sessions.inc
|
||||
|
||||
|
|
|
@ -649,22 +649,30 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
|
|||
Protocol *protocol= thd->protocol;
|
||||
char buff[2048];
|
||||
String buffer(buff, sizeof(buff), system_charset_info);
|
||||
List<Item> field_list;
|
||||
bool error= TRUE;
|
||||
DBUG_ENTER("mysqld_show_create");
|
||||
DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
|
||||
table_list->table_name));
|
||||
|
||||
/*
|
||||
Metadata locks taken during SHOW CREATE should be released when
|
||||
the statmement completes as it is an information statement.
|
||||
*/
|
||||
MDL_ticket *mdl_savepoint= thd->mdl_context.mdl_savepoint();
|
||||
|
||||
/* We want to preserve the tree for views. */
|
||||
thd->lex->view_prepare_mode= TRUE;
|
||||
|
||||
{
|
||||
Show_create_error_handler view_error_suppressor(thd, table_list);
|
||||
thd->push_internal_handler(&view_error_suppressor);
|
||||
bool error=
|
||||
bool open_error=
|
||||
open_normal_and_derived_tables(thd, table_list,
|
||||
MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL);
|
||||
thd->pop_internal_handler();
|
||||
if (error && (thd->killed || thd->is_error()))
|
||||
DBUG_RETURN(TRUE);
|
||||
if (open_error && (thd->killed || thd->is_error()))
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* TODO: add environment variables show when it become possible */
|
||||
|
@ -672,7 +680,7 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
|
|||
{
|
||||
my_error(ER_WRONG_OBJECT, MYF(0),
|
||||
table_list->db, table_list->table_name, "VIEW");
|
||||
DBUG_RETURN(TRUE);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
buffer.length(0);
|
||||
|
@ -684,9 +692,8 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
|
|||
view_store_create_info(thd, table_list, &buffer) :
|
||||
store_create_info(thd, table_list, &buffer, NULL,
|
||||
FALSE /* show_database */)))
|
||||
DBUG_RETURN(TRUE);
|
||||
goto exit;
|
||||
|
||||
List<Item> field_list;
|
||||
if (table_list->view)
|
||||
{
|
||||
field_list.push_back(new Item_empty_string("View",NAME_CHAR_LEN));
|
||||
|
@ -707,7 +714,8 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
|
|||
|
||||
if (protocol->send_result_set_metadata(&field_list,
|
||||
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
|
||||
DBUG_RETURN(TRUE);
|
||||
goto exit;
|
||||
|
||||
protocol->prepare_for_resend();
|
||||
if (table_list->view)
|
||||
protocol->store(table_list->view_name.str, system_charset_info);
|
||||
|
@ -735,10 +743,16 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
|
|||
protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
|
||||
|
||||
if (protocol->write())
|
||||
DBUG_RETURN(TRUE);
|
||||
goto exit;
|
||||
|
||||
error= FALSE;
|
||||
my_eof(thd);
|
||||
DBUG_RETURN(FALSE);
|
||||
|
||||
exit:
|
||||
close_thread_tables(thd);
|
||||
/* Release any metadata locks taken during SHOW CREATE. */
|
||||
thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
bool mysqld_show_create_db(THD *thd, char *dbname,
|
||||
|
|
Loading…
Add table
Reference in a new issue