Backport of:
------------------------------------------------------------
revno: 2617.23.18
committer: Davi Arnaut <Davi.Arnaut@Sun.COM>
branch nick: 4284-6.0
timestamp: Mon 2009-03-02 18:18:26 -0300
message:
Bug#989: If DROP TABLE while there's an active transaction, wrong binlog order
WL#4284: Transactional DDL locking
This is a prerequisite patch:
These changes are intended to split lock requests from granted
locks and to allow the memory and lifetime of granted locks to
be managed within the MDL subsystem. Furthermore, tickets can
now be shared and therefore are used to satisfy multiple lock
requests, but only shared locks can be recursive.
The problem is that the MDL subsystem morphs lock requests into
granted locks locks but does not manage the memory and lifetime
of lock requests, and hence, does not manage the memory of
granted locks either. This can be problematic because it puts the
burden of tracking references on the users of the subsystem and
it can't be easily done in transactional contexts where the locks
have to be kept around for the duration of a transaction.
Another issue is that recursive locks (when the context trying to
acquire a lock already holds a lock on the same object) requires
that each time the lock is granted, a unique lock request/granted
lock structure structure must be kept around until the lock is
released. This can lead to memory leaks in transactional contexts
as locks taken during the transaction should only be released at
the end of the transaction. This also leads to unnecessary wake
ups (broadcasts) in the MDL subsystem if the context still holds
a equivalent of the lock being released.
These issues are exacerbated due to the fact that WL#4284 low-level
design says that the implementation should "2) Store metadata locks
in transaction memory root, rather than statement memory root" but
this is not possible because a memory root, as implemented in mysys,
requires all objects allocated from it to be freed all at once.
This patch combines review input and significant code contributions
from Konstantin Osipov (kostja) and Dmitri Lenev (dlenev).
mysql-test/r/mdl_sync.result:
Add test case result.
mysql-test/t/mdl_sync.test:
Add test case for shared lock upgrade case.
sql/event_db_repository.cc:
Rename mdl_alloc_lock to mdl_request_alloc.
sql/ha_ndbcluster_binlog.cc:
Use new function names to initialize MDL lock requests.
sql/lock.cc:
Rename MDL functions.
sql/log_event.cc:
The MDL request now holds the table and database name data (MDL_KEY).
sql/mdl.cc:
Move the MDL key to the MDL_LOCK structure in order to make the
object suitable for allocation from a fixed-size allocator. This
allows the simplification of the lists in the MDL_LOCK object,
which now are just two, one for granted tickets and other for
waiting (upgraders) tickets.
Recursive requests for a shared lock on the same object can now
be granted using the same lock ticket. This schema is only used
for shared locks because that the only case that matters. This
is used to avoid waste of resources in case a context (connection)
already holds a shared lock on a object.
sql/mdl.h:
Introduce a metadata lock object key which is used to uniquely
identify lock objects.
Separate the structure used to represent pending lock requests
from the structure used to represent granted metadata locks.
Rename functions used to manipulate locks requests in order to
have a more consistent function naming schema.
sql/sp_head.cc:
Rename mdl_alloc_lock to mdl_request_alloc.
sql/sql_acl.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_base.cc:
Various changes to accommodate that lock requests are separated
from lock tickets (granted locks).
sql/sql_class.h:
Last acquired lock before the savepoint was set.
sql/sql_delete.cc:
Various changes to accommodate that lock requests are separated
from lock tickets (granted locks).
sql/sql_handler.cc:
Various changes to accommodate that lock requests are separated
from lock tickets (granted locks).
sql/sql_insert.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_parse.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_plist.h:
Typedef for iterator type.
sql/sql_plugin.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_servers.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_show.cc:
Various changes to accommodate that lock requests are separated
from lock tickets (granted locks).
sql/sql_table.cc:
Various changes to accommodate that lock requests are separated
from lock tickets (granted locks).
sql/sql_trigger.cc:
Save reference to the lock ticket so it can be downgraded later.
sql/sql_udf.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
sql/table.cc:
Rename mdl_alloc_lock to mdl_request_alloc.
sql/table.h:
Separate MDL lock requests from lock tickets (granted locks).
storage/myisammrg/ha_myisammrg.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
2009-12-04 02:29:40 +03:00
|
|
|
#
|
|
|
|
# We need the Debug Sync Facility.
|
|
|
|
#
|
|
|
|
--source include/have_debug_sync.inc
|
|
|
|
|
2009-12-09 12:44:05 +03:00
|
|
|
# Save the initial number of concurrent sessions.
|
|
|
|
--source include/count_sessions.inc
|
|
|
|
|
|
|
|
|
Backport of:
------------------------------------------------------------
revno: 2617.23.18
committer: Davi Arnaut <Davi.Arnaut@Sun.COM>
branch nick: 4284-6.0
timestamp: Mon 2009-03-02 18:18:26 -0300
message:
Bug#989: If DROP TABLE while there's an active transaction, wrong binlog order
WL#4284: Transactional DDL locking
This is a prerequisite patch:
These changes are intended to split lock requests from granted
locks and to allow the memory and lifetime of granted locks to
be managed within the MDL subsystem. Furthermore, tickets can
now be shared and therefore are used to satisfy multiple lock
requests, but only shared locks can be recursive.
The problem is that the MDL subsystem morphs lock requests into
granted locks locks but does not manage the memory and lifetime
of lock requests, and hence, does not manage the memory of
granted locks either. This can be problematic because it puts the
burden of tracking references on the users of the subsystem and
it can't be easily done in transactional contexts where the locks
have to be kept around for the duration of a transaction.
Another issue is that recursive locks (when the context trying to
acquire a lock already holds a lock on the same object) requires
that each time the lock is granted, a unique lock request/granted
lock structure structure must be kept around until the lock is
released. This can lead to memory leaks in transactional contexts
as locks taken during the transaction should only be released at
the end of the transaction. This also leads to unnecessary wake
ups (broadcasts) in the MDL subsystem if the context still holds
a equivalent of the lock being released.
These issues are exacerbated due to the fact that WL#4284 low-level
design says that the implementation should "2) Store metadata locks
in transaction memory root, rather than statement memory root" but
this is not possible because a memory root, as implemented in mysys,
requires all objects allocated from it to be freed all at once.
This patch combines review input and significant code contributions
from Konstantin Osipov (kostja) and Dmitri Lenev (dlenev).
mysql-test/r/mdl_sync.result:
Add test case result.
mysql-test/t/mdl_sync.test:
Add test case for shared lock upgrade case.
sql/event_db_repository.cc:
Rename mdl_alloc_lock to mdl_request_alloc.
sql/ha_ndbcluster_binlog.cc:
Use new function names to initialize MDL lock requests.
sql/lock.cc:
Rename MDL functions.
sql/log_event.cc:
The MDL request now holds the table and database name data (MDL_KEY).
sql/mdl.cc:
Move the MDL key to the MDL_LOCK structure in order to make the
object suitable for allocation from a fixed-size allocator. This
allows the simplification of the lists in the MDL_LOCK object,
which now are just two, one for granted tickets and other for
waiting (upgraders) tickets.
Recursive requests for a shared lock on the same object can now
be granted using the same lock ticket. This schema is only used
for shared locks because that the only case that matters. This
is used to avoid waste of resources in case a context (connection)
already holds a shared lock on a object.
sql/mdl.h:
Introduce a metadata lock object key which is used to uniquely
identify lock objects.
Separate the structure used to represent pending lock requests
from the structure used to represent granted metadata locks.
Rename functions used to manipulate locks requests in order to
have a more consistent function naming schema.
sql/sp_head.cc:
Rename mdl_alloc_lock to mdl_request_alloc.
sql/sql_acl.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_base.cc:
Various changes to accommodate that lock requests are separated
from lock tickets (granted locks).
sql/sql_class.h:
Last acquired lock before the savepoint was set.
sql/sql_delete.cc:
Various changes to accommodate that lock requests are separated
from lock tickets (granted locks).
sql/sql_handler.cc:
Various changes to accommodate that lock requests are separated
from lock tickets (granted locks).
sql/sql_insert.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_parse.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_plist.h:
Typedef for iterator type.
sql/sql_plugin.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_servers.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
sql/sql_show.cc:
Various changes to accommodate that lock requests are separated
from lock tickets (granted locks).
sql/sql_table.cc:
Various changes to accommodate that lock requests are separated
from lock tickets (granted locks).
sql/sql_trigger.cc:
Save reference to the lock ticket so it can be downgraded later.
sql/sql_udf.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
sql/table.cc:
Rename mdl_alloc_lock to mdl_request_alloc.
sql/table.h:
Separate MDL lock requests from lock tickets (granted locks).
storage/myisammrg/ha_myisammrg.cc:
Rename alloc_mdl_locks to alloc_mdl_requests.
2009-12-04 02:29:40 +03:00
|
|
|
# Clean up resources used in this test case.
|
|
|
|
--disable_warnings
|
|
|
|
SET DEBUG_SYNC= 'RESET';
|
|
|
|
--enable_warnings
|
|
|
|
|
|
|
|
#
|
|
|
|
# Test the case of when a exclusive lock request waits for a
|
|
|
|
# shared lock being upgraded to a exclusive lock.
|
|
|
|
#
|
|
|
|
|
|
|
|
connect (con1,localhost,root,,test,,);
|
|
|
|
connect (con2,localhost,root,,test,,);
|
|
|
|
connect (con3,localhost,root,,test,,);
|
|
|
|
|
|
|
|
connection default;
|
|
|
|
|
|
|
|
--disable_warnings
|
|
|
|
drop table if exists t1,t2,t3;
|
|
|
|
--enable_warnings
|
|
|
|
|
|
|
|
create table t1 (i int);
|
|
|
|
create table t2 (i int);
|
|
|
|
|
|
|
|
--echo connection: default
|
|
|
|
lock tables t2 read;
|
|
|
|
|
|
|
|
connection con1;
|
|
|
|
--echo connection: con1
|
|
|
|
set debug_sync='mdl_upgrade_shared_lock_to_exclusive SIGNAL parked WAIT_FOR go';
|
|
|
|
--send alter table t1 rename t3
|
|
|
|
|
|
|
|
connection default;
|
|
|
|
--echo connection: default
|
|
|
|
set debug_sync= 'now WAIT_FOR parked';
|
|
|
|
|
|
|
|
connection con2;
|
|
|
|
--echo connection: con2
|
|
|
|
set debug_sync='mdl_acquire_exclusive_locks_wait SIGNAL go';
|
|
|
|
--send drop table t1,t2
|
|
|
|
|
|
|
|
connection con1;
|
|
|
|
--echo connection: con1
|
|
|
|
--reap
|
|
|
|
|
|
|
|
connection default;
|
|
|
|
--echo connection: default
|
|
|
|
unlock tables;
|
|
|
|
|
|
|
|
connection con2;
|
|
|
|
--echo connection: con2
|
|
|
|
--error ER_BAD_TABLE_ERROR
|
|
|
|
--reap
|
|
|
|
|
|
|
|
connection default;
|
|
|
|
drop table t3;
|
|
|
|
|
|
|
|
disconnect con1;
|
|
|
|
disconnect con2;
|
|
|
|
disconnect con3;
|
|
|
|
|
|
|
|
# Clean up resources used in this test case.
|
|
|
|
--disable_warnings
|
|
|
|
SET DEBUG_SYNC= 'RESET';
|
|
|
|
--enable_warnings
|
2009-12-09 12:44:05 +03:00
|
|
|
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # Test for bug #46748 "Assertion in MDL_context::wait_for_locks()
|
|
|
|
--echo # on INSERT + CREATE TRIGGER".
|
|
|
|
--echo #
|
|
|
|
--disable_warnings
|
|
|
|
drop tables if exists t1, t2, t3, t4, t5;
|
|
|
|
--enable_warnings
|
|
|
|
--echo # Let us simulate scenario in which we open some tables from extended
|
|
|
|
--echo # part of prelocking set but then encounter conflicting metadata lock,
|
|
|
|
--echo # so have to back-off and wait for it to go away.
|
|
|
|
connect (con1root,localhost,root,,test,,);
|
|
|
|
connect (con2root,localhost,root,,test,,);
|
|
|
|
connection default;
|
|
|
|
create table t1 (i int);
|
|
|
|
create table t2 (j int);
|
|
|
|
create table t3 (k int);
|
|
|
|
create table t4 (l int);
|
|
|
|
create trigger t1_bi before insert on t1 for each row
|
|
|
|
insert into t2 values (new.i);
|
|
|
|
create trigger t2_bi before insert on t2 for each row
|
|
|
|
insert into t3 values (new.j);
|
|
|
|
--echo #
|
|
|
|
--echo # Switching to connection 'con1root'.
|
|
|
|
connection con1root;
|
|
|
|
lock tables t4 read;
|
|
|
|
--echo #
|
|
|
|
--echo # Switching to connection 'con2root'.
|
|
|
|
connection con2root;
|
|
|
|
--echo # Send :
|
|
|
|
--send rename table t3 to t5, t4 to t3;
|
|
|
|
--echo #
|
|
|
|
--echo # Switching to connection 'default'.
|
|
|
|
connection default;
|
|
|
|
--echo # Wait until the above RENAME TABLE adds pending requests for exclusive
|
|
|
|
--echo # metadata lock on its tables and blocks due to 't4' being used by LOCK
|
|
|
|
--echo # TABLES.
|
|
|
|
let $wait_condition= select count(*)= 1 from information_schema.processlist
|
|
|
|
where state= 'Waiting for table' and
|
|
|
|
info='rename table t3 to t5, t4 to t3';
|
|
|
|
--source include/wait_condition.inc
|
|
|
|
--echo # Send :
|
|
|
|
--send insert into t1 values (1);
|
|
|
|
--echo #
|
|
|
|
--echo # Switching to connection 'con1root'.
|
|
|
|
connection con1root;
|
|
|
|
--echo # Wait until INSERT statement waits due to encountering pending
|
|
|
|
--echo # exclusive metadata lock on 't3'.
|
|
|
|
let $wait_condition= select count(*)= 1 from information_schema.processlist
|
|
|
|
where state= 'Waiting for table' and
|
|
|
|
info='insert into t1 values (1)';
|
|
|
|
--source include/wait_condition.inc
|
|
|
|
unlock tables;
|
|
|
|
--echo #
|
|
|
|
--echo # Switching to connection 'con2root'.
|
|
|
|
connection con2root;
|
|
|
|
--echo # Reap RENAME TABLE.
|
|
|
|
--reap
|
|
|
|
--echo #
|
|
|
|
--echo # Switching to connection 'default'.
|
|
|
|
connection default;
|
|
|
|
--echo # Reap INSERT.
|
|
|
|
--reap
|
|
|
|
--echo # Clean-up.
|
|
|
|
disconnect con1root;
|
|
|
|
disconnect con2root;
|
|
|
|
drop tables t1, t2, t3, t5;
|
|
|
|
|
|
|
|
|
2009-12-10 11:53:20 +01:00
|
|
|
--echo #
|
|
|
|
--echo # Bug#42546 - Backup: RESTORE fails, thinking it finds an existing table
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
--disable_warnings
|
|
|
|
DROP TABLE IF EXISTS t1;
|
|
|
|
--enable_warnings
|
|
|
|
set @save_log_output=@@global.log_output;
|
|
|
|
set global log_output=file;
|
|
|
|
|
|
|
|
connect(con2, localhost, root,,);
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # Test 1: CREATE TABLE
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
--echo # Connection 2
|
|
|
|
connection con2;
|
|
|
|
--echo # Start insert on the not-yet existing table
|
|
|
|
--echo # Wait after taking the MDL lock
|
|
|
|
SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish';
|
|
|
|
--send INSERT INTO t1 VALUES(1,"def")
|
|
|
|
|
|
|
|
--echo # Connection 1
|
|
|
|
connection default;
|
|
|
|
SET DEBUG_SYNC= 'now WAIT_FOR locked';
|
|
|
|
--echo # Now INSERT has a MDL on the non-existent table t1.
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # Continue the INSERT once CREATE waits for exclusive lock
|
|
|
|
SET DEBUG_SYNC= 'mdl_acquire_exclusive_locks_wait SIGNAL finish';
|
|
|
|
--echo # Try to create that table.
|
|
|
|
--send CREATE TABLE t1 (c1 INT, c2 VARCHAR(100), KEY(c1))
|
|
|
|
|
|
|
|
--echo # Connection 2
|
|
|
|
--echo # Insert fails
|
|
|
|
connection con2;
|
|
|
|
--error ER_NO_SUCH_TABLE
|
|
|
|
--reap
|
|
|
|
|
|
|
|
--echo # Connection 1
|
|
|
|
connection default;
|
|
|
|
--reap;
|
|
|
|
SET DEBUG_SYNC= 'RESET';
|
|
|
|
SHOW TABLES;
|
|
|
|
|
|
|
|
--disable_warnings
|
|
|
|
DROP TABLE IF EXISTS t1;
|
|
|
|
--enable_warnings
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # Test 2: CREATE TABLE LIKE
|
|
|
|
--echo #
|
|
|
|
|
|
|
|
CREATE TABLE t2 (c1 INT, c2 VARCHAR(100), KEY(c1));
|
|
|
|
|
|
|
|
--echo # Connection 2
|
|
|
|
connection con2;
|
|
|
|
--echo # Start insert on the not-yet existing table
|
|
|
|
--echo # Wait after taking the MDL
|
|
|
|
SET DEBUG_SYNC= 'after_open_table_mdl_shared SIGNAL locked WAIT_FOR finish';
|
|
|
|
--send INSERT INTO t1 VALUES(1,"def")
|
|
|
|
|
|
|
|
--echo # Connection 1
|
|
|
|
connection default;
|
|
|
|
SET DEBUG_SYNC= 'now WAIT_FOR locked';
|
|
|
|
--echo # Now INSERT has a MDL on the non-existent table t1.
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # Continue the INSERT once CREATE waits for exclusive lock
|
|
|
|
SET DEBUG_SYNC= 'mdl_acquire_exclusive_locks_wait SIGNAL finish';
|
|
|
|
--echo # Try to create that table.
|
|
|
|
--send CREATE TABLE t1 LIKE t2
|
|
|
|
|
|
|
|
--echo # Connection 2
|
|
|
|
--echo # Insert fails
|
|
|
|
connection con2;
|
|
|
|
--error ER_NO_SUCH_TABLE
|
|
|
|
--reap
|
|
|
|
|
|
|
|
--echo # Connection 1
|
|
|
|
connection default;
|
|
|
|
--reap
|
|
|
|
SET DEBUG_SYNC= 'RESET';
|
|
|
|
SHOW TABLES;
|
|
|
|
|
|
|
|
DROP TABLE t2;
|
|
|
|
disconnect con2;
|
|
|
|
--disable_warnings
|
|
|
|
DROP TABLE IF EXISTS t1;
|
|
|
|
--enable_warnings
|
|
|
|
|
|
|
|
set global log_output=@save_log_output;
|
|
|
|
|
|
|
|
|
Backport of:
------------------------------------------------------------
revno: 2617.68.7
committer: Dmitry Lenev <dlenev@mysql.com>
branch nick: mysql-next-bg46044
timestamp: Thu 2009-08-27 10:22:17 +0400
message:
Fix for bug #46044 "MDL deadlock on LOCK TABLE + CREATE TABLE HIGH_PRIORITY
FOR UPDATE".
Deadlock occured when during execution of query to I_S we tried to open
a table or its .FRM in order to get information about it and had to wait
because we have encountered exclusive metadata lock on this table held by
a DDL operation from another connection which in its turn waited for some
resource currently owned by connection executing this I_S query.
For example, this might have happened if one under LOCK TABLES executed I_S
query targeted to particular table (which was not among locked) and also
concurrently tried to create this table using CREATE TABLE SELECT which
had to wait for one of tables locked by the first connection.
Another situation in which deadlock might have occured is when I_S query,
which was executed as part of transaction, tried to get information about
table which just has been dropped by concurrent DROP TABLES executed under
LOCK TABLES and this DROP TABLES for its completion also had to wait
transaction from the first connection.
This problem stemmed from the fact that opening of tables/.FRMs for I_S
filling is happening outside of connection's main MDL_context so code
which tries to detect deadlocks due to conflicting metadata locks doesn't
work in this case. Indeed, this led to deadlocks when during I_S filling
we tried to wait for conflicting metadata lock to go away, while its owner
was waiting for some resource held by connection executing I_S query.
This patch solves this problem by avoiding waiting in such situation.
Instead we skip this table and produce warning that information about
it was omitted from I_S due to concurrent DDL operation. We still wait
for conflicting metadata lock to go away when it is known that deadlock
is not possible (i.e. when connection executing I_S query does not hold
any metadata or table-level locks).
Basically, we apply our standard deadlock avoidance technique for metadata
locks to the process of filling of I_S tables but replace ER_LOCK_DEADLOCK
error with a warning.
Note that this change is supposed to be safe for 'mysqldump' since the
only its mode which is affected by this change is --single-transaction mode
is not safe in the presence of concurrent DDL anyway (and this fact is
documented). Other modes are unaffected because they either use
SHOW TABLES/SELECT * FROM I_S.TABLE_NAMES which do not take any metadata
locks in the process of I_S table filling and thus cannot skip tables or
execute I_S queries for tables which were previously locked by LOCK TABLES
(or in the presence of global read lock) which excludes possibility of
encountering conflicting metadata lock.
mysql-test/r/mdl_sync.result:
Added test for bug #46044 "MDL deadlock on LOCK TABLE + CREATE TABLE
HIGH_PRIORITY FOR UPDATE".
mysql-test/t/mdl_sync.test:
Added test for bug #46044 "MDL deadlock on LOCK TABLE + CREATE TABLE
HIGH_PRIORITY FOR UPDATE".
sql/mysql_priv.h:
Added a new flag for open_table() call which allows it to fail
with an error in cases when conflicting metadata lock is discovered
instead of waiting until this lock goes away.
sql/share/errmsg-utf8.txt:
Added error/warning message to be generated in cases when information
about table is omitted from I_S since there is conflicting metadata lock
on the table.
sql/share/errmsg.txt:
Added error/warning message to be generated in cases when information
about table is omitted from I_S since there is conflicting metadata lock
on the table.
sql/sql_base.cc:
Added a new flag for open_table() call which allows it to fail
with an error in cases when conflicting metadata lock is discovered
instead of waiting until this lock goes away.
sql/sql_show.cc:
When we are opening a table (or just .FRM) in order to fill I_S with
information about this table and encounter conflicting metadata lock
waiting for this lock to go away can lead to a deadlock in some
situations (under LOCK TABLES, within transaction, etc.). To avoid
these deadlocks we detect such situations and don't do waiting.
Instead, we skip table for which we have conflicting metadata lock,
thus omitting information about it from I_S table, and produce an
appropriate warning.
2009-12-09 18:48:42 +03:00
|
|
|
--echo #
|
|
|
|
--echo # Bug #46044 "MDL deadlock on LOCK TABLE + CREATE TABLE HIGH_PRIORITY
|
|
|
|
--echo # FOR UPDATE"
|
|
|
|
--echo #
|
|
|
|
--disable_warnings
|
|
|
|
drop tables if exists t1, t2;
|
|
|
|
--enable_warnings
|
|
|
|
connect (con46044, localhost, root,,);
|
|
|
|
connect (con46044_2, localhost, root,,);
|
|
|
|
connection default;
|
|
|
|
create table t1 (i int);
|
|
|
|
|
|
|
|
--echo # Let us check that we won't deadlock if during filling
|
|
|
|
--echo # of I_S table we encounter conflicting metadata lock
|
|
|
|
--echo # which owner is in its turn waiting for our connection.
|
|
|
|
lock tables t1 write;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044'.
|
|
|
|
connection con46044;
|
|
|
|
--echo # Sending:
|
|
|
|
--send create table t2 select * from t1;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'default'.
|
|
|
|
connection default;
|
|
|
|
--echo # Waiting until CREATE TABLE ... SELECT ... is blocked.
|
|
|
|
let $wait_condition=
|
|
|
|
select count(*) = 1 from information_schema.processlist
|
|
|
|
where state = "Table lock" and info = "create table t2 select * from t1";
|
|
|
|
--source include/wait_condition.inc
|
|
|
|
|
|
|
|
--echo # First let us check that SHOW FIELDS/DESCRIBE doesn't
|
|
|
|
--echo # gets blocked and emits and error.
|
|
|
|
--error ER_WARN_I_S_SKIPPED_TABLE
|
|
|
|
show fields from t2;
|
|
|
|
|
|
|
|
--echo # Now test for I_S query which reads only .FRMs.
|
|
|
|
--echo #
|
|
|
|
--echo # Query below should only emit a warning.
|
|
|
|
select column_name from information_schema.columns
|
|
|
|
where table_schema='test' and table_name='t2';
|
|
|
|
|
|
|
|
--echo # Finally, test for I_S query which does full-blown table open.
|
|
|
|
--echo #
|
|
|
|
--echo # Query below should not be blocked. Warning message should be
|
|
|
|
--echo # stored in the 'table_comment' column.
|
|
|
|
select table_name, table_type, auto_increment, table_comment
|
|
|
|
from information_schema.tables where table_schema='test' and table_name='t2';
|
|
|
|
|
|
|
|
--echo # Switching to connection 'default'.
|
|
|
|
connection default;
|
|
|
|
unlock tables;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044'.
|
|
|
|
connection con46044;
|
|
|
|
--echo # Reaping CREATE TABLE ... SELECT ... .
|
|
|
|
--reap
|
|
|
|
drop table t2;
|
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # Let us also check that queries to I_S wait for conflicting metadata
|
|
|
|
--echo # locks to go away instead of skipping table with a warning in cases
|
|
|
|
--echo # when deadlock is not possible. This is a nice thing from compatibility
|
|
|
|
--echo # and ease of use points of view.
|
|
|
|
--echo #
|
|
|
|
--echo # We check same three queries to I_S in this new situation.
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044_2'.
|
|
|
|
connection con46044_2;
|
|
|
|
lock tables t1 write;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044'.
|
|
|
|
connection con46044;
|
|
|
|
--echo # Sending:
|
|
|
|
--send create table t2 select * from t1;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'default'.
|
|
|
|
connection default;
|
|
|
|
--echo # Waiting until CREATE TABLE ... SELECT ... is blocked.
|
|
|
|
let $wait_condition=
|
|
|
|
select count(*) = 1 from information_schema.processlist
|
|
|
|
where state = "Table lock" and info = "create table t2 select * from t1";
|
|
|
|
--source include/wait_condition.inc
|
|
|
|
|
|
|
|
--echo # Let us check that SHOW FIELDS/DESCRIBE gets blocked.
|
|
|
|
--echo # Sending:
|
|
|
|
--send show fields from t2;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044_2'.
|
|
|
|
connection con46044_2;
|
|
|
|
--echo # Wait until SHOW FIELDS gets blocked.
|
|
|
|
let $wait_condition=
|
|
|
|
select count(*) = 1 from information_schema.processlist
|
|
|
|
where state = "Waiting for table" and info = "show fields from t2";
|
|
|
|
--source include/wait_condition.inc
|
|
|
|
|
|
|
|
unlock tables;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044'.
|
|
|
|
connection con46044;
|
|
|
|
--echo # Reaping CREATE TABLE ... SELECT ... .
|
|
|
|
--reap
|
|
|
|
|
|
|
|
--echo # Switching to connection 'default'.
|
|
|
|
connection default;
|
|
|
|
--echo # Reaping SHOW FIELDS ...
|
|
|
|
--reap
|
|
|
|
drop table t2;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044_2'.
|
|
|
|
connection con46044_2;
|
|
|
|
lock tables t1 write;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044'.
|
|
|
|
connection con46044;
|
|
|
|
--echo # Sending:
|
|
|
|
--send create table t2 select * from t1;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'default'.
|
|
|
|
connection default;
|
|
|
|
--echo # Waiting until CREATE TABLE ... SELECT ... is blocked.
|
|
|
|
let $wait_condition=
|
|
|
|
select count(*) = 1 from information_schema.processlist
|
|
|
|
where state = "Table lock" and info = "create table t2 select * from t1";
|
|
|
|
--source include/wait_condition.inc
|
|
|
|
|
|
|
|
--echo # Check that I_S query which reads only .FRMs gets blocked.
|
|
|
|
--echo # Sending:
|
|
|
|
--send select column_name from information_schema.columns where table_schema='test' and table_name='t2';
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044_2'.
|
|
|
|
connection con46044_2;
|
|
|
|
--echo # Wait until SELECT COLUMN_NAME FROM I_S.COLUMNS gets blocked.
|
|
|
|
let $wait_condition=
|
|
|
|
select count(*) = 1 from information_schema.processlist
|
|
|
|
where state = "Waiting for table" and
|
|
|
|
info like "select column_name from information_schema.columns%";
|
|
|
|
--source include/wait_condition.inc
|
|
|
|
|
|
|
|
unlock tables;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044'.
|
|
|
|
connection con46044;
|
|
|
|
--echo # Reaping CREATE TABLE ... SELECT ... .
|
|
|
|
--reap
|
|
|
|
|
|
|
|
--echo # Switching to connection 'default'.
|
|
|
|
connection default;
|
|
|
|
--echo # Reaping SELECT COLUMN_NAME FROM I_S.COLUMNS
|
|
|
|
--reap
|
|
|
|
drop table t2;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044_2'.
|
|
|
|
connection con46044_2;
|
|
|
|
lock tables t1 write;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044'.
|
|
|
|
connection con46044;
|
|
|
|
--echo # Sending:
|
|
|
|
--send create table t2 select * from t1;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'default'.
|
|
|
|
connection default;
|
|
|
|
--echo # Waiting until CREATE TABLE ... SELECT ... is blocked.
|
|
|
|
let $wait_condition=
|
|
|
|
select count(*) = 1 from information_schema.processlist
|
|
|
|
where state = "Table lock" and info = "create table t2 select * from t1";
|
|
|
|
--source include/wait_condition.inc
|
|
|
|
|
|
|
|
--echo # Finally, check that I_S query which does full-blown table open
|
|
|
|
--echo # also gets blocked.
|
|
|
|
--echo # Sending:
|
|
|
|
--send select table_name, table_type, auto_increment, table_comment from information_schema.tables where table_schema='test' and table_name='t2';
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044_2'.
|
|
|
|
connection con46044_2;
|
|
|
|
--echo # Wait until SELECT ... FROM I_S.TABLES gets blocked.
|
|
|
|
let $wait_condition=
|
|
|
|
select count(*) = 1 from information_schema.processlist
|
|
|
|
where state = "Waiting for table" and
|
|
|
|
info like "select table_name, table_type, auto_increment, table_comment from information_schema.tables%";
|
|
|
|
--source include/wait_condition.inc
|
|
|
|
|
|
|
|
unlock tables;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46044'.
|
|
|
|
connection con46044;
|
|
|
|
--echo # Reaping CREATE TABLE ... SELECT ... .
|
|
|
|
--reap
|
|
|
|
|
|
|
|
--echo # Switching to connection 'default'.
|
|
|
|
connection default;
|
|
|
|
--echo # Reaping SELECT ... FROM I_S.TABLES
|
|
|
|
--reap
|
|
|
|
drop table t2;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'default'.
|
|
|
|
connection default;
|
|
|
|
--echo # Clean-up.
|
|
|
|
disconnect con46044;
|
|
|
|
disconnect con46044_2;
|
|
|
|
drop table t1;
|
|
|
|
|
2009-12-09 18:56:34 +03:00
|
|
|
|
|
|
|
--echo #
|
|
|
|
--echo # Test for bug #46673 "Deadlock between FLUSH TABLES WITH READ LOCK
|
|
|
|
--echo # and DML".
|
|
|
|
--echo #
|
|
|
|
--disable_warnings
|
|
|
|
drop tables if exists t1;
|
|
|
|
--enable_warnings
|
|
|
|
connect (con46673, localhost, root,,);
|
|
|
|
connection default;
|
|
|
|
create table t1 (i int);
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46673'.
|
|
|
|
connection con46673;
|
|
|
|
begin;
|
|
|
|
insert into t1 values (1);
|
|
|
|
|
|
|
|
--echo # Switching to connection 'default'.
|
|
|
|
connection default;
|
|
|
|
--echo # Statement below should not get blocked. And if after some
|
|
|
|
--echo # changes to code it is there should not be a deadlock between
|
|
|
|
--echo # it and transaction from connection 'con46673'.
|
|
|
|
flush tables with read lock;
|
|
|
|
unlock tables;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'con46673'.
|
|
|
|
connection con46673;
|
|
|
|
delete from t1 where i = 1;
|
|
|
|
commit;
|
|
|
|
|
|
|
|
--echo # Switching to connection 'default'.
|
|
|
|
connection default;
|
|
|
|
--echo # Clean-up
|
|
|
|
disconnect con46673;
|
|
|
|
drop table t1;
|
|
|
|
|
|
|
|
|
2009-12-09 12:44:05 +03:00
|
|
|
# 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
|