Skip to content

Commit ea91553

Browse files
author
Dmitry Lenev
committed
Implement new type-of-operation-aware metadata locks.
Add a wait-for graph based deadlock detector to the MDL subsystem. Fixes bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock" and bug #37346 "innodb does not detect deadlock between update and alter table". The first bug manifested itself as an unwarranted abort of a transaction with ER_LOCK_DEADLOCK error by a concurrent ALTER statement, when this transaction tried to repeat use of a table, which it has already used in a similar fashion before ALTER started. The second bug showed up as a deadlock between table-level locks and InnoDB row locks, which was "detected" only after innodb_lock_wait_timeout timeout. A transaction would start using the table and modify a few rows. Then ALTER TABLE would come in, and start copying rows into a temporary table. Eventually it would stumble on the modified records and get blocked on a row lock. The first transaction would try to do more updates, and get blocked on thr_lock.c lock. This situation of circular wait would only get resolved by a timeout. Both these bugs stemmed from inadequate solutions to the problem of deadlocks occurring between different locking subsystems. In the first case we tried to avoid deadlocks between metadata locking and table-level locking subsystems, when upgrading shared metadata lock to exclusive one. Transactions holding the shared lock on the table and waiting for some table-level lock used to be aborted too aggressively. We also allowed ALTER TABLE to start in presence of transactions that modify the subject table. ALTER TABLE acquires TL_WRITE_ALLOW_READ lock at start, and that block all writes against the table (naturally, we don't want any writes to be lost when switching the old and the new table). TL_WRITE_ALLOW_READ lock, in turn, would block the started transaction on thr_lock.c lock, should they do more updates. This, again, lead to the need to abort such transactions. The second bug occurred simply because we didn't have any mechanism to detect deadlocks between the table-level locks in thr_lock.c and row-level locks in InnoDB, other than innodb_lock_wait_timeout. This patch solves both these problems by moving lock conflicts which are causing these deadlocks into the metadata locking subsystem, thus making it possible to avoid or detect such deadlocks inside MDL. To do this we introduce new type-of-operation-aware metadata locks, which allow MDL subsystem to know not only the fact that transaction has used or is going to use some object but also what kind of operation it has carried out or going to carry out on the object. This, along with the addition of a special kind of upgradable metadata lock, allows ALTER TABLE to wait until all transactions which has updated the table to go away. This solves the second issue. Another special type of upgradable metadata lock is acquired by LOCK TABLE WRITE. This second lock type allows to solve the first issue, since abortion of table-level locks in event of DDL under LOCK TABLES becomes also unnecessary. Below follows the list of incompatible changes introduced by this patch: - From now on, ALTER TABLE and CREATE/DROP TRIGGER SQL (i.e. those statements that acquire TL_WRITE_ALLOW_READ lock) wait for all transactions which has *updated* the table to complete. - From now on, LOCK TABLES ... WRITE, REPAIR/OPTIMIZE TABLE (i.e. all statements which acquire TL_WRITE table-level lock) wait for all transaction which *updated or read* from the table to complete. As a consequence, innodb_table_locks=0 option no longer applies to LOCK TABLES ... WRITE. - DROP DATABASE, DROP TABLE, RENAME TABLE no longer abort statements or transactions which use tables being dropped or renamed, and instead wait for these transactions to complete. - Since LOCK TABLES WRITE now takes a special metadata lock, not compatible with with reads or writes against the subject table and transaction-wide, thr_lock.c deadlock avoidance algorithm that used to ensure absence of deadlocks between LOCK TABLES WRITE and other statements is no longer sufficient, even for MyISAM. The wait-for graph based deadlock detector of MDL subsystem may sometimes be necessary and is involved. This may lead to ER_LOCK_DEADLOCK error produced for multi-statement transactions even if these only use MyISAM: session 1: session 2: begin; update t1 ... lock table t2 write, t1 write; -- gets a lock on t2, blocks on t1 update t2 ... (ER_LOCK_DEADLOCK) - Finally, support of LOW_PRIORITY option for LOCK TABLES ... WRITE was abandoned. LOCK TABLE ... LOW_PRIORITY WRITE from now on has the same priority as the usual LOCK TABLE ... WRITE. SELECT HIGH PRIORITY no longer trumps LOCK TABLE ... WRITE in the wait queue. - We do not take upgradable metadata locks on implicitly locked tables. So if one has, say, a view v1 that uses table t1, and issues: LOCK TABLE v1 WRITE; FLUSH TABLE t1; -- (or just 'FLUSH TABLES'), an error is produced. In order to be able to perform DDL on a table under LOCK TABLES, the table must be locked explicitly in the LOCK TABLES list. --BZR-- revision-id: [email protected] property-branch-nick: mysql-next-4284-nl-push property-file-info: ld7:file_id65:sp1f-handler.test-20010406221832-gfvg6n4rp4py6lunazzembziuu5qxvi57:message601:Adjusted test case to trigger an execution path on which bug 41110 property-file-info: "crash with handler command when used concurrently with alter property-file-info: table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data property-file-info: with alter table" were originally discovered. Left old test case property-file-info: which no longer triggers this execution path for the sake of property-file-info: coverage. property-file-info: Added test coverage for HANDLER SQL statements and type-aware property-file-info: metadata locks. property-file-info: Added a test for the global shared lock and HANDLER SQL. property-file-info: Updated tests to take into account that the old simple deadlock property-file-info: detection heuristics was replaced with a graph-based deadlock property-file-info: detector.4:path30:mysql-test/include/handler.inced7:file_id51:debug_sync.result-20090925124518-2m0htks1bbp5jaf5-27:message38:Updated results (see debug_sync.test).4:path30:mysql-test/r/debug_sync.resulted7:file_id73:sp1f-innodb_handler.resul-20020821205505-jopsqbjuqwwxb5hvf3r2wn37vobunxru7:message39:Updated results (see handler.inc test).4:path34:mysql-test/r/handler_innodb.resulted7:file_id67:sp1f-handler.result-20010406221832-ybo3cgjo6qapqc6776ivjpdngwmk6plu7:message39:Updated results (see handler.inc test).4:path34:mysql-test/r/handler_myisam.resulted7:file_id70:sp1f-innodblock.result-20040429134230-i3dq3yx3lvsutqlypaqgv45wtanr6s6r7:message39:Updated results (see innodb-lock.test).4:path31:mysql-test/r/innodb-lock.resulted7:file_id54:innodb_mysql_lock.re-20090708120319-55a6h1vcofl3qyco-17:message45:Updated results (see innodb_mysql_lock.test).4:path37:mysql-test/r/innodb_mysql_lock.resulted7:file_id64:sp1f-lock.result-20010327100548-v7vnhudpyvpujzoumsnowmqxa26ojsji7:message32:Updated results (see lock.test).4:path24:mysql-test/r/lock.resulted7:file_id70:sp1f-lock_multi.result-20011008015806-j56mw7cxenwk7wmwzgciunzotxn2oopp7:message38:Updated results (see lock_multi.test).4:path30:mysql-test/r/lock_multi.resulted7:file_id50:lock_sync.result-20091026185321-a3yhtolup4w2s1qf-17:message37:Updated results (see lock_sync.test).4:path29:mysql-test/r/lock_sync.resulted7:file_id49:mdl_sync.result-20090302184602-k11i6o8vh2s5umno-17:message36:Updated results (see mdl_sync.test).4:path28:mysql-test/r/mdl_sync.resulted7:file_id69:sp1f-spthreads.result-20040806161110-wbricurkbmq374o7blz3jumgdb67bqwu7:message133:SHOW PROCESSLIST output has changed due to the fact that waiting property-file-info: for LOCK TABLES WRITE now happens within metadata locking property-file-info: subsystem.4:path30:mysql-test/r/sp-threads.resulted7:file_id54:truncate_coverage.re-20090721163847-yburwvu68nh9l5ds-17:message45:Updated results (see truncate_coverage.test).4:path37:mysql-test/r/truncate_coverage.resulted7:file_id72:sp1f-processlist_val.inc-20070815194641-3hfsmyh3jr2gjhvgms52iydpkamdbnoz7:message140:SELECT FROM I_S.PROCESSLIST output has changed due to fact that property-file-info: waiting for LOCK TABLES WRITE now happens within metadata locking property-file-info: subsystem.4:path53:mysql-test/suite/funcs_1/datadict/processlist_val.inced7:file_id73:sp1f-a_processlist_val_no-20070815194641-puz2vi6caqirb4nqzumushorqyuniraq7:message140:SELECT FROM I_S.PROCESSLIST output has changed due to fact that property-file-info: waiting for LOCK TABLES WRITE now happens within metadata locking property-file-info: subsystem.4:path57:mysql-test/suite/funcs_1/r/processlist_val_no_prot.resulted7:file_id64:sp1f-rpl_sp.test-20050505122048-sfpoerdz7zbb5decjlbpxcme6ew43qcp7:message45:Updated to a new SHOW PROCESSLIST state name.4:path34:mysql-test/suite/rpl/t/rpl_sp.tested7:file_id49:debug_sync.test-20090925124518-2m0htks1bbp5jaf5-47:message205:Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter property-file-info: no longer allows to trigger execution path involving waiting on property-file-info: thr_lock.c lock and therefore reaching debug sync-point covered property-file-info: by this test.4:path28:mysql-test/t/debug_sync.tested7:file_id68:sp1f-innodblock.test-20040429134230-ml3z54sjjeakf7rmih6oauxeqq67337r7:message159:Adjusted test case to the fact that innodb_table_locks=0 option is property-file-info: no longer supported, since LOCK TABLES WRITE handles all its property-file-info: conflicts within MDL subsystem.4:path29:mysql-test/t/innodb-lock.tested7:file_id54:innodb_mysql_lock.te-20090708120331-rlixkpo3dev1mlo7-17:message91:Added test for bug #37346 "innodb does not detect deadlock between property-file-info: update and alter table".4:path35:mysql-test/t/innodb_mysql_lock.tested7:file_id62:sp1f-lock.test-20010327100548-76bepwa6zhtmrjdgc6vpqv36ggjvnp3t7:message171:Added test coverage which checks the fact that we no longer support property-file-info: DDL under LOCK TABLES on tables which were locked implicitly. property-file-info: Adjusted existing test cases accordingly.4:path22:mysql-test/t/lock.tested7:file_id68:sp1f-lock_multi.test-20011008015806-67rpwlsigaymaevma2l42r5edbtot3fp7:message201:Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary property-file-info: deadlock". Adjusted other test cases to take into account the property-file-info: fact that waiting for LOCK TABLES ... WRITE now happens within MDL property-file-info: subsystem.4:path28:mysql-test/t/lock_multi.tested7:file_id48:lock_sync.test-20091026185315-9p2a80gl4ah39te2-17:message225:Since LOCK TABLES ... WRITE now takes SNRW metadata lock for property-file-info: tables locked explicitly we have to implicitly lock InnoDB tables property-file-info: (through view) to trigger the table-level lock conflict between property-file-info: TL_WRITE and TL_WRITE_ALLOW_WRITE.4:path27:mysql-test/t/lock_sync.tested7:file_id47:mdl_sync.test-20090302184558-2nfnp7wh7pj6ra6e-17:message244:Added basic test coverage for type-of-operation-aware metadata property-file-info: locks. Also covered with tests some use cases involving HANDLER property-file-info: statements in which a deadlock could arise. property-file-info: Adjusted existing tests to take type-of-operation-aware MDL into property-file-info: account.4:path26:mysql-test/t/mdl_sync.tested7:file_id70:sp1f-multi_update.test-20010611232825-wkkm3vvyawipiowjzwqmkqegx6wd6aiw7:message44:Update to a new SHOW PROCESSLIST state name.4:path30:mysql-test/t/multi_update.tested7:file_id54:truncate_coverage.te-20090721163847-yburwvu68nh9l5ds-27:message172:Adjusted test case after making LOCK TABLES WRITE to wait until property-file-info: transactions that use the table to be locked are completed. property-file-info: Updated to the changed name of DEBUG_SYNC point.4:path35:mysql-test/t/truncate_coverage.tested7:file_id63:sp1f-handler.cc-19700101030959-ta6zfrlbxzucylciyro3musjsdpocrdh7:message59:Global read lock functionality has been property-file-info: moved into a class.4:path14:sql/handler.cced7:file_id60:sp1f-lock.cc-19700101030959-lzrt5tyolna3dcihuenjh7nlicr7llt77:message96:Global read lock functionality has been property-file-info: moved into a class. property-file-info: Updated code to use the new MDL API.4:path11:sql/lock.cced7:file_id40:mdl.cc-20080523121737-j62pi0m62eaw1hq6-17:message1601:Introduced new type-of-operation aware metadata locks. property-file-info: To do this: property-file-info: - Changed MDL_lock to use one list for waiting requests and one property-file-info: list for granted requests. For each list, added a bitmap property-file-info: that holds information what lock types a list contains. property-file-info: Added a helper class MDL_lock::List to manipulate with granted property-file-info: and waited lists while keeping the bitmaps in sync property-file-info: with list contents. property-file-info: - Changed lock-compatibility functions to use bitmaps that property-file-info: define compatibility. property-file-info: - Introduced a graph based deadlock detector inspired by property-file-info: waiting_threads.c from Maria implementation. property-file-info: - Now that we have a deadlock detector, and no longer have property-file-info: a global lock to protect individual lock objects, but rather property-file-info: use an rw lock per object, removed redundant code for upgrade, property-file-info: and the global read lock. Changed the MDL API to property-file-info: no longer require the caller to acquire the global property-file-info: intention exclusive lock by means of a separate method. property-file-info: Removed a few more methods that became redundant. property-file-info: - Removed deadlock detection heuristic, it has been made property-file-info: obsolete by the deadlock detector. property-file-info: - With operation-type-aware metadata locks, MDL subsystem has property-file-info: become aware of potential conflicts between DDL and open property-file-info: transactions. This made it possible to remove calls to property-file-info: mysql_abort_transactions_with_shared_lock() from acquisition property-file-info: paths for exclusive lock and lock upgrade. Now we can simply property-file-info: wait for these transactions to complete without fear of property-file-info: deadlock. Function mysql_lock_abort() has also become property-file-info: unnecessary for all conflicting cases except when a DDL property-file-info: conflicts with a connection that has an open HANDLER.4:path10:sql/mdl.cced7:file_id39:mdl.h-20080523121748-o4y2wcq3maotb9do-17:message301:Introduced new type-of-operation aware metadata locks. property-file-info: Introduced a graph based deadlock detector and supporting property-file-info: methods. property-file-info: Added comments. property-file-info: God rid of redundant API calls. property-file-info: Renamed m_lt_or_ha_sentinel to m_trans_sentinel, property-file-info: since now it guards the global read lock as well as property-file-info: LOCK TABLES and HANDLER locks.4:path9:sql/mdl.hed7:file_id65:sp1f-mysql_priv.h-19700101030959-4fl65tqpop5zfgxaxkqotu2fa2ree5ci7:message334:Moved the global read lock functionality into a property-file-info: class. property-file-info: Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces property-file-info: open_tables() to take MDL_SHARED on tables instead of property-file-info: metadata locks specified in the parser. We use this to property-file-info: allow PREPARE run concurrently in presence of property-file-info: LOCK TABLES ... WRITE. property-file-info: Added signature for find_table_for_mdl_ugprade().4:path16:sql/mysql_priv.hed7:file_id63:sp1f-set_var.cc-20020723153119-nwbpg2pwpz55pfw7yfzaxt7hsszzy7y37:message59:Global read lock functionality has been property-file-info: moved into a class.4:path14:sql/set_var.cced7:file_id63:sp1f-sp_head.cc-20021208185920-jtgc5wvyqdnu2gvcdus3gazrfhxbofxd7:message171:When creating TABLE_LIST elements for prelocking or property-file-info: system tables set the type of request for metadata property-file-info: lock according to the operation that will be performed property-file-info: on the table.4:path14:sql/sp_head.cced7:file_id64:sp1f-sql_base.cc-19700101030959-w7tul2gb2n4jzayjwlslj3ybmf3uhk6a7:message988:- Updated code to use the new MDL API. property-file-info: - In order to avoid locks starvation we take upgradable property-file-info: locks all at once. As result implicitly locked tables no property-file-info: longer get an upgradable lock. Consequently DDL and FLUSH property-file-info: TABLES for such tables is prohibited. property-file-info: find_write_locked_table() was replaced by property-file-info: find_table_for_mdl_upgrade() function. property-file-info: open_table() was adjusted to return TABLE instance with property-file-info: upgradable ticket when necessary. property-file-info: - We no longer wait for all locks on OT_WAIT back off property-file-info: action -- only on the lock that caused the wait property-file-info: conflict. Moreover, now we distinguish cases when we property-file-info: have to wait due to conflict in MDL and old version property-file-info: of table in TDC. property-file-info: - Upate mysql_notify_threads_having_share_locks() property-file-info: to only abort thr_lock.c waits of threads that property-file-info: have open HANDLERs, since lock conflicts with only property-file-info: these threads now can lead to deadlocks not detectable property-file-info: by the MDL deadlock detector. property-file-info: - Remove mysql_abort_transactions_with_shared_locks() property-file-info: which is no longer needed.4:path15:sql/sql_base.cced7:file_id65:sp1f-sql_class.cc-19700101030959-rpotnweaff2pikkozh3butrf7mv3oero7:message114:Global read lock functionality has been moved into a class. property-file-info: Re-arranged code in THD::cleanup() to simplify assert.4:path16:sql/sql_class.cced7:file_id64:sp1f-sql_class.h-19700101030959-jnqnbrjyqsvgncsibnumsmg3lyi7pa5s7:message190:Introduced class to incapsulate global read lock property-file-info: functionality. property-file-info: Now sentinel in MDL subsystem guards the global read lock property-file-info: as well as LOCK TABLES and HANDLER locks. Adjusted code property-file-info: accordingly.4:path15:sql/sql_class.hed7:file_id62:sp1f-sql_db.cc-19700101030959-hyw6zjuisjyda5cj5746a2zzuzz5yibr7:message59:Global read lock functionality has been moved into a class.4:path13:sql/sql_db.cced7:file_id66:sp1f-sql_delete.cc-19700101030959-ch2a6r6ushvc2vfwxt7ehcjuplelwthr7:message200:We no longer acquire upgradable metadata locks on tables property-file-info: which are locked by LOCK TABLES implicitly. As result property-file-info: TRUNCATE TABLE is no longer allowed for such tables. property-file-info: Updated code to use the new MDL API.4:path17:sql/sql_delete.cced7:file_id67:sp1f-sql_handler.cc-20010406221833-l4tsiortoyipmoyajcoz2tcdppvyeltl7:message281:Inform MDL_context about presence of open HANDLERs. property-file-info: Since HANLDERs break MDL protocol by acquiring table-level property-file-info: lock while holding only S metadata lock on a table MDL property-file-info: subsystem should take special care about such contexts (Now property-file-info: this is the only case when mysql_lock_abort() is used).4:path18:sql/sql_handler.cced7:file_id65:sp1f-sql_parse.cc-19700101030959-ehcre3rwhv5l3mlxqhaxg36ujenxnrcd7:message530:Global read lock functionality has been moved into a class. property-file-info: Do not take upgradable metadata locks when opening tables property-file-info: for CREATE TABLE SELECT as it is not necessary and limits property-file-info: concurrency. property-file-info: When initializing TABLE_LIST objects before adding them property-file-info: to the table list set the type of request for metadata lock property-file-info: according to the operation that will be performed on the property-file-info: table. property-file-info: We no longer acquire upgradable metadata locks on tables property-file-info: which are locked by LOCK TABLES implicitly. As result FLUSH property-file-info: TABLES is no longer allowed for such tables.4:path16:sql/sql_parse.cced7:file_id67:sp1f-sql_prepare.cc-20020612210720-gtqjjiu7vpmfxb5xct2qke7urmqcabli7:message150:Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening property-file-info: tables during PREPARE. This allows PREPARE to run property-file-info: concurrently in presence of LOCK TABLES ... WRITE.4:path18:sql/sql_prepare.cced7:file_id66:sp1f-sql_rename.cc-20000821000147-ltbepgfv52umnrkaxzycedl5p2tlr3fp7:message59:Global read lock functionality has been moved into a class.4:path17:sql/sql_rename.cced7:file_id64:sp1f-sql_show.cc-19700101030959-umlljfnpplg452h7reeyqr4xnbmlkvfj7:message36:Updated code to use the new MDL API.4:path15:sql/sql_show.cced7:file_id65:sp1f-sql_table.cc-19700101030959-tzdkvgigezpuaxnldqh3fx2h7h2ggslu7:message256:Global read lock functionality has been moved into a class. property-file-info: We no longer acquire upgradable metadata locks on tables property-file-info: which are locked by LOCK TABLES implicitly. As result DROP property-file-info: TABLE is no longer allowed for such tables. property-file-info: Updated code to use the new MDL API.4:path16:sql/sql_table.cced7:file_id67:sp1f-sql_trigger.cc-20040907122911-35k3wamrp6g7qsupxe7hisftpobcwin57:message265:Global read lock functionality has been moved into a class. property-file-info: We no longer acquire upgradable metadata locks on tables property-file-info: which are locked by LOCK TABLES implicitly. As result property-file-info: CREATE/DROP TRIGGER is no longer allowed for such tables. property-file-info: Updated code to use the new MDL API.4:path18:sql/sql_trigger.cced7:file_id64:sp1f-sql_view.cc-20040715221517-nw4p4mja6nzzlvwwhzfgfqb4umxqobe47:message168:Global read lock functionality has been moved into a class. property-file-info: Fixed results of wrong merge that led to misuse of GLR API. property-file-info: CREATE VIEW statement is not a commit statement.4:path15:sql/sql_view.cced7:file_id61:sp1f-table.cc-19700101030959-nsxtem2adyqzwe6nz4cgrpcmts3o54v77:message252:When resetting TABLE_LIST objects for PS or SP re-execution property-file-info: set the type of request for metadata lock according to the property-file-info: operation that will be performed on the table. Do the same property-file-info: in auxiliary function initializing metadata lock requests property-file-info: in a table list.4:path12:sql/table.cced7:file_id60:sp1f-table.h-19700101030959-dv72bajftxj5fbdjuajquappanuv2ija7:message142:When initializing TABLE_LIST objects set the type of request property-file-info: for metadata lock according to the operation that will be property-file-info: performed on the table.4:path11:sql/table.hed7:file_id48:transaction.cc-20080807231139-0scowboulgaz4j08-17:message59:Global read lock functionality has been moved into a class.4:path18:sql/transaction.ccee testament3-sha1: 8d45c0a2701c7477d33c106611e1f97c4c824a8c
1 parent dea880d commit ea91553

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+6707
-1810
lines changed

