mariadb/mysql-test/t/schema.test
Jon Olav Hauglid c7bcb28f0c Bug #49988 MDL deadlocks with mysql_create_db, reload_acl_and_cache
This was a deadlock between LOCK TABLES/CREATE DATABASE in one connection
and DROP DATABASE in another. It only happened if the table locked by 
LOCK TABLES was in the database to be dropped. The deadlock is similar
to the one in Bug#48940, but with LOCK TABLES instead of an active
transaction.

The order of events needed to trigger the deadlock was:
1) Connection 1 locks table db1.t1 using LOCK TABLES. It will now
have a metadata lock on the table name.
2) Connection 2 issues DROP DATABASE db1. This will wait inside
the MDL subsystem for the lock on db1.t1 to go away. While waiting, it
will hold the LOCK_mysql_create_db mutex.
3) Connection 1 issues CREATE DATABASE (database name irrelevant).
This will hang trying to lock the same mutex. Since this is the connection
holding the metadata lock blocking Connection 2, we have a deadlock.

This deadlock would also happen for earlier trees without MDL, but 
there DROP DATABASE would wait for a table to be removed from the
table definition cache.

This patch fixes the problem by prohibiting CREATE DATABASE in LOCK TABLES
mode. In the example above, this prevents Connection 1 from hanging trying
to get the LOCK_mysql_create_db mutex. Note that other commands that use
LOCK_mysql_create_db (ALTER/DROP DATABASE) are already prohibited in 
LOCK TABLES mode.

Incompatible change: CREATE DATABASE is now disallowed in LOCK TABLES mode.

Test case added to schema.test.


mysql-test/t/drop.test:
  Updates the test for Bug#21216 by swapping the order of CREATE DATABASE
  and LOCK TABLES. This is now needed as CREATE DATABASE is prohibited in
  LOCK TABLES mode.
mysql-test/t/schema.test:
  Test case for Bug#49988 added.
  Also fixes a problem with the test for Bug#48940 where the result 
  would differ for embedded server.
2010-01-12 16:15:21 +01:00

107 lines
2.4 KiB
Text

#
# Just a couple of tests to make sure that schema works.
#
# Drop mysqltest1 database, as it can left from the previous tests.
#
# Save the initial number of concurrent sessions.
--source include/count_sessions.inc
--disable_warnings
drop database if exists mysqltest1;
--enable_warnings
create schema foo;
show create schema foo;
show schemas;
drop schema foo;
--echo #
--echo # Bug #48940 MDL deadlocks against mysql_rm_db
--echo #
--disable_warnings
DROP SCHEMA IF EXISTS schema1;
--enable_warnings
connect(con2, localhost, root);
--echo # Connection default
connection default;
CREATE SCHEMA schema1;
CREATE TABLE schema1.t1 (a INT);
SET autocommit= FALSE;
INSERT INTO schema1.t1 VALUES (1);
--echo # Connection 2
connection con2;
--send DROP SCHEMA schema1
--echo # Connection default
connection default;
let $wait_condition= SELECT COUNT(*)= 1 FROM information_schema.processlist
WHERE state= 'Waiting for table'
AND info='DROP SCHEMA schema1';
--source include/wait_condition.inc
# Listing the error twice to prevent result diffences based on filename
--error 1,1
ALTER SCHEMA schema1 DEFAULT CHARACTER SET utf8;
SET autocommit= TRUE;
--echo # Connection 2
connection con2;
--reap
--echo # Connection default
connection default;
disconnect con2;
--echo #
--echo # Bug #49988 MDL deadlocks with mysql_create_db, reload_acl_and_cache
--echo #
--disable_warnings
DROP SCHEMA IF EXISTS schema1;
--enable_warnings
connect (con2, localhost, root);
--echo # Connection default
connection default;
CREATE SCHEMA schema1;
CREATE TABLE schema1.t1 (id INT);
LOCK TABLE schema1.t1 WRITE;
--echo # Connection con2
connection con2;
--send DROP SCHEMA schema1
--echo # Connection default
connection default;
let $wait_condition=SELECT COUNT(*)=1 FROM information_schema.processlist
WHERE state='Waiting for table' and info='DROP SCHEMA schema1';
--source include/wait_condition.inc
--echo # CREATE SCHEMA used to give a deadlock.
--echo # Now we prohibit CREATE SCHEMA in LOCK TABLES mode.
--error ER_LOCK_OR_ACTIVE_TRANSACTION
CREATE SCHEMA IF NOT EXISTS schema1;
--echo # UNLOCK TABLES so DROP SCHEMA can continue.
UNLOCK TABLES;
--echo # Connection con2
connection con2;
--reap
--echo # Connection default
connection default;
disconnect con2;
# Check that all connections opened by test cases in this file are really
# gone so execution of other tests won't be affected by their presence.
--source include/wait_until_count_sessions.inc