mysql-test/include/handler.inc

Lines changed: 156 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -732,21 +732,48 @@ connection default;
732732
--disable_warnings
733733
drop table if exists t1;
734734
--enable_warnings
735-
create table t1 (a int, key a (a));
735+
--echo # First test case which is supposed trigger the execution
736+
--echo # path on which problem was discovered.
737+
create table t1 (a int);
736738
insert into t1 values (1);
737739
handler t1 open;
738740
connection con1;
741+
lock table t1 write;
739742
send alter table t1 engine=memory;
740743
connection con2;
741744
let $wait_condition=
742745
select count(*) = 1 from information_schema.processlist
743746
where state = "Waiting for table" and info = "alter table t1 engine=memory";
744747
--source include/wait_condition.inc
745748
connection default;
749+
--error ER_ILLEGAL_HA
746750
handler t1 read a next;
747751
handler t1 close;
748752
connection con1;
749753
--reap
754+
unlock tables;
755+
drop table t1;
756+
--echo # Now test case which was reported originally but which no longer
757+
--echo # triggers execution path which has caused the problem.
758+
connection default;
759+
create table t1 (a int, key(a));
760+
insert into t1 values (1);
761+
handler t1 open;
762+
connection con1;
763+
send alter table t1 engine=memory;
764+
connection con2;
765+
let $wait_condition=
766+
select count(*) = 1 from information_schema.processlist
767+
where state = "Waiting for table" and info = "alter table t1 engine=memory";
768+
--source include/wait_condition.inc
769+
connection default;
770+
--echo # Since S metadata lock was already acquired at HANDLER OPEN time
771+
--echo # and TL_READ lock requested by HANDLER READ is compatible with
772+
--echo # ALTER's TL_WRITE_ALLOW_READ the below statement should succeed
773+
--echo # without waiting. The old version of table should be used in it.
774+
handler t1 read a next;
775+
handler t1 close;
776+
connection con1;
750777
drop table t1;
751778
disconnect con1;
752779
--source include/wait_until_disconnected.inc
@@ -1228,15 +1255,27 @@ create table t2 like t1;
12281255
handler t1 open;
12291256
--echo # --> connection con1
12301257
connection con1;
1231-
lock table t2 read;
1258+
lock table t1 write, t2 write;
12321259
--echo # --> connection default
12331260
connection default;
1261+
send drop table t2;
1262+
--echo # --> connection con2
1263+
connection con2;
1264+
--echo # Waiting for 'drop table t2' to get blocked...
1265+
let $wait_condition=select count(*)=1 from information_schema.processlist where state='Waiting for table' and info='drop table t2';
1266+
--source include/wait_condition.inc
1267+
--echo # --> connection con1
1268+
connection con1;
12341269
--error ER_LOCK_DEADLOCK
1235-
drop table t2;
1236-
--error ER_LOCK_DEADLOCK
1237-
rename table t2 to t3;
1270+
drop table t1;
1271+
unlock tables;
1272+
--echo # --> connection default
1273+
connection default;
1274+
reap;
1275+
12381276
--echo # Demonstrate that there is no deadlock with FLUSH TABLE,
12391277
--echo # even though it is waiting for the other table to go away
1278+
create table t2 like t1;
12401279
--echo # Sending:
12411280
--send flush table t2
12421281
--echo # --> connection con2
@@ -1256,6 +1295,7 @@ drop table t2;
12561295
--echo # lead to deadlocks
12571296
--echo #
12581297
create table t1 (a int, key a(a));
1298+
insert into t1 values (1), (2);
12591299

12601300
--echo # --> connection default
12611301
connection default;
@@ -1265,7 +1305,31 @@ handler t1 open;
12651305

12661306
--echo # --> connection con1
12671307
connection con1;
1268-
lock tables t1 write;
1308+
--echo # Sending:
1309+
--send lock tables t1 write
1310+
1311+
--echo # --> connection con2
1312+
connection con2;
1313+
--echo # Check that 'lock tables t1 write' waits until transaction which
1314+
--echo # has read from the table commits.
1315+
let $wait_condition=
1316+
select count(*) = 1 from information_schema.processlist
1317+
where state = "Waiting for table" and info = "lock tables t1 write";
1318+
--source include/wait_condition.inc
1319+
1320+
--echo # --> connection default
1321+
connection default;
1322+
--echo # The below 'handler t1 read ...' should not be blocked as
1323+
--echo # 'lock tables t1 write' has not succeeded yet.
1324+
handler t1 read a next;
1325+
1326+
--echo # Unblock 'lock tables t1 write'.
1327+
commit;
1328+
1329+
--echo # --> connection con1
1330+
connection con1;
1331+
--echo # Reap 'lock tables t1 write'.
1332+
--reap
12691333

12701334
--echo # --> connection default
12711335
connection default;
@@ -1279,29 +1343,18 @@ let $wait_condition=
12791343
select count(*) = 1 from information_schema.processlist
12801344
where state = "Table lock" and info = "handler t1 read a next";
12811345
--source include/wait_condition.inc
1282-
--echo # Sending:
1283-
--send drop table t1
12841346

1285-
--echo # --> connection con2
1286-
connection con2;
1287-
--echo # Waiting for 'drop table t1' to get blocked...
1288-
let $wait_condition=
1289-
select count(*) = 1 from information_schema.processlist
1290-
where state = "Waiting for table" and info = "drop table t1";
1291-
--source include/wait_condition.inc
1347+
--echo # The below 'drop table t1' should be able to proceed without
1348+
--echo # waiting as it will force HANDLER to be closed.
1349+
drop table t1;
1350+
unlock tables;
12921351

12931352
--echo # --> connection default
12941353
connection default;
12951354
--echo # Reaping 'handler t1 read a next'...
1296-
--error ER_LOCK_DEADLOCK
1355+
--error ER_NO_SUCH_TABLE
12971356
--reap
12981357
handler t1 close;
1299-
commit;
1300-
1301-
--echo # --> connection con1
1302-
connection con1;
1303-
--echo # Reaping 'drop table t1'...
1304-
--reap
13051358

13061359
--echo # --> connection con1
13071360
connection con1;
@@ -1357,3 +1410,84 @@ rename table t4 to t5, t3 to t4, t5 to t3;
13571410
handler t1 read first;
13581411
handler t2 read first;
13591412
drop table t1, t2, t3, t4;
1413+
1414+
--echo #
1415+
--echo # A test for FLUSH TABLES WITH READ LOCK and HANDLER statements.
1416+
--echo #
1417+
set autocommit=0;
1418+
create table t1 (a int, b int, key a (a));
1419+
insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
1420+
create table t2 like t1;
1421+
insert into t2 (a, b) select a, b from t1;
1422+
create table t3 like t1;
1423+
insert into t3 (a, b) select a, b from t1;
1424+
commit;
1425+
flush tables with read lock;
1426+
handler t1 open;
1427+
lock table t1 read;
1428+
--error ER_LOCK_OR_ACTIVE_TRANSACTION
1429+
handler t1 read next;
1430+
--echo # This implicitly leaves LOCK TABLES but doesn't drop the GLR
1431+
--error ER_NO_SUCH_TABLE
1432+
lock table not_exists_write read;
1433+
--echo # We still have the read lock.
1434+
--error ER_CANT_UPDATE_WITH_READLOCK
1435+
drop table t1;
1436+
handler t1 open;
1437+
select a from t2;
1438+
handler t1 read next;
1439+
flush tables with read lock;
1440+
handler t2 open;
1441+
flush tables with read lock;
1442+
handler t1 read next;
1443+
select a from t3;
1444+
handler t2 read next;
1445+
handler t1 close;
1446+
rollback;
1447+
handler t2 close;
1448+
--error ER_CANT_UPDATE_WITH_READLOCK
1449+
drop table t1;
1450+
commit;
1451+
flush tables;
1452+
--error ER_CANT_UPDATE_WITH_READLOCK
1453+
drop table t1;
1454+
unlock tables;
1455+
drop table t1;
1456+
set autocommit=default;
1457+
drop table t2, t3;
1458+
1459+
--echo #
1460+
--echo # HANDLER statement and operation-type aware metadata locks.
1461+
--echo # Check that when we clone a ticket for HANDLER we downrade
1462+
--echo # the lock.
1463+
--echo #
1464+
--echo # Establish an auxiliary connection con1.
1465+
connect (con1,localhost,root,,);
1466+
--echo # -> connection default
1467+
connection default;
1468+
create table t1 (a int, b int, key a (a));
1469+
insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
1470+
begin;
1471+
insert into t1 (a, b) values (6, 6);
1472+
handler t1 open;
1473+
handler t1 read a last;
1474+
insert into t1 (a, b) values (7, 7);
1475+
handler t1 read a last;
1476+
commit;
1477+
--echo # -> connection con1
1478+
connection con1;
1479+
--echo # Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
1480+
lock table t1 write;
1481+
unlock tables;
1482+
--echo # -> connection default
1483+
connection default;
1484+
handler t1 read a prev;
1485+
handler t1 close;
1486+
--echo # Cleanup.
1487+
drop table t1;
1488+
--echo # -> connection con1
1489+
connection con1;
1490+
disconnect con1;
1491+
--source include/wait_until_disconnected.inc
1492+
--echo # -> connection default
1493+
connection default;

mysql-test/r/debug_sync.result

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ DROP TABLE t1;
263263
SET DEBUG_SYNC= 'RESET';
264264
DROP TABLE IF EXISTS t1;
265265
CREATE TABLE t1 (c1 INT);
266-
LOCK TABLE t1 WRITE;
266+
LOCK TABLE t1 READ;
267267
connection con1
268268
SET DEBUG_SYNC= 'wait_for_lock SIGNAL locked EXECUTE 2';
269269
INSERT INTO t1 VALUES (1);

0 commit comments

Comments
 (0)