mariadb/mysql-test/suite/handler/handler.inc

1612 lines
41 KiB
PHP
Raw Normal View History

- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
# handler.inc
This changeset belongs to WL#3397 Refactoring storage engine test cases (for falcon) It contains also fixes according to code review. Contents: Testcases which were in history dedicated to InnoDB or MyISAM only. Modifications: 1. Shift the main testing code into include/<testing field>.inc Introduce $variables which can be used to omit tests for features which are not supported by certain storage engines. 2. The storage engine to be tested is assigned within the toplevel script (t/<whatever>_<engine>.test) via variable $engine_type and the the main testing code is sourced from include/<testing field>.inc 3. Some toplevel testscripts have to be renamed to - avoid immediate or future namespace clashes - show via filename which storage engine is tested 4. Minor code cleanup like remove trailing spaces, some additional comments .... mysql-test/t/unsafe_binlog_innodb-master.opt: Rename: mysql-test/t/innodb_unsafe_binlog-master.opt -> mysql-test/t/unsafe_binlog_innodb-master.opt mysql-test/r/read_many_rows_innodb.result: Rename: mysql-test/r/innodb-big.result -> mysql-test/r/read_many_rows_innodb.result mysql-test/t/cache_innodb-master.opt: Rename: mysql-test/t/innodb_cache-master.opt -> mysql-test/t/cache_innodb-master.opt mysql-test/t/concurrent_innodb-master.opt: Rename: mysql-test/t/innodb_concurrent-master.opt -> mysql-test/t/concurrent_innodb-master.opt BitKeeper/deleted/.del-index_merge.result: Delete: mysql-test/r/index_merge.result BitKeeper/deleted/.del-index_merge_innodb.result: Delete: mysql-test/r/index_merge_innodb.result BitKeeper/deleted/.del-index_merge_innodb2.result: Delete: mysql-test/r/index_merge_innodb2.result BitKeeper/deleted/.del-index_merge_ror.result: Delete: mysql-test/r/index_merge_ror.result BitKeeper/deleted/.del-index_merge_ror_cpk.result: Delete: mysql-test/r/index_merge_ror_cpk.result mysql-test/r/index_merge_innodb.result: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/r/index_merge_innodb.result mysql-test/t/index_merge_innodb.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_innodb.test mysql-test/t/index_merge_myisam.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_myisam.test mysql-test/include/concurrent.inc: 1. This file contains now the main testing code of the former t/innodb_concurrent.test. 2. It is now sourced by t/concurrent_innodb.test. mysql-test/include/deadlock.inc: 1. This file contains now the main testing code of the former t/innodb-deadlock.test 2. It is now sourced by t/deadlock_innodb.test. mysql-test/include/handler.inc: 1. This file contains now the main testing code of the former t/innodb_handler.test + t/handler.test. 2. It is now sourced by t/handler_myisam.test and t/handler_innodb.test. mysql-test/include/index_merge1.inc: 1. This file contains now the main testing code of the former t/index_merge.test. 2. It is now sourced by t/index_merge_myisam.test. mysql-test/include/index_merge2.inc: 1. This file contains now the main code of t/index_merge_innodb.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_2sweeps.inc: 1. This file contains now the main code of the former t/index_merge_innodb2.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_ror.inc: 1. This file contains now the main code of the former t/index_merge_ror.test. 2. It is sourced by t/index_merge_myisam.test. mysql-test/include/index_merge_ror_cpk.inc: 1. This file contains now the main testing code of the former t/index_merge_ror_cpk.test. 2. It is now sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/mix1.inc: 1. This file contains now the main testing code of the t/innodb_mysql.test 2. The name mix1.inc was used because the test contains subtests for different fields. 3. It is sourced by t/innodb_mysql.test. 4. Fixes: - Assign $other_engine_type instead of hardcoded MyISAM. - improve comment - remove redundant subtest - analyze table t4 instead of wrong table t1 - remove not needed "eval set storage_engine = $engine_type;" mysql-test/include/mix2.inc: 1. This file is a copy of the main testing code of the t/innodb.test A copy has to be used, because t/innodb.test is to be maintained by INNOBASE only. 2. The name mix2.inc was used because the test contains subtests for different fields. 3. It is sourced by t/mix2_myisam.test. 4. Fixes: - improved comment - additional "eval SET SESSION STORAGE_ENGINE = $other_engine_type;" at beginning of tests - assign $other_engine_type instead of hardcoded MyISAM or HEAP - assign $other_engine_type where it is needed to preserve test logics - correct logical bugs - improve(extend) "checksum table" test mysql-test/include/query_cache.inc: 1. This file contains now the main testing code of the former t/innodb_cache.test. 2. It is now sourced by t/cache_innodb.test mysql-test/include/read_many_rows.inc: 1. This file contains now the main testing code of the former t/innodb_big.test. 2. It is now sourced by t/read_many_rows_innodb.test. mysql-test/include/rowid_order.inc: 1. This file contains now the main testing code of t/rowid_order_innodb.test. 2. It is now sourced by t/rowid_order_innodb.test. mysql-test/include/unsafe_binlog.inc: 1. This file contains now the main testing code of the former t/innodb_unsafe_binlog.test. 2. It is now sourced by t/unsafe_binlog_innodb.test. mysql-test/r/cache_innodb.result: Updated result mysql-test/r/concurrent_innodb.result: Updated result mysql-test/r/deadlock_innodb.result: Updated result mysql-test/r/handler_innodb.result: Updated result mysql-test/r/handler_myisam.result: Updated result mysql-test/r/index_merge_myisam.result: Updated result mysql-test/r/innodb_mysql.result: Updated result mysql-test/r/mix2_myisam.result: Updated result mysql-test/r/rowid_order_innodb.result: Updated result mysql-test/r/unsafe_binlog_innodb.result: Updated result mysql-test/t/cache_innodb.test: 1. Renaming of t/innodb_cache.test to t/cache_innodb.test 2. Main code is now sourced from include/query_cache.inc. mysql-test/t/concurrent_innodb.test: 1. Renaming of t/innodb_concurrent.test to t/concurrent_innodb.test 2. Main code is now sourced from include/concurrent.inc. Attention: This test fails even in the old version. (BUG#21579). --> added to t/disabled.def mysql-test/t/deadlock_innodb.test: 1. Renaming of t/innodb_deadlock.test to t/deadlock_innodb.test 2. Main code is now sourced from include/deadlock.inc. mysql-test/t/disabled.def: Add the test concurrent_innodb because of BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences mysql-test/t/handler_innodb.test: 1. Renaming of t/innodb_handler.test to t/handler_innodb.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/innodb_handler.test mysql-test/t/handler_myisam.test: 1. Renaming of t/handler.test to t/handler_myisam.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/handler_innodb.test. mysql-test/t/innodb_mysql.test: 1. Main code is now sourced from include/mix1.inc. 2. Test was not renamed because t/innodb.test refers to it. mysql-test/t/mix2_myisam.test: New test: MyISAM variant of mix2 ( = t/innodb.test) mysql-test/t/read_many_rows_innodb.test: 1. Renaming of t/innodb_big.test to t/read_many_rows_innodb.test 2. Main code is now sourced from include/read_many_rows.inc. mysql-test/t/rowid_order_innodb.test: Main code is now sourced from t/rowid_order.inc. mysql-test/t/unsafe_binlog_innodb.test: 1. Renaming of t/innodb_unsafe_binlog.test to t/unsafe_binlog_innodb.test 2. Main code is now sourced from include/unsafe_binlog.inc.
2006-08-16 14:58:49 +02:00
#
- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
# See init.inc for setup of variables for this script
#
2006-08-16 19:29:49 +02:00
# The variables
This changeset belongs to WL#3397 Refactoring storage engine test cases (for falcon) It contains also fixes according to code review. Contents: Testcases which were in history dedicated to InnoDB or MyISAM only. Modifications: 1. Shift the main testing code into include/<testing field>.inc Introduce $variables which can be used to omit tests for features which are not supported by certain storage engines. 2. The storage engine to be tested is assigned within the toplevel script (t/<whatever>_<engine>.test) via variable $engine_type and the the main testing code is sourced from include/<testing field>.inc 3. Some toplevel testscripts have to be renamed to - avoid immediate or future namespace clashes - show via filename which storage engine is tested 4. Minor code cleanup like remove trailing spaces, some additional comments .... mysql-test/t/unsafe_binlog_innodb-master.opt: Rename: mysql-test/t/innodb_unsafe_binlog-master.opt -> mysql-test/t/unsafe_binlog_innodb-master.opt mysql-test/r/read_many_rows_innodb.result: Rename: mysql-test/r/innodb-big.result -> mysql-test/r/read_many_rows_innodb.result mysql-test/t/cache_innodb-master.opt: Rename: mysql-test/t/innodb_cache-master.opt -> mysql-test/t/cache_innodb-master.opt mysql-test/t/concurrent_innodb-master.opt: Rename: mysql-test/t/innodb_concurrent-master.opt -> mysql-test/t/concurrent_innodb-master.opt BitKeeper/deleted/.del-index_merge.result: Delete: mysql-test/r/index_merge.result BitKeeper/deleted/.del-index_merge_innodb.result: Delete: mysql-test/r/index_merge_innodb.result BitKeeper/deleted/.del-index_merge_innodb2.result: Delete: mysql-test/r/index_merge_innodb2.result BitKeeper/deleted/.del-index_merge_ror.result: Delete: mysql-test/r/index_merge_ror.result BitKeeper/deleted/.del-index_merge_ror_cpk.result: Delete: mysql-test/r/index_merge_ror_cpk.result mysql-test/r/index_merge_innodb.result: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/r/index_merge_innodb.result mysql-test/t/index_merge_innodb.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_innodb.test mysql-test/t/index_merge_myisam.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_myisam.test mysql-test/include/concurrent.inc: 1. This file contains now the main testing code of the former t/innodb_concurrent.test. 2. It is now sourced by t/concurrent_innodb.test. mysql-test/include/deadlock.inc: 1. This file contains now the main testing code of the former t/innodb-deadlock.test 2. It is now sourced by t/deadlock_innodb.test. mysql-test/include/handler.inc: 1. This file contains now the main testing code of the former t/innodb_handler.test + t/handler.test. 2. It is now sourced by t/handler_myisam.test and t/handler_innodb.test. mysql-test/include/index_merge1.inc: 1. This file contains now the main testing code of the former t/index_merge.test. 2. It is now sourced by t/index_merge_myisam.test. mysql-test/include/index_merge2.inc: 1. This file contains now the main code of t/index_merge_innodb.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_2sweeps.inc: 1. This file contains now the main code of the former t/index_merge_innodb2.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_ror.inc: 1. This file contains now the main code of the former t/index_merge_ror.test. 2. It is sourced by t/index_merge_myisam.test. mysql-test/include/index_merge_ror_cpk.inc: 1. This file contains now the main testing code of the former t/index_merge_ror_cpk.test. 2. It is now sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/mix1.inc: 1. This file contains now the main testing code of the t/innodb_mysql.test 2. The name mix1.inc was used because the test contains subtests for different fields. 3. It is sourced by t/innodb_mysql.test. 4. Fixes: - Assign $other_engine_type instead of hardcoded MyISAM. - improve comment - remove redundant subtest - analyze table t4 instead of wrong table t1 - remove not needed "eval set storage_engine = $engine_type;" mysql-test/include/mix2.inc: 1. This file is a copy of the main testing code of the t/innodb.test A copy has to be used, because t/innodb.test is to be maintained by INNOBASE only. 2. The name mix2.inc was used because the test contains subtests for different fields. 3. It is sourced by t/mix2_myisam.test. 4. Fixes: - improved comment - additional "eval SET SESSION STORAGE_ENGINE = $other_engine_type;" at beginning of tests - assign $other_engine_type instead of hardcoded MyISAM or HEAP - assign $other_engine_type where it is needed to preserve test logics - correct logical bugs - improve(extend) "checksum table" test mysql-test/include/query_cache.inc: 1. This file contains now the main testing code of the former t/innodb_cache.test. 2. It is now sourced by t/cache_innodb.test mysql-test/include/read_many_rows.inc: 1. This file contains now the main testing code of the former t/innodb_big.test. 2. It is now sourced by t/read_many_rows_innodb.test. mysql-test/include/rowid_order.inc: 1. This file contains now the main testing code of t/rowid_order_innodb.test. 2. It is now sourced by t/rowid_order_innodb.test. mysql-test/include/unsafe_binlog.inc: 1. This file contains now the main testing code of the former t/innodb_unsafe_binlog.test. 2. It is now sourced by t/unsafe_binlog_innodb.test. mysql-test/r/cache_innodb.result: Updated result mysql-test/r/concurrent_innodb.result: Updated result mysql-test/r/deadlock_innodb.result: Updated result mysql-test/r/handler_innodb.result: Updated result mysql-test/r/handler_myisam.result: Updated result mysql-test/r/index_merge_myisam.result: Updated result mysql-test/r/innodb_mysql.result: Updated result mysql-test/r/mix2_myisam.result: Updated result mysql-test/r/rowid_order_innodb.result: Updated result mysql-test/r/unsafe_binlog_innodb.result: Updated result mysql-test/t/cache_innodb.test: 1. Renaming of t/innodb_cache.test to t/cache_innodb.test 2. Main code is now sourced from include/query_cache.inc. mysql-test/t/concurrent_innodb.test: 1. Renaming of t/innodb_concurrent.test to t/concurrent_innodb.test 2. Main code is now sourced from include/concurrent.inc. Attention: This test fails even in the old version. (BUG#21579). --> added to t/disabled.def mysql-test/t/deadlock_innodb.test: 1. Renaming of t/innodb_deadlock.test to t/deadlock_innodb.test 2. Main code is now sourced from include/deadlock.inc. mysql-test/t/disabled.def: Add the test concurrent_innodb because of BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences mysql-test/t/handler_innodb.test: 1. Renaming of t/innodb_handler.test to t/handler_innodb.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/innodb_handler.test mysql-test/t/handler_myisam.test: 1. Renaming of t/handler.test to t/handler_myisam.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/handler_innodb.test. mysql-test/t/innodb_mysql.test: 1. Main code is now sourced from include/mix1.inc. 2. Test was not renamed because t/innodb.test refers to it. mysql-test/t/mix2_myisam.test: New test: MyISAM variant of mix2 ( = t/innodb.test) mysql-test/t/read_many_rows_innodb.test: 1. Renaming of t/innodb_big.test to t/read_many_rows_innodb.test 2. Main code is now sourced from include/read_many_rows.inc. mysql-test/t/rowid_order_innodb.test: Main code is now sourced from t/rowid_order.inc. mysql-test/t/unsafe_binlog_innodb.test: 1. Renaming of t/innodb_unsafe_binlog.test to t/unsafe_binlog_innodb.test 2. Main code is now sourced from include/unsafe_binlog.inc.
2006-08-16 14:58:49 +02:00
# $engine_type -- storage engine to be tested
2006-08-16 19:29:49 +02:00
# $other_handler_engine_type -- storage engine <> $engine_type, if possible
# 1. $other_handler_engine_type must support handler
# 2. $other_handler_engine_type must point to an all
# time available storage engine
# 2006-08 MySQL 5.1 MyISAM and MEMORY only
#
# test of HANDLER ...
#
This changeset belongs to WL#3397 Refactoring storage engine test cases (for falcon) It contains also fixes according to code review. Contents: Testcases which were in history dedicated to InnoDB or MyISAM only. Modifications: 1. Shift the main testing code into include/<testing field>.inc Introduce $variables which can be used to omit tests for features which are not supported by certain storage engines. 2. The storage engine to be tested is assigned within the toplevel script (t/<whatever>_<engine>.test) via variable $engine_type and the the main testing code is sourced from include/<testing field>.inc 3. Some toplevel testscripts have to be renamed to - avoid immediate or future namespace clashes - show via filename which storage engine is tested 4. Minor code cleanup like remove trailing spaces, some additional comments .... mysql-test/t/unsafe_binlog_innodb-master.opt: Rename: mysql-test/t/innodb_unsafe_binlog-master.opt -> mysql-test/t/unsafe_binlog_innodb-master.opt mysql-test/r/read_many_rows_innodb.result: Rename: mysql-test/r/innodb-big.result -> mysql-test/r/read_many_rows_innodb.result mysql-test/t/cache_innodb-master.opt: Rename: mysql-test/t/innodb_cache-master.opt -> mysql-test/t/cache_innodb-master.opt mysql-test/t/concurrent_innodb-master.opt: Rename: mysql-test/t/innodb_concurrent-master.opt -> mysql-test/t/concurrent_innodb-master.opt BitKeeper/deleted/.del-index_merge.result: Delete: mysql-test/r/index_merge.result BitKeeper/deleted/.del-index_merge_innodb.result: Delete: mysql-test/r/index_merge_innodb.result BitKeeper/deleted/.del-index_merge_innodb2.result: Delete: mysql-test/r/index_merge_innodb2.result BitKeeper/deleted/.del-index_merge_ror.result: Delete: mysql-test/r/index_merge_ror.result BitKeeper/deleted/.del-index_merge_ror_cpk.result: Delete: mysql-test/r/index_merge_ror_cpk.result mysql-test/r/index_merge_innodb.result: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/r/index_merge_innodb.result mysql-test/t/index_merge_innodb.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_innodb.test mysql-test/t/index_merge_myisam.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_myisam.test mysql-test/include/concurrent.inc: 1. This file contains now the main testing code of the former t/innodb_concurrent.test. 2. It is now sourced by t/concurrent_innodb.test. mysql-test/include/deadlock.inc: 1. This file contains now the main testing code of the former t/innodb-deadlock.test 2. It is now sourced by t/deadlock_innodb.test. mysql-test/include/handler.inc: 1. This file contains now the main testing code of the former t/innodb_handler.test + t/handler.test. 2. It is now sourced by t/handler_myisam.test and t/handler_innodb.test. mysql-test/include/index_merge1.inc: 1. This file contains now the main testing code of the former t/index_merge.test. 2. It is now sourced by t/index_merge_myisam.test. mysql-test/include/index_merge2.inc: 1. This file contains now the main code of t/index_merge_innodb.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_2sweeps.inc: 1. This file contains now the main code of the former t/index_merge_innodb2.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_ror.inc: 1. This file contains now the main code of the former t/index_merge_ror.test. 2. It is sourced by t/index_merge_myisam.test. mysql-test/include/index_merge_ror_cpk.inc: 1. This file contains now the main testing code of the former t/index_merge_ror_cpk.test. 2. It is now sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/mix1.inc: 1. This file contains now the main testing code of the t/innodb_mysql.test 2. The name mix1.inc was used because the test contains subtests for different fields. 3. It is sourced by t/innodb_mysql.test. 4. Fixes: - Assign $other_engine_type instead of hardcoded MyISAM. - improve comment - remove redundant subtest - analyze table t4 instead of wrong table t1 - remove not needed "eval set storage_engine = $engine_type;" mysql-test/include/mix2.inc: 1. This file is a copy of the main testing code of the t/innodb.test A copy has to be used, because t/innodb.test is to be maintained by INNOBASE only. 2. The name mix2.inc was used because the test contains subtests for different fields. 3. It is sourced by t/mix2_myisam.test. 4. Fixes: - improved comment - additional "eval SET SESSION STORAGE_ENGINE = $other_engine_type;" at beginning of tests - assign $other_engine_type instead of hardcoded MyISAM or HEAP - assign $other_engine_type where it is needed to preserve test logics - correct logical bugs - improve(extend) "checksum table" test mysql-test/include/query_cache.inc: 1. This file contains now the main testing code of the former t/innodb_cache.test. 2. It is now sourced by t/cache_innodb.test mysql-test/include/read_many_rows.inc: 1. This file contains now the main testing code of the former t/innodb_big.test. 2. It is now sourced by t/read_many_rows_innodb.test. mysql-test/include/rowid_order.inc: 1. This file contains now the main testing code of t/rowid_order_innodb.test. 2. It is now sourced by t/rowid_order_innodb.test. mysql-test/include/unsafe_binlog.inc: 1. This file contains now the main testing code of the former t/innodb_unsafe_binlog.test. 2. It is now sourced by t/unsafe_binlog_innodb.test. mysql-test/r/cache_innodb.result: Updated result mysql-test/r/concurrent_innodb.result: Updated result mysql-test/r/deadlock_innodb.result: Updated result mysql-test/r/handler_innodb.result: Updated result mysql-test/r/handler_myisam.result: Updated result mysql-test/r/index_merge_myisam.result: Updated result mysql-test/r/innodb_mysql.result: Updated result mysql-test/r/mix2_myisam.result: Updated result mysql-test/r/rowid_order_innodb.result: Updated result mysql-test/r/unsafe_binlog_innodb.result: Updated result mysql-test/t/cache_innodb.test: 1. Renaming of t/innodb_cache.test to t/cache_innodb.test 2. Main code is now sourced from include/query_cache.inc. mysql-test/t/concurrent_innodb.test: 1. Renaming of t/innodb_concurrent.test to t/concurrent_innodb.test 2. Main code is now sourced from include/concurrent.inc. Attention: This test fails even in the old version. (BUG#21579). --> added to t/disabled.def mysql-test/t/deadlock_innodb.test: 1. Renaming of t/innodb_deadlock.test to t/deadlock_innodb.test 2. Main code is now sourced from include/deadlock.inc. mysql-test/t/disabled.def: Add the test concurrent_innodb because of BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences mysql-test/t/handler_innodb.test: 1. Renaming of t/innodb_handler.test to t/handler_innodb.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/innodb_handler.test mysql-test/t/handler_myisam.test: 1. Renaming of t/handler.test to t/handler_myisam.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/handler_innodb.test. mysql-test/t/innodb_mysql.test: 1. Main code is now sourced from include/mix1.inc. 2. Test was not renamed because t/innodb.test refers to it. mysql-test/t/mix2_myisam.test: New test: MyISAM variant of mix2 ( = t/innodb.test) mysql-test/t/read_many_rows_innodb.test: 1. Renaming of t/innodb_big.test to t/read_many_rows_innodb.test 2. Main code is now sourced from include/read_many_rows.inc. mysql-test/t/rowid_order_innodb.test: Main code is now sourced from t/rowid_order.inc. mysql-test/t/unsafe_binlog_innodb.test: 1. Renaming of t/innodb_unsafe_binlog.test to t/unsafe_binlog_innodb.test 2. Main code is now sourced from include/unsafe_binlog.inc.
2006-08-16 14:58:49 +02:00
# Last update:
# 2006-07-31 ML test refactored (MySQL 5.1)
# code of t/handler.test and t/innodb_handler.test united
- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
# main testing code put into handler.inc
This changeset belongs to WL#3397 Refactoring storage engine test cases (for falcon) It contains also fixes according to code review. Contents: Testcases which were in history dedicated to InnoDB or MyISAM only. Modifications: 1. Shift the main testing code into include/<testing field>.inc Introduce $variables which can be used to omit tests for features which are not supported by certain storage engines. 2. The storage engine to be tested is assigned within the toplevel script (t/<whatever>_<engine>.test) via variable $engine_type and the the main testing code is sourced from include/<testing field>.inc 3. Some toplevel testscripts have to be renamed to - avoid immediate or future namespace clashes - show via filename which storage engine is tested 4. Minor code cleanup like remove trailing spaces, some additional comments .... mysql-test/t/unsafe_binlog_innodb-master.opt: Rename: mysql-test/t/innodb_unsafe_binlog-master.opt -> mysql-test/t/unsafe_binlog_innodb-master.opt mysql-test/r/read_many_rows_innodb.result: Rename: mysql-test/r/innodb-big.result -> mysql-test/r/read_many_rows_innodb.result mysql-test/t/cache_innodb-master.opt: Rename: mysql-test/t/innodb_cache-master.opt -> mysql-test/t/cache_innodb-master.opt mysql-test/t/concurrent_innodb-master.opt: Rename: mysql-test/t/innodb_concurrent-master.opt -> mysql-test/t/concurrent_innodb-master.opt BitKeeper/deleted/.del-index_merge.result: Delete: mysql-test/r/index_merge.result BitKeeper/deleted/.del-index_merge_innodb.result: Delete: mysql-test/r/index_merge_innodb.result BitKeeper/deleted/.del-index_merge_innodb2.result: Delete: mysql-test/r/index_merge_innodb2.result BitKeeper/deleted/.del-index_merge_ror.result: Delete: mysql-test/r/index_merge_ror.result BitKeeper/deleted/.del-index_merge_ror_cpk.result: Delete: mysql-test/r/index_merge_ror_cpk.result mysql-test/r/index_merge_innodb.result: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/r/index_merge_innodb.result mysql-test/t/index_merge_innodb.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_innodb.test mysql-test/t/index_merge_myisam.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_myisam.test mysql-test/include/concurrent.inc: 1. This file contains now the main testing code of the former t/innodb_concurrent.test. 2. It is now sourced by t/concurrent_innodb.test. mysql-test/include/deadlock.inc: 1. This file contains now the main testing code of the former t/innodb-deadlock.test 2. It is now sourced by t/deadlock_innodb.test. mysql-test/include/handler.inc: 1. This file contains now the main testing code of the former t/innodb_handler.test + t/handler.test. 2. It is now sourced by t/handler_myisam.test and t/handler_innodb.test. mysql-test/include/index_merge1.inc: 1. This file contains now the main testing code of the former t/index_merge.test. 2. It is now sourced by t/index_merge_myisam.test. mysql-test/include/index_merge2.inc: 1. This file contains now the main code of t/index_merge_innodb.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_2sweeps.inc: 1. This file contains now the main code of the former t/index_merge_innodb2.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_ror.inc: 1. This file contains now the main code of the former t/index_merge_ror.test. 2. It is sourced by t/index_merge_myisam.test. mysql-test/include/index_merge_ror_cpk.inc: 1. This file contains now the main testing code of the former t/index_merge_ror_cpk.test. 2. It is now sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/mix1.inc: 1. This file contains now the main testing code of the t/innodb_mysql.test 2. The name mix1.inc was used because the test contains subtests for different fields. 3. It is sourced by t/innodb_mysql.test. 4. Fixes: - Assign $other_engine_type instead of hardcoded MyISAM. - improve comment - remove redundant subtest - analyze table t4 instead of wrong table t1 - remove not needed "eval set storage_engine = $engine_type;" mysql-test/include/mix2.inc: 1. This file is a copy of the main testing code of the t/innodb.test A copy has to be used, because t/innodb.test is to be maintained by INNOBASE only. 2. The name mix2.inc was used because the test contains subtests for different fields. 3. It is sourced by t/mix2_myisam.test. 4. Fixes: - improved comment - additional "eval SET SESSION STORAGE_ENGINE = $other_engine_type;" at beginning of tests - assign $other_engine_type instead of hardcoded MyISAM or HEAP - assign $other_engine_type where it is needed to preserve test logics - correct logical bugs - improve(extend) "checksum table" test mysql-test/include/query_cache.inc: 1. This file contains now the main testing code of the former t/innodb_cache.test. 2. It is now sourced by t/cache_innodb.test mysql-test/include/read_many_rows.inc: 1. This file contains now the main testing code of the former t/innodb_big.test. 2. It is now sourced by t/read_many_rows_innodb.test. mysql-test/include/rowid_order.inc: 1. This file contains now the main testing code of t/rowid_order_innodb.test. 2. It is now sourced by t/rowid_order_innodb.test. mysql-test/include/unsafe_binlog.inc: 1. This file contains now the main testing code of the former t/innodb_unsafe_binlog.test. 2. It is now sourced by t/unsafe_binlog_innodb.test. mysql-test/r/cache_innodb.result: Updated result mysql-test/r/concurrent_innodb.result: Updated result mysql-test/r/deadlock_innodb.result: Updated result mysql-test/r/handler_innodb.result: Updated result mysql-test/r/handler_myisam.result: Updated result mysql-test/r/index_merge_myisam.result: Updated result mysql-test/r/innodb_mysql.result: Updated result mysql-test/r/mix2_myisam.result: Updated result mysql-test/r/rowid_order_innodb.result: Updated result mysql-test/r/unsafe_binlog_innodb.result: Updated result mysql-test/t/cache_innodb.test: 1. Renaming of t/innodb_cache.test to t/cache_innodb.test 2. Main code is now sourced from include/query_cache.inc. mysql-test/t/concurrent_innodb.test: 1. Renaming of t/innodb_concurrent.test to t/concurrent_innodb.test 2. Main code is now sourced from include/concurrent.inc. Attention: This test fails even in the old version. (BUG#21579). --> added to t/disabled.def mysql-test/t/deadlock_innodb.test: 1. Renaming of t/innodb_deadlock.test to t/deadlock_innodb.test 2. Main code is now sourced from include/deadlock.inc. mysql-test/t/disabled.def: Add the test concurrent_innodb because of BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences mysql-test/t/handler_innodb.test: 1. Renaming of t/innodb_handler.test to t/handler_innodb.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/innodb_handler.test mysql-test/t/handler_myisam.test: 1. Renaming of t/handler.test to t/handler_myisam.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/handler_innodb.test. mysql-test/t/innodb_mysql.test: 1. Main code is now sourced from include/mix1.inc. 2. Test was not renamed because t/innodb.test refers to it. mysql-test/t/mix2_myisam.test: New test: MyISAM variant of mix2 ( = t/innodb.test) mysql-test/t/read_many_rows_innodb.test: 1. Renaming of t/innodb_big.test to t/read_many_rows_innodb.test 2. Main code is now sourced from include/read_many_rows.inc. mysql-test/t/rowid_order_innodb.test: Main code is now sourced from t/rowid_order.inc. mysql-test/t/unsafe_binlog_innodb.test: 1. Renaming of t/innodb_unsafe_binlog.test to t/unsafe_binlog_innodb.test 2. Main code is now sourced from include/unsafe_binlog.inc.
2006-08-16 14:58:49 +02:00
#
source include/have_csv.inc;
Fixes to embedded server to be able to run tests with it (Needed for "list of pushes" web page and autopush) include/mysql.h: Fix to embedded server to be able to run tests on it libmysql/libmysql.c: Fix to embedded server to be able to run tests on it libmysqld/emb_qcache.cc: Fix to embedded server to be able to run tests on it libmysqld/embedded_priv.h: Fix to embedded server to be able to run tests on it libmysqld/lib_sql.cc: Fix to embedded server to be able to run tests on it libmysqld/libmysqld.c: Fix to embedded server to be able to run tests on it mysql-test/mysql-test-run.sh: Fix to embedded server to be able to run tests on it mysql-test/r/binlog.result: Updated test for embedded server mysql-test/r/ctype_cp932.result: Updated test for embedded server mysql-test/r/innodb.result: Updated test for embedded server mysql-test/r/mysqltest.result: Updated test for embedded server mysql-test/r/query_cache.result: Updated test for embedded server mysql-test/r/query_cache_notembedded.result: Updated test for embedded server mysql-test/r/sp-error.result: Updated test for embedded server mysql-test/r/sp.result: Updated test for embedded server mysql-test/r/subselect.result: Updated test for embedded server mysql-test/r/view.result: Updated test for embedded server mysql-test/r/view_grant.result: Updated test for embedded server mysql-test/t/backup.test: Updated test for embedded server mysql-test/t/binlog.test: Updated test for embedded server mysql-test/t/blackhole.test: Updated test for embedded server mysql-test/t/compress.test: Updated test for embedded server mysql-test/t/ctype_cp932.test: Updated test for embedded server mysql-test/t/delayed.test: Updated test for embedded server mysql-test/t/handler.test: Updated test for embedded server mysql-test/t/innodb.test: Updated test for embedded server mysql-test/t/mysql.test: Updated test for embedded server mysql-test/t/mysql_client_test.test: Updated test for embedded server mysql-test/t/mysqltest.test: Updated test for embedded server mysql-test/t/query_cache.test: Updated test for embedded server mysql-test/t/query_cache_notembedded.test: Updated test for embedded server mysql-test/t/read_only.test: Updated test for embedded server mysql-test/t/skip_grants.test: Updated test for embedded server mysql-test/t/sp-destruct.test: Updated test for embedded server mysql-test/t/sp-error.test: Updated test for embedded server mysql-test/t/sp-threads.test: Updated test for embedded server mysql-test/t/sp.test: Updated test for embedded server mysql-test/t/subselect.test: Updated test for embedded server mysql-test/t/temp_table.test: Updated test for embedded server mysql-test/t/view.test: Updated test for embedded server mysql-test/t/view_grant.test: Updated test for embedded server mysql-test/t/wait_timeout.test: Updated test for embedded server mysys/mf_dirname.c: Review fix: Don't access data outside of array mysys/my_bitmap.c: Remove compiler warnings scripts/mysql_fix_privilege_tables.sql: Add flush privileges to .sql script so that one doesn't have to reboot mysqld when one runs the mysql_fix_privilege_script sql-common/client.c: Updated test for embedded server sql/item.cc: Remove DBUG_PRINT statement that can cause crashes when running with --debug sql/mysqld.cc: Fix to embedded server to be able to run tests on it sql/protocol.cc: Fix to embedded server to be able to run tests on it (Trivial reconstruction of code) sql/protocol.h: Fix to embedded server to be able to run tests on it sql/sql_base.cc: Better comment sql/sql_class.cc: Fix to embedded server to be able to run tests on it sql/sql_class.h: Fix to embedded server to be able to run tests on it sql/sql_cursor.cc: Fix to embedded server to be able to run tests on it sql/sql_parse.cc: Fix to embedded server to be able to run tests on it Don't crash for disabled commands when using embedded server sql/sql_prepare.cc: Fix to embedded server to be able to run tests on it mysql-test/r/ctype_cp932_notembedded.result: New BitKeeper file ``mysql-test/r/ctype_cp932_notembedded.result'' mysql-test/r/innodb_notembedded.result: New BitKeeper file ``mysql-test/r/innodb_notembedded.result'' mysql-test/r/sp.result.orig: New BitKeeper file ``mysql-test/r/sp.result.orig'' mysql-test/r/sp_notembedded.result: New BitKeeper file ``mysql-test/r/sp_notembedded.result'' mysql-test/r/subselect_notembedded.result: New BitKeeper file ``mysql-test/r/subselect_notembedded.result'' mysql-test/t/ctype_cp932_notembedded.test: New BitKeeper file ``mysql-test/t/ctype_cp932_notembedded.test'' mysql-test/t/innodb_notembedded.test: New BitKeeper file ``mysql-test/t/innodb_notembedded.test'' mysql-test/t/sp.test.orig: New BitKeeper file ``mysql-test/t/sp.test.orig'' mysql-test/t/sp_notembedded.test: New BitKeeper file ``mysql-test/t/sp_notembedded.test'' mysql-test/t/subselect_notembedded.test: New BitKeeper file ``mysql-test/t/subselect_notembedded.test''
2006-02-24 18:34:15 +02:00
- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
#
# Start testing the table created in init.inc
#
handler t1 open as t2;
Added HANDLER support for MEMORY tables Added key and file version numbers to MEMORY tables so that we can detect if someone has changed them between HANDLER calls. mysql-test/suite/handler/aria.result: Fixed result after test changes mysql-test/suite/handler/handler.inc: Changed test to use combined key to ensure rows are returned in a pre-determinated order. mysql-test/suite/handler/heap.result: New result mysql-test/suite/handler/heap.test: Added test for HANDLER + HEAP mysql-test/suite/handler/innodb.result: Fixed result after test changes mysql-test/suite/handler/myisam.result: Fixed result after test changes sql/sql_handler.cc: Fixed wrong parameter to ha_index_next_same() storage/heap/ha_heap.cc: Abort key scan if table has changed. Abort table scan if table has been recreated. storage/heap/ha_heap.h: Added support for HANDLER storage/heap/hp_clear.c: Increase version number so that we can notice changes if using HANDLER storage/heap/hp_delete.c: Increase key data version number on key changes. storage/heap/hp_rfirst.c: Remember version of key data Give error if using read-first on hash key. storage/heap/hp_rkey.c: Remember version of key data storage/heap/hp_rlast.c: Remember version of key data Give error if using read-last on hash key. storage/heap/hp_rnext.c: Fixed that we get next key from last search. storage/heap/hp_rprev.c: Fixed that we get previous key from last search. storage/heap/hp_scan.c: Remember version of key and file data storage/heap/hp_update.c: Increase key data version number on key changes. storage/heap/hp_write.c: Increase key data version number on key changes.
2011-01-11 18:51:59 +02:00
handler t2 read b first;
handler t2 read b next;
handler t2 read b next;
handler t2 read b prev;
handler t2 read b last;
handler t2 read b prev;
handler t2 read b prev;
handler t2 read b first;
handler t2 read b prev;
handler t2 read b last;
handler t2 read b prev;
handler t2 read b next;
handler t2 read b next;
handler t2 read a=(15);
handler t2 read a=(21);
--error 1070
handler t2 read a=(19,"fff");
handler t2 read b=(19,"fff");
handler t2 read b=(19,"yyy");
handler t2 read b=(19);
--error 1109
handler t1 read a last;
handler t2 read a=(11);
handler t2 read a>=(11);
Added HANDLER support for MEMORY tables Added key and file version numbers to MEMORY tables so that we can detect if someone has changed them between HANDLER calls. mysql-test/suite/handler/aria.result: Fixed result after test changes mysql-test/suite/handler/handler.inc: Changed test to use combined key to ensure rows are returned in a pre-determinated order. mysql-test/suite/handler/heap.result: New result mysql-test/suite/handler/heap.test: Added test for HANDLER + HEAP mysql-test/suite/handler/innodb.result: Fixed result after test changes mysql-test/suite/handler/myisam.result: Fixed result after test changes sql/sql_handler.cc: Fixed wrong parameter to ha_index_next_same() storage/heap/ha_heap.cc: Abort key scan if table has changed. Abort table scan if table has been recreated. storage/heap/ha_heap.h: Added support for HANDLER storage/heap/hp_clear.c: Increase version number so that we can notice changes if using HANDLER storage/heap/hp_delete.c: Increase key data version number on key changes. storage/heap/hp_rfirst.c: Remember version of key data Give error if using read-first on hash key. storage/heap/hp_rkey.c: Remember version of key data storage/heap/hp_rlast.c: Remember version of key data Give error if using read-last on hash key. storage/heap/hp_rnext.c: Fixed that we get next key from last search. storage/heap/hp_rprev.c: Fixed that we get previous key from last search. storage/heap/hp_scan.c: Remember version of key and file data storage/heap/hp_update.c: Increase key data version number on key changes. storage/heap/hp_write.c: Increase key data version number on key changes.
2011-01-11 18:51:59 +02:00
# Search on something we can find
handler t2 read b=(18);
handler t2 read b>=(18);
handler t2 read b>(18);
handler t2 read b<=(18);
handler t2 read b<(18);
- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
# Search on something we can't find
Added HANDLER support for MEMORY tables Added key and file version numbers to MEMORY tables so that we can detect if someone has changed them between HANDLER calls. mysql-test/suite/handler/aria.result: Fixed result after test changes mysql-test/suite/handler/handler.inc: Changed test to use combined key to ensure rows are returned in a pre-determinated order. mysql-test/suite/handler/heap.result: New result mysql-test/suite/handler/heap.test: Added test for HANDLER + HEAP mysql-test/suite/handler/innodb.result: Fixed result after test changes mysql-test/suite/handler/myisam.result: Fixed result after test changes sql/sql_handler.cc: Fixed wrong parameter to ha_index_next_same() storage/heap/ha_heap.cc: Abort key scan if table has changed. Abort table scan if table has been recreated. storage/heap/ha_heap.h: Added support for HANDLER storage/heap/hp_clear.c: Increase version number so that we can notice changes if using HANDLER storage/heap/hp_delete.c: Increase key data version number on key changes. storage/heap/hp_rfirst.c: Remember version of key data Give error if using read-first on hash key. storage/heap/hp_rkey.c: Remember version of key data storage/heap/hp_rlast.c: Remember version of key data Give error if using read-last on hash key. storage/heap/hp_rnext.c: Fixed that we get next key from last search. storage/heap/hp_rprev.c: Fixed that we get previous key from last search. storage/heap/hp_scan.c: Remember version of key and file data storage/heap/hp_update.c: Increase key data version number on key changes. storage/heap/hp_write.c: Increase key data version number on key changes.
2011-01-11 18:51:59 +02:00
--sorted_result
- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
handler t2 read a=(15);
Added HANDLER support for MEMORY tables Added key and file version numbers to MEMORY tables so that we can detect if someone has changed them between HANDLER calls. mysql-test/suite/handler/aria.result: Fixed result after test changes mysql-test/suite/handler/handler.inc: Changed test to use combined key to ensure rows are returned in a pre-determinated order. mysql-test/suite/handler/heap.result: New result mysql-test/suite/handler/heap.test: Added test for HANDLER + HEAP mysql-test/suite/handler/innodb.result: Fixed result after test changes mysql-test/suite/handler/myisam.result: Fixed result after test changes sql/sql_handler.cc: Fixed wrong parameter to ha_index_next_same() storage/heap/ha_heap.cc: Abort key scan if table has changed. Abort table scan if table has been recreated. storage/heap/ha_heap.h: Added support for HANDLER storage/heap/hp_clear.c: Increase version number so that we can notice changes if using HANDLER storage/heap/hp_delete.c: Increase key data version number on key changes. storage/heap/hp_rfirst.c: Remember version of key data Give error if using read-first on hash key. storage/heap/hp_rkey.c: Remember version of key data storage/heap/hp_rlast.c: Remember version of key data Give error if using read-last on hash key. storage/heap/hp_rnext.c: Fixed that we get next key from last search. storage/heap/hp_rprev.c: Fixed that we get previous key from last search. storage/heap/hp_scan.c: Remember version of key and file data storage/heap/hp_update.c: Increase key data version number on key changes. storage/heap/hp_write.c: Increase key data version number on key changes.
2011-01-11 18:51:59 +02:00
--sorted_result
handler t2 read a>=(15) limit 2;
Added HANDLER support for MEMORY tables Added key and file version numbers to MEMORY tables so that we can detect if someone has changed them between HANDLER calls. mysql-test/suite/handler/aria.result: Fixed result after test changes mysql-test/suite/handler/handler.inc: Changed test to use combined key to ensure rows are returned in a pre-determinated order. mysql-test/suite/handler/heap.result: New result mysql-test/suite/handler/heap.test: Added test for HANDLER + HEAP mysql-test/suite/handler/innodb.result: Fixed result after test changes mysql-test/suite/handler/myisam.result: Fixed result after test changes sql/sql_handler.cc: Fixed wrong parameter to ha_index_next_same() storage/heap/ha_heap.cc: Abort key scan if table has changed. Abort table scan if table has been recreated. storage/heap/ha_heap.h: Added support for HANDLER storage/heap/hp_clear.c: Increase version number so that we can notice changes if using HANDLER storage/heap/hp_delete.c: Increase key data version number on key changes. storage/heap/hp_rfirst.c: Remember version of key data Give error if using read-first on hash key. storage/heap/hp_rkey.c: Remember version of key data storage/heap/hp_rlast.c: Remember version of key data Give error if using read-last on hash key. storage/heap/hp_rnext.c: Fixed that we get next key from last search. storage/heap/hp_rprev.c: Fixed that we get previous key from last search. storage/heap/hp_scan.c: Remember version of key and file data storage/heap/hp_update.c: Increase key data version number on key changes. storage/heap/hp_write.c: Increase key data version number on key changes.
2011-01-11 18:51:59 +02:00
--sorted_result
handler t2 read a>(15) limit 2;
- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
handler t2 read a<=(15);
handler t2 read a<(15);
# Search from upper end
handler t2 read a=(54);
handler t2 read a>=(54);
handler t2 read a>(54);
handler t2 read a<=(54);
handler t2 read a<(54);
# Search from lower end
handler t2 read a=(1);
handler t2 read a>=(1);
handler t2 read a>(1);
handler t2 read a<=(1);
handler t2 read a<(1);
Added HANDLER support for MEMORY tables Added key and file version numbers to MEMORY tables so that we can detect if someone has changed them between HANDLER calls. mysql-test/suite/handler/aria.result: Fixed result after test changes mysql-test/suite/handler/handler.inc: Changed test to use combined key to ensure rows are returned in a pre-determinated order. mysql-test/suite/handler/heap.result: New result mysql-test/suite/handler/heap.test: Added test for HANDLER + HEAP mysql-test/suite/handler/innodb.result: Fixed result after test changes mysql-test/suite/handler/myisam.result: Fixed result after test changes sql/sql_handler.cc: Fixed wrong parameter to ha_index_next_same() storage/heap/ha_heap.cc: Abort key scan if table has changed. Abort table scan if table has been recreated. storage/heap/ha_heap.h: Added support for HANDLER storage/heap/hp_clear.c: Increase version number so that we can notice changes if using HANDLER storage/heap/hp_delete.c: Increase key data version number on key changes. storage/heap/hp_rfirst.c: Remember version of key data Give error if using read-first on hash key. storage/heap/hp_rkey.c: Remember version of key data storage/heap/hp_rlast.c: Remember version of key data Give error if using read-last on hash key. storage/heap/hp_rnext.c: Fixed that we get next key from last search. storage/heap/hp_rprev.c: Fixed that we get previous key from last search. storage/heap/hp_scan.c: Remember version of key and file data storage/heap/hp_update.c: Increase key data version number on key changes. storage/heap/hp_write.c: Increase key data version number on key changes.
2011-01-11 18:51:59 +02:00
handler t2 read b first limit 5;
handler t2 read b next limit 3;
handler t2 read b prev limit 10;
handler t2 read b>=(16) limit 4;
handler t2 read b>=(16) limit 2,2;
select * from t1 where a>=16 order by a,b limit 2,2;
handler t2 read a last limit 3;
handler t2 read b=(16) limit 1,3;
Added HANDLER support for MEMORY tables Added key and file version numbers to MEMORY tables so that we can detect if someone has changed them between HANDLER calls. mysql-test/suite/handler/aria.result: Fixed result after test changes mysql-test/suite/handler/handler.inc: Changed test to use combined key to ensure rows are returned in a pre-determinated order. mysql-test/suite/handler/heap.result: New result mysql-test/suite/handler/heap.test: Added test for HANDLER + HEAP mysql-test/suite/handler/innodb.result: Fixed result after test changes mysql-test/suite/handler/myisam.result: Fixed result after test changes sql/sql_handler.cc: Fixed wrong parameter to ha_index_next_same() storage/heap/ha_heap.cc: Abort key scan if table has changed. Abort table scan if table has been recreated. storage/heap/ha_heap.h: Added support for HANDLER storage/heap/hp_clear.c: Increase version number so that we can notice changes if using HANDLER storage/heap/hp_delete.c: Increase key data version number on key changes. storage/heap/hp_rfirst.c: Remember version of key data Give error if using read-first on hash key. storage/heap/hp_rkey.c: Remember version of key data storage/heap/hp_rlast.c: Remember version of key data Give error if using read-last on hash key. storage/heap/hp_rnext.c: Fixed that we get next key from last search. storage/heap/hp_rprev.c: Fixed that we get previous key from last search. storage/heap/hp_scan.c: Remember version of key and file data storage/heap/hp_update.c: Increase key data version number on key changes. storage/heap/hp_write.c: Increase key data version number on key changes.
2011-01-11 18:51:59 +02:00
handler t2 read b=(19);
handler t2 read b=(19) where b="yyy";
handler t2 read first;
handler t2 read next;
handler t2 read next;
handler t2 close;
This changeset belongs to WL#3397 Refactoring storage engine test cases (for falcon) It contains also fixes according to code review. Contents: Testcases which were in history dedicated to InnoDB or MyISAM only. Modifications: 1. Shift the main testing code into include/<testing field>.inc Introduce $variables which can be used to omit tests for features which are not supported by certain storage engines. 2. The storage engine to be tested is assigned within the toplevel script (t/<whatever>_<engine>.test) via variable $engine_type and the the main testing code is sourced from include/<testing field>.inc 3. Some toplevel testscripts have to be renamed to - avoid immediate or future namespace clashes - show via filename which storage engine is tested 4. Minor code cleanup like remove trailing spaces, some additional comments .... mysql-test/t/unsafe_binlog_innodb-master.opt: Rename: mysql-test/t/innodb_unsafe_binlog-master.opt -> mysql-test/t/unsafe_binlog_innodb-master.opt mysql-test/r/read_many_rows_innodb.result: Rename: mysql-test/r/innodb-big.result -> mysql-test/r/read_many_rows_innodb.result mysql-test/t/cache_innodb-master.opt: Rename: mysql-test/t/innodb_cache-master.opt -> mysql-test/t/cache_innodb-master.opt mysql-test/t/concurrent_innodb-master.opt: Rename: mysql-test/t/innodb_concurrent-master.opt -> mysql-test/t/concurrent_innodb-master.opt BitKeeper/deleted/.del-index_merge.result: Delete: mysql-test/r/index_merge.result BitKeeper/deleted/.del-index_merge_innodb.result: Delete: mysql-test/r/index_merge_innodb.result BitKeeper/deleted/.del-index_merge_innodb2.result: Delete: mysql-test/r/index_merge_innodb2.result BitKeeper/deleted/.del-index_merge_ror.result: Delete: mysql-test/r/index_merge_ror.result BitKeeper/deleted/.del-index_merge_ror_cpk.result: Delete: mysql-test/r/index_merge_ror_cpk.result mysql-test/r/index_merge_innodb.result: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/r/index_merge_innodb.result mysql-test/t/index_merge_innodb.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_innodb.test mysql-test/t/index_merge_myisam.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_myisam.test mysql-test/include/concurrent.inc: 1. This file contains now the main testing code of the former t/innodb_concurrent.test. 2. It is now sourced by t/concurrent_innodb.test. mysql-test/include/deadlock.inc: 1. This file contains now the main testing code of the former t/innodb-deadlock.test 2. It is now sourced by t/deadlock_innodb.test. mysql-test/include/handler.inc: 1. This file contains now the main testing code of the former t/innodb_handler.test + t/handler.test. 2. It is now sourced by t/handler_myisam.test and t/handler_innodb.test. mysql-test/include/index_merge1.inc: 1. This file contains now the main testing code of the former t/index_merge.test. 2. It is now sourced by t/index_merge_myisam.test. mysql-test/include/index_merge2.inc: 1. This file contains now the main code of t/index_merge_innodb.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_2sweeps.inc: 1. This file contains now the main code of the former t/index_merge_innodb2.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_ror.inc: 1. This file contains now the main code of the former t/index_merge_ror.test. 2. It is sourced by t/index_merge_myisam.test. mysql-test/include/index_merge_ror_cpk.inc: 1. This file contains now the main testing code of the former t/index_merge_ror_cpk.test. 2. It is now sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/mix1.inc: 1. This file contains now the main testing code of the t/innodb_mysql.test 2. The name mix1.inc was used because the test contains subtests for different fields. 3. It is sourced by t/innodb_mysql.test. 4. Fixes: - Assign $other_engine_type instead of hardcoded MyISAM. - improve comment - remove redundant subtest - analyze table t4 instead of wrong table t1 - remove not needed "eval set storage_engine = $engine_type;" mysql-test/include/mix2.inc: 1. This file is a copy of the main testing code of the t/innodb.test A copy has to be used, because t/innodb.test is to be maintained by INNOBASE only. 2. The name mix2.inc was used because the test contains subtests for different fields. 3. It is sourced by t/mix2_myisam.test. 4. Fixes: - improved comment - additional "eval SET SESSION STORAGE_ENGINE = $other_engine_type;" at beginning of tests - assign $other_engine_type instead of hardcoded MyISAM or HEAP - assign $other_engine_type where it is needed to preserve test logics - correct logical bugs - improve(extend) "checksum table" test mysql-test/include/query_cache.inc: 1. This file contains now the main testing code of the former t/innodb_cache.test. 2. It is now sourced by t/cache_innodb.test mysql-test/include/read_many_rows.inc: 1. This file contains now the main testing code of the former t/innodb_big.test. 2. It is now sourced by t/read_many_rows_innodb.test. mysql-test/include/rowid_order.inc: 1. This file contains now the main testing code of t/rowid_order_innodb.test. 2. It is now sourced by t/rowid_order_innodb.test. mysql-test/include/unsafe_binlog.inc: 1. This file contains now the main testing code of the former t/innodb_unsafe_binlog.test. 2. It is now sourced by t/unsafe_binlog_innodb.test. mysql-test/r/cache_innodb.result: Updated result mysql-test/r/concurrent_innodb.result: Updated result mysql-test/r/deadlock_innodb.result: Updated result mysql-test/r/handler_innodb.result: Updated result mysql-test/r/handler_myisam.result: Updated result mysql-test/r/index_merge_myisam.result: Updated result mysql-test/r/innodb_mysql.result: Updated result mysql-test/r/mix2_myisam.result: Updated result mysql-test/r/rowid_order_innodb.result: Updated result mysql-test/r/unsafe_binlog_innodb.result: Updated result mysql-test/t/cache_innodb.test: 1. Renaming of t/innodb_cache.test to t/cache_innodb.test 2. Main code is now sourced from include/query_cache.inc. mysql-test/t/concurrent_innodb.test: 1. Renaming of t/innodb_concurrent.test to t/concurrent_innodb.test 2. Main code is now sourced from include/concurrent.inc. Attention: This test fails even in the old version. (BUG#21579). --> added to t/disabled.def mysql-test/t/deadlock_innodb.test: 1. Renaming of t/innodb_deadlock.test to t/deadlock_innodb.test 2. Main code is now sourced from include/deadlock.inc. mysql-test/t/disabled.def: Add the test concurrent_innodb because of BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences mysql-test/t/handler_innodb.test: 1. Renaming of t/innodb_handler.test to t/handler_innodb.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/innodb_handler.test mysql-test/t/handler_myisam.test: 1. Renaming of t/handler.test to t/handler_myisam.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/handler_innodb.test. mysql-test/t/innodb_mysql.test: 1. Main code is now sourced from include/mix1.inc. 2. Test was not renamed because t/innodb.test refers to it. mysql-test/t/mix2_myisam.test: New test: MyISAM variant of mix2 ( = t/innodb.test) mysql-test/t/read_many_rows_innodb.test: 1. Renaming of t/innodb_big.test to t/read_many_rows_innodb.test 2. Main code is now sourced from include/read_many_rows.inc. mysql-test/t/rowid_order_innodb.test: Main code is now sourced from t/rowid_order.inc. mysql-test/t/unsafe_binlog_innodb.test: 1. Renaming of t/innodb_unsafe_binlog.test to t/unsafe_binlog_innodb.test 2. Main code is now sourced from include/unsafe_binlog.inc.
2006-08-16 14:58:49 +02:00
handler t1 open;
handler t1 read b next; # this used to crash as a bug#5373
handler t1 read b next;
This changeset belongs to WL#3397 Refactoring storage engine test cases (for falcon) It contains also fixes according to code review. Contents: Testcases which were in history dedicated to InnoDB or MyISAM only. Modifications: 1. Shift the main testing code into include/<testing field>.inc Introduce $variables which can be used to omit tests for features which are not supported by certain storage engines. 2. The storage engine to be tested is assigned within the toplevel script (t/<whatever>_<engine>.test) via variable $engine_type and the the main testing code is sourced from include/<testing field>.inc 3. Some toplevel testscripts have to be renamed to - avoid immediate or future namespace clashes - show via filename which storage engine is tested 4. Minor code cleanup like remove trailing spaces, some additional comments .... mysql-test/t/unsafe_binlog_innodb-master.opt: Rename: mysql-test/t/innodb_unsafe_binlog-master.opt -> mysql-test/t/unsafe_binlog_innodb-master.opt mysql-test/r/read_many_rows_innodb.result: Rename: mysql-test/r/innodb-big.result -> mysql-test/r/read_many_rows_innodb.result mysql-test/t/cache_innodb-master.opt: Rename: mysql-test/t/innodb_cache-master.opt -> mysql-test/t/cache_innodb-master.opt mysql-test/t/concurrent_innodb-master.opt: Rename: mysql-test/t/innodb_concurrent-master.opt -> mysql-test/t/concurrent_innodb-master.opt BitKeeper/deleted/.del-index_merge.result: Delete: mysql-test/r/index_merge.result BitKeeper/deleted/.del-index_merge_innodb.result: Delete: mysql-test/r/index_merge_innodb.result BitKeeper/deleted/.del-index_merge_innodb2.result: Delete: mysql-test/r/index_merge_innodb2.result BitKeeper/deleted/.del-index_merge_ror.result: Delete: mysql-test/r/index_merge_ror.result BitKeeper/deleted/.del-index_merge_ror_cpk.result: Delete: mysql-test/r/index_merge_ror_cpk.result mysql-test/r/index_merge_innodb.result: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/r/index_merge_innodb.result mysql-test/t/index_merge_innodb.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_innodb.test mysql-test/t/index_merge_myisam.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_myisam.test mysql-test/include/concurrent.inc: 1. This file contains now the main testing code of the former t/innodb_concurrent.test. 2. It is now sourced by t/concurrent_innodb.test. mysql-test/include/deadlock.inc: 1. This file contains now the main testing code of the former t/innodb-deadlock.test 2. It is now sourced by t/deadlock_innodb.test. mysql-test/include/handler.inc: 1. This file contains now the main testing code of the former t/innodb_handler.test + t/handler.test. 2. It is now sourced by t/handler_myisam.test and t/handler_innodb.test. mysql-test/include/index_merge1.inc: 1. This file contains now the main testing code of the former t/index_merge.test. 2. It is now sourced by t/index_merge_myisam.test. mysql-test/include/index_merge2.inc: 1. This file contains now the main code of t/index_merge_innodb.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_2sweeps.inc: 1. This file contains now the main code of the former t/index_merge_innodb2.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_ror.inc: 1. This file contains now the main code of the former t/index_merge_ror.test. 2. It is sourced by t/index_merge_myisam.test. mysql-test/include/index_merge_ror_cpk.inc: 1. This file contains now the main testing code of the former t/index_merge_ror_cpk.test. 2. It is now sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/mix1.inc: 1. This file contains now the main testing code of the t/innodb_mysql.test 2. The name mix1.inc was used because the test contains subtests for different fields. 3. It is sourced by t/innodb_mysql.test. 4. Fixes: - Assign $other_engine_type instead of hardcoded MyISAM. - improve comment - remove redundant subtest - analyze table t4 instead of wrong table t1 - remove not needed "eval set storage_engine = $engine_type;" mysql-test/include/mix2.inc: 1. This file is a copy of the main testing code of the t/innodb.test A copy has to be used, because t/innodb.test is to be maintained by INNOBASE only. 2. The name mix2.inc was used because the test contains subtests for different fields. 3. It is sourced by t/mix2_myisam.test. 4. Fixes: - improved comment - additional "eval SET SESSION STORAGE_ENGINE = $other_engine_type;" at beginning of tests - assign $other_engine_type instead of hardcoded MyISAM or HEAP - assign $other_engine_type where it is needed to preserve test logics - correct logical bugs - improve(extend) "checksum table" test mysql-test/include/query_cache.inc: 1. This file contains now the main testing code of the former t/innodb_cache.test. 2. It is now sourced by t/cache_innodb.test mysql-test/include/read_many_rows.inc: 1. This file contains now the main testing code of the former t/innodb_big.test. 2. It is now sourced by t/read_many_rows_innodb.test. mysql-test/include/rowid_order.inc: 1. This file contains now the main testing code of t/rowid_order_innodb.test. 2. It is now sourced by t/rowid_order_innodb.test. mysql-test/include/unsafe_binlog.inc: 1. This file contains now the main testing code of the former t/innodb_unsafe_binlog.test. 2. It is now sourced by t/unsafe_binlog_innodb.test. mysql-test/r/cache_innodb.result: Updated result mysql-test/r/concurrent_innodb.result: Updated result mysql-test/r/deadlock_innodb.result: Updated result mysql-test/r/handler_innodb.result: Updated result mysql-test/r/handler_myisam.result: Updated result mysql-test/r/index_merge_myisam.result: Updated result mysql-test/r/innodb_mysql.result: Updated result mysql-test/r/mix2_myisam.result: Updated result mysql-test/r/rowid_order_innodb.result: Updated result mysql-test/r/unsafe_binlog_innodb.result: Updated result mysql-test/t/cache_innodb.test: 1. Renaming of t/innodb_cache.test to t/cache_innodb.test 2. Main code is now sourced from include/query_cache.inc. mysql-test/t/concurrent_innodb.test: 1. Renaming of t/innodb_concurrent.test to t/concurrent_innodb.test 2. Main code is now sourced from include/concurrent.inc. Attention: This test fails even in the old version. (BUG#21579). --> added to t/disabled.def mysql-test/t/deadlock_innodb.test: 1. Renaming of t/innodb_deadlock.test to t/deadlock_innodb.test 2. Main code is now sourced from include/deadlock.inc. mysql-test/t/disabled.def: Add the test concurrent_innodb because of BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences mysql-test/t/handler_innodb.test: 1. Renaming of t/innodb_handler.test to t/handler_innodb.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/innodb_handler.test mysql-test/t/handler_myisam.test: 1. Renaming of t/handler.test to t/handler_myisam.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/handler_innodb.test. mysql-test/t/innodb_mysql.test: 1. Main code is now sourced from include/mix1.inc. 2. Test was not renamed because t/innodb.test refers to it. mysql-test/t/mix2_myisam.test: New test: MyISAM variant of mix2 ( = t/innodb.test) mysql-test/t/read_many_rows_innodb.test: 1. Renaming of t/innodb_big.test to t/read_many_rows_innodb.test 2. Main code is now sourced from include/read_many_rows.inc. mysql-test/t/rowid_order_innodb.test: Main code is now sourced from t/rowid_order.inc. mysql-test/t/unsafe_binlog_innodb.test: 1. Renaming of t/innodb_unsafe_binlog.test to t/unsafe_binlog_innodb.test 2. Main code is now sourced from include/unsafe_binlog.inc.
2006-08-16 14:58:49 +02:00
handler t1 close;
handler t1 open;
handler t1 read a prev; # this used to crash as a bug#5373
handler t1 read a prev;
handler t1 close;
handler t1 open as t2;
handler t2 read first;
eval alter table t1 engine = $engine_type;
--error 1109
handler t2 read first;
Implementation of MWL#172: Add support for prepared statements to HANDLER READ It includes speed optimizations for HANDLER READ by caching as much as possible in HANDLER OPEN Other things: - Added mysqld option --disable-thr-alarm to be able to benchmark things without thr_alarm - Changed 'Locked' state to 'System lock' and 'Table lock' (these where used in the code but never shown to end user) - Better error message if mysql_install_db.sh fails - Moved handler function prototypes to sql_handler.h - Remove not anymore used 'thd->locked' member include/thr_alarm.h: Added my_disable_thr_alarm include/thr_lock.h: Add new member to THR_LOCK_DATA to remember original lock type state. This is needed as thr_unlock() resets type to TL_UNLOCK. mysql-test/include/check_no_concurrent_insert.inc: Locked -> Table lock mysql-test/include/handler.inc: Locked -> Table lock mysql-test/r/handler_innodb.result: Updated results for new tests mysql-test/r/handler_myisam.result: Updated results for new tests mysql-test/r/sp-threads.result: Locked -> Table lock mysql-test/suite/binlog/t/binlog_stm_row.test: Locked -> Table lock mysql-test/suite/funcs_1/datadict/processlist_val.inc: Locked -> Table lock mysql-test/suite/pbxt/t/lock_multi.test: Locked -> Table lock mysql-test/suite/sys_vars/r/concurrent_insert_func.result: Locked -> Table lock mysql-test/suite/sys_vars/t/concurrent_insert_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/delayed_insert_limit_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/sql_low_priority_updates_func.test: Locked -> Table lock mysql-test/t/insert_notembedded.test: Locked -> Table lock mysql-test/t/lock_multi.test: Locked -> Table lock mysql-test/t/merge-big.test: Locked -> Table lock mysql-test/t/multi_update.test: Locked -> Table lock mysql-test/t/query_cache_28249.test: Locked -> Table lock mysql-test/t/sp_notembedded.test: Locked -> Table lock mysql-test/t/sp_sync.test: Locked -> Table lock mysql-test/t/status.test: Locked -> Table lock mysql-test/t/trigger_notembedded.test: Locked -> Table lock mysys/thr_alarm.c: Added option to disable thr_alarm mysys/thr_lock.c: Detect loops scripts/mysql_install_db.sh: Give better error message if something goes wrong sql/Makefile.am: Added sql_handler.h sql/lock.cc: Split functions to allow one to cache value if store_lock() (for HANDLER functions). - Split mysql_lock_tables() into two functions, where first one allocates MYSQL_LOCK and other other one uses it. - Made get_lock_data() an external function. - Added argument to mysql_unlock_tables() to not free sql_lock. - Added argument to reset_lock_data() to reset lock structure to initial state (as after get_lock_data()) sql/mysql_priv.h: Moved handler function prototypes to sql_handler.h Added new lock functions. sql/mysqld.cc: Added --thread-alarm startup option sql/net_serv.cc: Don't call vio_blocking() if not needed sql/sql_base.cc: include sql_handler.h sql/sql_class.cc: include sql_handler.h Remove not anymore used 'thd->locked' member sql/sql_class.h: Remove not anymore used 'thd->locked' member sql/sql_db.cc: include sql_handler.h sql/sql_delete.cc: include sql_handler.h sql/sql_handler.cc: Rewrote all code to use SQL_HANDLER instead of TABLE_LIST (original interface) Rewrote mysql_ha_open() to cache all things from TABLE_LIST and items for field list, where etc. In mysql_ha_open() also cache MYSQL_LOCK structure from get_lock_data(). Split functions into smaller sub functions (needed to be able to implement mysql_ha_read_prepare()) Added mysql_ha_read_prepare() to allow one to prepare HANDLER READ. sql/sql_handler.h: Interface to sql_handler.cc sql/sql_parse.cc: include sql_handler.h sql/sql_prepare.cc: Added mysql_test_handler_read(), prepare for HANDLER READ sql/sql_rename.cc: include sql_handler.h sql/sql_show.cc: Removed usage of thd->locked sql/sql_table.cc: include sql_handler.h sql/sql_trigger.cc: include sql_handler.h
2011-01-04 00:55:41 +02:00
handler t1 open;
Fixed build issues - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client - Fixed bug in heap tables when doing handler read next-prev over last row BUILD/compile-dist: - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client cmd-line-utils/libedit/vi.c: Fixed compiler warning about not checking return value for write mysql-test/r/index_intersect.result: Updated results (missed this file in my last push) mysql-test/suite/handler/aria.result: Updated test results mysql-test/suite/handler/handler.inc: Changed test to use read next/read prev on key where there are duplicates that can come in different order depending on system Added testing of read next-prev over last row and read prev-next around first row mysql-test/suite/handler/heap.result: Updated test results mysql-test/suite/handler/init.inc: More rows to test mysql-test/suite/handler/innodb.result: Updated test results mysql-test/suite/handler/interface.result: Updated test results mysql-test/suite/handler/myisam.result: Updated test results mysql-test/t/variables-big.test: Fixed test to not fail on windows mysql-test/valgrind.supp: Removed not matching fun: to get rid of valgrind warning storage/heap/hp_rfirst.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rkey.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rnext.c: Handle reading several next after finding the last row (this caused a crash before) storage/heap/hp_rprev.c: Handle reading several prev after finding the first row (this caused a crash before) storage/xtradb/buf/buf0buf.c: Fixed compiler warning about uninitialized value
2011-02-23 14:46:16 +02:00
handler t1 read a=(20) limit 1,3;
Implementation of MWL#172: Add support for prepared statements to HANDLER READ It includes speed optimizations for HANDLER READ by caching as much as possible in HANDLER OPEN Other things: - Added mysqld option --disable-thr-alarm to be able to benchmark things without thr_alarm - Changed 'Locked' state to 'System lock' and 'Table lock' (these where used in the code but never shown to end user) - Better error message if mysql_install_db.sh fails - Moved handler function prototypes to sql_handler.h - Remove not anymore used 'thd->locked' member include/thr_alarm.h: Added my_disable_thr_alarm include/thr_lock.h: Add new member to THR_LOCK_DATA to remember original lock type state. This is needed as thr_unlock() resets type to TL_UNLOCK. mysql-test/include/check_no_concurrent_insert.inc: Locked -> Table lock mysql-test/include/handler.inc: Locked -> Table lock mysql-test/r/handler_innodb.result: Updated results for new tests mysql-test/r/handler_myisam.result: Updated results for new tests mysql-test/r/sp-threads.result: Locked -> Table lock mysql-test/suite/binlog/t/binlog_stm_row.test: Locked -> Table lock mysql-test/suite/funcs_1/datadict/processlist_val.inc: Locked -> Table lock mysql-test/suite/pbxt/t/lock_multi.test: Locked -> Table lock mysql-test/suite/sys_vars/r/concurrent_insert_func.result: Locked -> Table lock mysql-test/suite/sys_vars/t/concurrent_insert_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/delayed_insert_limit_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/sql_low_priority_updates_func.test: Locked -> Table lock mysql-test/t/insert_notembedded.test: Locked -> Table lock mysql-test/t/lock_multi.test: Locked -> Table lock mysql-test/t/merge-big.test: Locked -> Table lock mysql-test/t/multi_update.test: Locked -> Table lock mysql-test/t/query_cache_28249.test: Locked -> Table lock mysql-test/t/sp_notembedded.test: Locked -> Table lock mysql-test/t/sp_sync.test: Locked -> Table lock mysql-test/t/status.test: Locked -> Table lock mysql-test/t/trigger_notembedded.test: Locked -> Table lock mysys/thr_alarm.c: Added option to disable thr_alarm mysys/thr_lock.c: Detect loops scripts/mysql_install_db.sh: Give better error message if something goes wrong sql/Makefile.am: Added sql_handler.h sql/lock.cc: Split functions to allow one to cache value if store_lock() (for HANDLER functions). - Split mysql_lock_tables() into two functions, where first one allocates MYSQL_LOCK and other other one uses it. - Made get_lock_data() an external function. - Added argument to mysql_unlock_tables() to not free sql_lock. - Added argument to reset_lock_data() to reset lock structure to initial state (as after get_lock_data()) sql/mysql_priv.h: Moved handler function prototypes to sql_handler.h Added new lock functions. sql/mysqld.cc: Added --thread-alarm startup option sql/net_serv.cc: Don't call vio_blocking() if not needed sql/sql_base.cc: include sql_handler.h sql/sql_class.cc: include sql_handler.h Remove not anymore used 'thd->locked' member sql/sql_class.h: Remove not anymore used 'thd->locked' member sql/sql_db.cc: include sql_handler.h sql/sql_delete.cc: include sql_handler.h sql/sql_handler.cc: Rewrote all code to use SQL_HANDLER instead of TABLE_LIST (original interface) Rewrote mysql_ha_open() to cache all things from TABLE_LIST and items for field list, where etc. In mysql_ha_open() also cache MYSQL_LOCK structure from get_lock_data(). Split functions into smaller sub functions (needed to be able to implement mysql_ha_read_prepare()) Added mysql_ha_read_prepare() to allow one to prepare HANDLER READ. sql/sql_handler.h: Interface to sql_handler.cc sql/sql_parse.cc: include sql_handler.h sql/sql_prepare.cc: Added mysql_test_handler_read(), prepare for HANDLER READ sql/sql_rename.cc: include sql_handler.h sql/sql_show.cc: Removed usage of thd->locked sql/sql_table.cc: include sql_handler.h sql/sql_trigger.cc: include sql_handler.h
2011-01-04 00:55:41 +02:00
flush tables;
Fixed build issues - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client - Fixed bug in heap tables when doing handler read next-prev over last row BUILD/compile-dist: - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client cmd-line-utils/libedit/vi.c: Fixed compiler warning about not checking return value for write mysql-test/r/index_intersect.result: Updated results (missed this file in my last push) mysql-test/suite/handler/aria.result: Updated test results mysql-test/suite/handler/handler.inc: Changed test to use read next/read prev on key where there are duplicates that can come in different order depending on system Added testing of read next-prev over last row and read prev-next around first row mysql-test/suite/handler/heap.result: Updated test results mysql-test/suite/handler/init.inc: More rows to test mysql-test/suite/handler/innodb.result: Updated test results mysql-test/suite/handler/interface.result: Updated test results mysql-test/suite/handler/myisam.result: Updated test results mysql-test/t/variables-big.test: Fixed test to not fail on windows mysql-test/valgrind.supp: Removed not matching fun: to get rid of valgrind warning storage/heap/hp_rfirst.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rkey.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rnext.c: Handle reading several next after finding the last row (this caused a crash before) storage/heap/hp_rprev.c: Handle reading several prev after finding the first row (this caused a crash before) storage/xtradb/buf/buf0buf.c: Fixed compiler warning about uninitialized value
2011-02-23 14:46:16 +02:00
handler t1 read a=(20) limit 1,3;
handler t1 close;
#
# Search after end and before start of index
#
handler t1 open;
handler t1 read a=(25);
handler t1 read a next;
handler t1 read a next;
handler t1 read a next;
handler t1 read a prev;
handler t1 read a=(1000);
handler t1 read a next;
handler t1 read a prev;
handler t1 read a=(1000);
handler t1 read a prev;
handler t1 read a=(14);
handler t1 read a prev;
handler t1 read a prev;
handler t1 read a next;
handler t1 read a=(1);
handler t1 read a prev;
handler t1 read a next;
handler t1 read a=(1);
handler t1 read a next;
Implementation of MWL#172: Add support for prepared statements to HANDLER READ It includes speed optimizations for HANDLER READ by caching as much as possible in HANDLER OPEN Other things: - Added mysqld option --disable-thr-alarm to be able to benchmark things without thr_alarm - Changed 'Locked' state to 'System lock' and 'Table lock' (these where used in the code but never shown to end user) - Better error message if mysql_install_db.sh fails - Moved handler function prototypes to sql_handler.h - Remove not anymore used 'thd->locked' member include/thr_alarm.h: Added my_disable_thr_alarm include/thr_lock.h: Add new member to THR_LOCK_DATA to remember original lock type state. This is needed as thr_unlock() resets type to TL_UNLOCK. mysql-test/include/check_no_concurrent_insert.inc: Locked -> Table lock mysql-test/include/handler.inc: Locked -> Table lock mysql-test/r/handler_innodb.result: Updated results for new tests mysql-test/r/handler_myisam.result: Updated results for new tests mysql-test/r/sp-threads.result: Locked -> Table lock mysql-test/suite/binlog/t/binlog_stm_row.test: Locked -> Table lock mysql-test/suite/funcs_1/datadict/processlist_val.inc: Locked -> Table lock mysql-test/suite/pbxt/t/lock_multi.test: Locked -> Table lock mysql-test/suite/sys_vars/r/concurrent_insert_func.result: Locked -> Table lock mysql-test/suite/sys_vars/t/concurrent_insert_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/delayed_insert_limit_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/sql_low_priority_updates_func.test: Locked -> Table lock mysql-test/t/insert_notembedded.test: Locked -> Table lock mysql-test/t/lock_multi.test: Locked -> Table lock mysql-test/t/merge-big.test: Locked -> Table lock mysql-test/t/multi_update.test: Locked -> Table lock mysql-test/t/query_cache_28249.test: Locked -> Table lock mysql-test/t/sp_notembedded.test: Locked -> Table lock mysql-test/t/sp_sync.test: Locked -> Table lock mysql-test/t/status.test: Locked -> Table lock mysql-test/t/trigger_notembedded.test: Locked -> Table lock mysys/thr_alarm.c: Added option to disable thr_alarm mysys/thr_lock.c: Detect loops scripts/mysql_install_db.sh: Give better error message if something goes wrong sql/Makefile.am: Added sql_handler.h sql/lock.cc: Split functions to allow one to cache value if store_lock() (for HANDLER functions). - Split mysql_lock_tables() into two functions, where first one allocates MYSQL_LOCK and other other one uses it. - Made get_lock_data() an external function. - Added argument to mysql_unlock_tables() to not free sql_lock. - Added argument to reset_lock_data() to reset lock structure to initial state (as after get_lock_data()) sql/mysql_priv.h: Moved handler function prototypes to sql_handler.h Added new lock functions. sql/mysqld.cc: Added --thread-alarm startup option sql/net_serv.cc: Don't call vio_blocking() if not needed sql/sql_base.cc: include sql_handler.h sql/sql_class.cc: include sql_handler.h Remove not anymore used 'thd->locked' member sql/sql_class.h: Remove not anymore used 'thd->locked' member sql/sql_db.cc: include sql_handler.h sql/sql_delete.cc: include sql_handler.h sql/sql_handler.cc: Rewrote all code to use SQL_HANDLER instead of TABLE_LIST (original interface) Rewrote mysql_ha_open() to cache all things from TABLE_LIST and items for field list, where etc. In mysql_ha_open() also cache MYSQL_LOCK structure from get_lock_data(). Split functions into smaller sub functions (needed to be able to implement mysql_ha_read_prepare()) Added mysql_ha_read_prepare() to allow one to prepare HANDLER READ. sql/sql_handler.h: Interface to sql_handler.cc sql/sql_parse.cc: include sql_handler.h sql/sql_prepare.cc: Added mysql_test_handler_read(), prepare for HANDLER READ sql/sql_rename.cc: include sql_handler.h sql/sql_show.cc: Removed usage of thd->locked sql/sql_table.cc: include sql_handler.h sql/sql_trigger.cc: include sql_handler.h
2011-01-04 00:55:41 +02:00
handler t1 close;
#
# Test with prepared statements
#
handler t1 open;
prepare stmt from 'handler t1 read a=(?) limit ?,?';
Fixed build issues - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client - Fixed bug in heap tables when doing handler read next-prev over last row BUILD/compile-dist: - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client cmd-line-utils/libedit/vi.c: Fixed compiler warning about not checking return value for write mysql-test/r/index_intersect.result: Updated results (missed this file in my last push) mysql-test/suite/handler/aria.result: Updated test results mysql-test/suite/handler/handler.inc: Changed test to use read next/read prev on key where there are duplicates that can come in different order depending on system Added testing of read next-prev over last row and read prev-next around first row mysql-test/suite/handler/heap.result: Updated test results mysql-test/suite/handler/init.inc: More rows to test mysql-test/suite/handler/innodb.result: Updated test results mysql-test/suite/handler/interface.result: Updated test results mysql-test/suite/handler/myisam.result: Updated test results mysql-test/t/variables-big.test: Fixed test to not fail on windows mysql-test/valgrind.supp: Removed not matching fun: to get rid of valgrind warning storage/heap/hp_rfirst.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rkey.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rnext.c: Handle reading several next after finding the last row (this caused a crash before) storage/heap/hp_rprev.c: Handle reading several prev after finding the first row (this caused a crash before) storage/xtradb/buf/buf0buf.c: Fixed compiler warning about uninitialized value
2011-02-23 14:46:16 +02:00
set @a=20,@b=1,@c=100;
Implementation of MWL#172: Add support for prepared statements to HANDLER READ It includes speed optimizations for HANDLER READ by caching as much as possible in HANDLER OPEN Other things: - Added mysqld option --disable-thr-alarm to be able to benchmark things without thr_alarm - Changed 'Locked' state to 'System lock' and 'Table lock' (these where used in the code but never shown to end user) - Better error message if mysql_install_db.sh fails - Moved handler function prototypes to sql_handler.h - Remove not anymore used 'thd->locked' member include/thr_alarm.h: Added my_disable_thr_alarm include/thr_lock.h: Add new member to THR_LOCK_DATA to remember original lock type state. This is needed as thr_unlock() resets type to TL_UNLOCK. mysql-test/include/check_no_concurrent_insert.inc: Locked -> Table lock mysql-test/include/handler.inc: Locked -> Table lock mysql-test/r/handler_innodb.result: Updated results for new tests mysql-test/r/handler_myisam.result: Updated results for new tests mysql-test/r/sp-threads.result: Locked -> Table lock mysql-test/suite/binlog/t/binlog_stm_row.test: Locked -> Table lock mysql-test/suite/funcs_1/datadict/processlist_val.inc: Locked -> Table lock mysql-test/suite/pbxt/t/lock_multi.test: Locked -> Table lock mysql-test/suite/sys_vars/r/concurrent_insert_func.result: Locked -> Table lock mysql-test/suite/sys_vars/t/concurrent_insert_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/delayed_insert_limit_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/sql_low_priority_updates_func.test: Locked -> Table lock mysql-test/t/insert_notembedded.test: Locked -> Table lock mysql-test/t/lock_multi.test: Locked -> Table lock mysql-test/t/merge-big.test: Locked -> Table lock mysql-test/t/multi_update.test: Locked -> Table lock mysql-test/t/query_cache_28249.test: Locked -> Table lock mysql-test/t/sp_notembedded.test: Locked -> Table lock mysql-test/t/sp_sync.test: Locked -> Table lock mysql-test/t/status.test: Locked -> Table lock mysql-test/t/trigger_notembedded.test: Locked -> Table lock mysys/thr_alarm.c: Added option to disable thr_alarm mysys/thr_lock.c: Detect loops scripts/mysql_install_db.sh: Give better error message if something goes wrong sql/Makefile.am: Added sql_handler.h sql/lock.cc: Split functions to allow one to cache value if store_lock() (for HANDLER functions). - Split mysql_lock_tables() into two functions, where first one allocates MYSQL_LOCK and other other one uses it. - Made get_lock_data() an external function. - Added argument to mysql_unlock_tables() to not free sql_lock. - Added argument to reset_lock_data() to reset lock structure to initial state (as after get_lock_data()) sql/mysql_priv.h: Moved handler function prototypes to sql_handler.h Added new lock functions. sql/mysqld.cc: Added --thread-alarm startup option sql/net_serv.cc: Don't call vio_blocking() if not needed sql/sql_base.cc: include sql_handler.h sql/sql_class.cc: include sql_handler.h Remove not anymore used 'thd->locked' member sql/sql_class.h: Remove not anymore used 'thd->locked' member sql/sql_db.cc: include sql_handler.h sql/sql_delete.cc: include sql_handler.h sql/sql_handler.cc: Rewrote all code to use SQL_HANDLER instead of TABLE_LIST (original interface) Rewrote mysql_ha_open() to cache all things from TABLE_LIST and items for field list, where etc. In mysql_ha_open() also cache MYSQL_LOCK structure from get_lock_data(). Split functions into smaller sub functions (needed to be able to implement mysql_ha_read_prepare()) Added mysql_ha_read_prepare() to allow one to prepare HANDLER READ. sql/sql_handler.h: Interface to sql_handler.cc sql/sql_parse.cc: include sql_handler.h sql/sql_prepare.cc: Added mysql_test_handler_read(), prepare for HANDLER READ sql/sql_rename.cc: include sql_handler.h sql/sql_show.cc: Removed usage of thd->locked sql/sql_table.cc: include sql_handler.h sql/sql_trigger.cc: include sql_handler.h
2011-01-04 00:55:41 +02:00
execute stmt using @a,@b,@c;
Fixed build issues - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client - Fixed bug in heap tables when doing handler read next-prev over last row BUILD/compile-dist: - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client cmd-line-utils/libedit/vi.c: Fixed compiler warning about not checking return value for write mysql-test/r/index_intersect.result: Updated results (missed this file in my last push) mysql-test/suite/handler/aria.result: Updated test results mysql-test/suite/handler/handler.inc: Changed test to use read next/read prev on key where there are duplicates that can come in different order depending on system Added testing of read next-prev over last row and read prev-next around first row mysql-test/suite/handler/heap.result: Updated test results mysql-test/suite/handler/init.inc: More rows to test mysql-test/suite/handler/innodb.result: Updated test results mysql-test/suite/handler/interface.result: Updated test results mysql-test/suite/handler/myisam.result: Updated test results mysql-test/t/variables-big.test: Fixed test to not fail on windows mysql-test/valgrind.supp: Removed not matching fun: to get rid of valgrind warning storage/heap/hp_rfirst.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rkey.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rnext.c: Handle reading several next after finding the last row (this caused a crash before) storage/heap/hp_rprev.c: Handle reading several prev after finding the first row (this caused a crash before) storage/xtradb/buf/buf0buf.c: Fixed compiler warning about uninitialized value
2011-02-23 14:46:16 +02:00
set @a=20,@b=2,@c=1;
Implementation of MWL#172: Add support for prepared statements to HANDLER READ It includes speed optimizations for HANDLER READ by caching as much as possible in HANDLER OPEN Other things: - Added mysqld option --disable-thr-alarm to be able to benchmark things without thr_alarm - Changed 'Locked' state to 'System lock' and 'Table lock' (these where used in the code but never shown to end user) - Better error message if mysql_install_db.sh fails - Moved handler function prototypes to sql_handler.h - Remove not anymore used 'thd->locked' member include/thr_alarm.h: Added my_disable_thr_alarm include/thr_lock.h: Add new member to THR_LOCK_DATA to remember original lock type state. This is needed as thr_unlock() resets type to TL_UNLOCK. mysql-test/include/check_no_concurrent_insert.inc: Locked -> Table lock mysql-test/include/handler.inc: Locked -> Table lock mysql-test/r/handler_innodb.result: Updated results for new tests mysql-test/r/handler_myisam.result: Updated results for new tests mysql-test/r/sp-threads.result: Locked -> Table lock mysql-test/suite/binlog/t/binlog_stm_row.test: Locked -> Table lock mysql-test/suite/funcs_1/datadict/processlist_val.inc: Locked -> Table lock mysql-test/suite/pbxt/t/lock_multi.test: Locked -> Table lock mysql-test/suite/sys_vars/r/concurrent_insert_func.result: Locked -> Table lock mysql-test/suite/sys_vars/t/concurrent_insert_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/delayed_insert_limit_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/sql_low_priority_updates_func.test: Locked -> Table lock mysql-test/t/insert_notembedded.test: Locked -> Table lock mysql-test/t/lock_multi.test: Locked -> Table lock mysql-test/t/merge-big.test: Locked -> Table lock mysql-test/t/multi_update.test: Locked -> Table lock mysql-test/t/query_cache_28249.test: Locked -> Table lock mysql-test/t/sp_notembedded.test: Locked -> Table lock mysql-test/t/sp_sync.test: Locked -> Table lock mysql-test/t/status.test: Locked -> Table lock mysql-test/t/trigger_notembedded.test: Locked -> Table lock mysys/thr_alarm.c: Added option to disable thr_alarm mysys/thr_lock.c: Detect loops scripts/mysql_install_db.sh: Give better error message if something goes wrong sql/Makefile.am: Added sql_handler.h sql/lock.cc: Split functions to allow one to cache value if store_lock() (for HANDLER functions). - Split mysql_lock_tables() into two functions, where first one allocates MYSQL_LOCK and other other one uses it. - Made get_lock_data() an external function. - Added argument to mysql_unlock_tables() to not free sql_lock. - Added argument to reset_lock_data() to reset lock structure to initial state (as after get_lock_data()) sql/mysql_priv.h: Moved handler function prototypes to sql_handler.h Added new lock functions. sql/mysqld.cc: Added --thread-alarm startup option sql/net_serv.cc: Don't call vio_blocking() if not needed sql/sql_base.cc: include sql_handler.h sql/sql_class.cc: include sql_handler.h Remove not anymore used 'thd->locked' member sql/sql_class.h: Remove not anymore used 'thd->locked' member sql/sql_db.cc: include sql_handler.h sql/sql_delete.cc: include sql_handler.h sql/sql_handler.cc: Rewrote all code to use SQL_HANDLER instead of TABLE_LIST (original interface) Rewrote mysql_ha_open() to cache all things from TABLE_LIST and items for field list, where etc. In mysql_ha_open() also cache MYSQL_LOCK structure from get_lock_data(). Split functions into smaller sub functions (needed to be able to implement mysql_ha_read_prepare()) Added mysql_ha_read_prepare() to allow one to prepare HANDLER READ. sql/sql_handler.h: Interface to sql_handler.cc sql/sql_parse.cc: include sql_handler.h sql/sql_prepare.cc: Added mysql_test_handler_read(), prepare for HANDLER READ sql/sql_rename.cc: include sql_handler.h sql/sql_show.cc: Removed usage of thd->locked sql/sql_table.cc: include sql_handler.h sql/sql_trigger.cc: include sql_handler.h
2011-01-04 00:55:41 +02:00
execute stmt using @a,@b,@c;
Fixed build issues - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client - Fixed bug in heap tables when doing handler read next-prev over last row BUILD/compile-dist: - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client cmd-line-utils/libedit/vi.c: Fixed compiler warning about not checking return value for write mysql-test/r/index_intersect.result: Updated results (missed this file in my last push) mysql-test/suite/handler/aria.result: Updated test results mysql-test/suite/handler/handler.inc: Changed test to use read next/read prev on key where there are duplicates that can come in different order depending on system Added testing of read next-prev over last row and read prev-next around first row mysql-test/suite/handler/heap.result: Updated test results mysql-test/suite/handler/init.inc: More rows to test mysql-test/suite/handler/innodb.result: Updated test results mysql-test/suite/handler/interface.result: Updated test results mysql-test/suite/handler/myisam.result: Updated test results mysql-test/t/variables-big.test: Fixed test to not fail on windows mysql-test/valgrind.supp: Removed not matching fun: to get rid of valgrind warning storage/heap/hp_rfirst.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rkey.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rnext.c: Handle reading several next after finding the last row (this caused a crash before) storage/heap/hp_rprev.c: Handle reading several prev after finding the first row (this caused a crash before) storage/xtradb/buf/buf0buf.c: Fixed compiler warning about uninitialized value
2011-02-23 14:46:16 +02:00
set @a=20,@b=0,@c=2;
Implementation of MWL#172: Add support for prepared statements to HANDLER READ It includes speed optimizations for HANDLER READ by caching as much as possible in HANDLER OPEN Other things: - Added mysqld option --disable-thr-alarm to be able to benchmark things without thr_alarm - Changed 'Locked' state to 'System lock' and 'Table lock' (these where used in the code but never shown to end user) - Better error message if mysql_install_db.sh fails - Moved handler function prototypes to sql_handler.h - Remove not anymore used 'thd->locked' member include/thr_alarm.h: Added my_disable_thr_alarm include/thr_lock.h: Add new member to THR_LOCK_DATA to remember original lock type state. This is needed as thr_unlock() resets type to TL_UNLOCK. mysql-test/include/check_no_concurrent_insert.inc: Locked -> Table lock mysql-test/include/handler.inc: Locked -> Table lock mysql-test/r/handler_innodb.result: Updated results for new tests mysql-test/r/handler_myisam.result: Updated results for new tests mysql-test/r/sp-threads.result: Locked -> Table lock mysql-test/suite/binlog/t/binlog_stm_row.test: Locked -> Table lock mysql-test/suite/funcs_1/datadict/processlist_val.inc: Locked -> Table lock mysql-test/suite/pbxt/t/lock_multi.test: Locked -> Table lock mysql-test/suite/sys_vars/r/concurrent_insert_func.result: Locked -> Table lock mysql-test/suite/sys_vars/t/concurrent_insert_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/delayed_insert_limit_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/sql_low_priority_updates_func.test: Locked -> Table lock mysql-test/t/insert_notembedded.test: Locked -> Table lock mysql-test/t/lock_multi.test: Locked -> Table lock mysql-test/t/merge-big.test: Locked -> Table lock mysql-test/t/multi_update.test: Locked -> Table lock mysql-test/t/query_cache_28249.test: Locked -> Table lock mysql-test/t/sp_notembedded.test: Locked -> Table lock mysql-test/t/sp_sync.test: Locked -> Table lock mysql-test/t/status.test: Locked -> Table lock mysql-test/t/trigger_notembedded.test: Locked -> Table lock mysys/thr_alarm.c: Added option to disable thr_alarm mysys/thr_lock.c: Detect loops scripts/mysql_install_db.sh: Give better error message if something goes wrong sql/Makefile.am: Added sql_handler.h sql/lock.cc: Split functions to allow one to cache value if store_lock() (for HANDLER functions). - Split mysql_lock_tables() into two functions, where first one allocates MYSQL_LOCK and other other one uses it. - Made get_lock_data() an external function. - Added argument to mysql_unlock_tables() to not free sql_lock. - Added argument to reset_lock_data() to reset lock structure to initial state (as after get_lock_data()) sql/mysql_priv.h: Moved handler function prototypes to sql_handler.h Added new lock functions. sql/mysqld.cc: Added --thread-alarm startup option sql/net_serv.cc: Don't call vio_blocking() if not needed sql/sql_base.cc: include sql_handler.h sql/sql_class.cc: include sql_handler.h Remove not anymore used 'thd->locked' member sql/sql_class.h: Remove not anymore used 'thd->locked' member sql/sql_db.cc: include sql_handler.h sql/sql_delete.cc: include sql_handler.h sql/sql_handler.cc: Rewrote all code to use SQL_HANDLER instead of TABLE_LIST (original interface) Rewrote mysql_ha_open() to cache all things from TABLE_LIST and items for field list, where etc. In mysql_ha_open() also cache MYSQL_LOCK structure from get_lock_data(). Split functions into smaller sub functions (needed to be able to implement mysql_ha_read_prepare()) Added mysql_ha_read_prepare() to allow one to prepare HANDLER READ. sql/sql_handler.h: Interface to sql_handler.cc sql/sql_parse.cc: include sql_handler.h sql/sql_prepare.cc: Added mysql_test_handler_read(), prepare for HANDLER READ sql/sql_rename.cc: include sql_handler.h sql/sql_show.cc: Removed usage of thd->locked sql/sql_table.cc: include sql_handler.h sql/sql_trigger.cc: include sql_handler.h
2011-01-04 00:55:41 +02:00
execute stmt using @a,@b,@c;
deallocate prepare stmt;
prepare stmt from 'handler t1 read a next limit ?';
Fixed build issues - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client - Fixed bug in heap tables when doing handler read next-prev over last row BUILD/compile-dist: - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client cmd-line-utils/libedit/vi.c: Fixed compiler warning about not checking return value for write mysql-test/r/index_intersect.result: Updated results (missed this file in my last push) mysql-test/suite/handler/aria.result: Updated test results mysql-test/suite/handler/handler.inc: Changed test to use read next/read prev on key where there are duplicates that can come in different order depending on system Added testing of read next-prev over last row and read prev-next around first row mysql-test/suite/handler/heap.result: Updated test results mysql-test/suite/handler/init.inc: More rows to test mysql-test/suite/handler/innodb.result: Updated test results mysql-test/suite/handler/interface.result: Updated test results mysql-test/suite/handler/myisam.result: Updated test results mysql-test/t/variables-big.test: Fixed test to not fail on windows mysql-test/valgrind.supp: Removed not matching fun: to get rid of valgrind warning storage/heap/hp_rfirst.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rkey.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rnext.c: Handle reading several next after finding the last row (this caused a crash before) storage/heap/hp_rprev.c: Handle reading several prev after finding the first row (this caused a crash before) storage/xtradb/buf/buf0buf.c: Fixed compiler warning about uninitialized value
2011-02-23 14:46:16 +02:00
handler t1 read a>=(21);
Implementation of MWL#172: Add support for prepared statements to HANDLER READ It includes speed optimizations for HANDLER READ by caching as much as possible in HANDLER OPEN Other things: - Added mysqld option --disable-thr-alarm to be able to benchmark things without thr_alarm - Changed 'Locked' state to 'System lock' and 'Table lock' (these where used in the code but never shown to end user) - Better error message if mysql_install_db.sh fails - Moved handler function prototypes to sql_handler.h - Remove not anymore used 'thd->locked' member include/thr_alarm.h: Added my_disable_thr_alarm include/thr_lock.h: Add new member to THR_LOCK_DATA to remember original lock type state. This is needed as thr_unlock() resets type to TL_UNLOCK. mysql-test/include/check_no_concurrent_insert.inc: Locked -> Table lock mysql-test/include/handler.inc: Locked -> Table lock mysql-test/r/handler_innodb.result: Updated results for new tests mysql-test/r/handler_myisam.result: Updated results for new tests mysql-test/r/sp-threads.result: Locked -> Table lock mysql-test/suite/binlog/t/binlog_stm_row.test: Locked -> Table lock mysql-test/suite/funcs_1/datadict/processlist_val.inc: Locked -> Table lock mysql-test/suite/pbxt/t/lock_multi.test: Locked -> Table lock mysql-test/suite/sys_vars/r/concurrent_insert_func.result: Locked -> Table lock mysql-test/suite/sys_vars/t/concurrent_insert_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/delayed_insert_limit_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/sql_low_priority_updates_func.test: Locked -> Table lock mysql-test/t/insert_notembedded.test: Locked -> Table lock mysql-test/t/lock_multi.test: Locked -> Table lock mysql-test/t/merge-big.test: Locked -> Table lock mysql-test/t/multi_update.test: Locked -> Table lock mysql-test/t/query_cache_28249.test: Locked -> Table lock mysql-test/t/sp_notembedded.test: Locked -> Table lock mysql-test/t/sp_sync.test: Locked -> Table lock mysql-test/t/status.test: Locked -> Table lock mysql-test/t/trigger_notembedded.test: Locked -> Table lock mysys/thr_alarm.c: Added option to disable thr_alarm mysys/thr_lock.c: Detect loops scripts/mysql_install_db.sh: Give better error message if something goes wrong sql/Makefile.am: Added sql_handler.h sql/lock.cc: Split functions to allow one to cache value if store_lock() (for HANDLER functions). - Split mysql_lock_tables() into two functions, where first one allocates MYSQL_LOCK and other other one uses it. - Made get_lock_data() an external function. - Added argument to mysql_unlock_tables() to not free sql_lock. - Added argument to reset_lock_data() to reset lock structure to initial state (as after get_lock_data()) sql/mysql_priv.h: Moved handler function prototypes to sql_handler.h Added new lock functions. sql/mysqld.cc: Added --thread-alarm startup option sql/net_serv.cc: Don't call vio_blocking() if not needed sql/sql_base.cc: include sql_handler.h sql/sql_class.cc: include sql_handler.h Remove not anymore used 'thd->locked' member sql/sql_class.h: Remove not anymore used 'thd->locked' member sql/sql_db.cc: include sql_handler.h sql/sql_delete.cc: include sql_handler.h sql/sql_handler.cc: Rewrote all code to use SQL_HANDLER instead of TABLE_LIST (original interface) Rewrote mysql_ha_open() to cache all things from TABLE_LIST and items for field list, where etc. In mysql_ha_open() also cache MYSQL_LOCK structure from get_lock_data(). Split functions into smaller sub functions (needed to be able to implement mysql_ha_read_prepare()) Added mysql_ha_read_prepare() to allow one to prepare HANDLER READ. sql/sql_handler.h: Interface to sql_handler.cc sql/sql_parse.cc: include sql_handler.h sql/sql_prepare.cc: Added mysql_test_handler_read(), prepare for HANDLER READ sql/sql_rename.cc: include sql_handler.h sql/sql_show.cc: Removed usage of thd->locked sql/sql_table.cc: include sql_handler.h sql/sql_trigger.cc: include sql_handler.h
2011-01-04 00:55:41 +02:00
set @a=3;
execute stmt using @a;
execute stmt using @a;
execute stmt using @a;
deallocate prepare stmt;
prepare stmt from 'handler t1 read b prev limit ?';
execute stmt using @a;
execute stmt using @a;
execute stmt using @a;
execute stmt using @a;
deallocate prepare stmt;
prepare stmt from 'handler t1 read b=(?,?)';
set @a=14, @b='aaa';
execute stmt using @a,@b;
set @a=14, @b='not found';
execute stmt using @a,@b;
deallocate prepare stmt;
prepare stmt from 'handler t1 read b=(1+?) limit 10';
set @a=15;
execute stmt using @a;
execute stmt using @a;
deallocate prepare stmt;
prepare stmt from 'handler t1 read b>=(?) where a < ? limit 5';
Fixed build issues - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client - Fixed bug in heap tables when doing handler read next-prev over last row BUILD/compile-dist: - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client cmd-line-utils/libedit/vi.c: Fixed compiler warning about not checking return value for write mysql-test/r/index_intersect.result: Updated results (missed this file in my last push) mysql-test/suite/handler/aria.result: Updated test results mysql-test/suite/handler/handler.inc: Changed test to use read next/read prev on key where there are duplicates that can come in different order depending on system Added testing of read next-prev over last row and read prev-next around first row mysql-test/suite/handler/heap.result: Updated test results mysql-test/suite/handler/init.inc: More rows to test mysql-test/suite/handler/innodb.result: Updated test results mysql-test/suite/handler/interface.result: Updated test results mysql-test/suite/handler/myisam.result: Updated test results mysql-test/t/variables-big.test: Fixed test to not fail on windows mysql-test/valgrind.supp: Removed not matching fun: to get rid of valgrind warning storage/heap/hp_rfirst.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rkey.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rnext.c: Handle reading several next after finding the last row (this caused a crash before) storage/heap/hp_rprev.c: Handle reading several prev after finding the first row (this caused a crash before) storage/xtradb/buf/buf0buf.c: Fixed compiler warning about uninitialized value
2011-02-23 14:46:16 +02:00
set @a=17, @b=24;
Implementation of MWL#172: Add support for prepared statements to HANDLER READ It includes speed optimizations for HANDLER READ by caching as much as possible in HANDLER OPEN Other things: - Added mysqld option --disable-thr-alarm to be able to benchmark things without thr_alarm - Changed 'Locked' state to 'System lock' and 'Table lock' (these where used in the code but never shown to end user) - Better error message if mysql_install_db.sh fails - Moved handler function prototypes to sql_handler.h - Remove not anymore used 'thd->locked' member include/thr_alarm.h: Added my_disable_thr_alarm include/thr_lock.h: Add new member to THR_LOCK_DATA to remember original lock type state. This is needed as thr_unlock() resets type to TL_UNLOCK. mysql-test/include/check_no_concurrent_insert.inc: Locked -> Table lock mysql-test/include/handler.inc: Locked -> Table lock mysql-test/r/handler_innodb.result: Updated results for new tests mysql-test/r/handler_myisam.result: Updated results for new tests mysql-test/r/sp-threads.result: Locked -> Table lock mysql-test/suite/binlog/t/binlog_stm_row.test: Locked -> Table lock mysql-test/suite/funcs_1/datadict/processlist_val.inc: Locked -> Table lock mysql-test/suite/pbxt/t/lock_multi.test: Locked -> Table lock mysql-test/suite/sys_vars/r/concurrent_insert_func.result: Locked -> Table lock mysql-test/suite/sys_vars/t/concurrent_insert_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/delayed_insert_limit_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/sql_low_priority_updates_func.test: Locked -> Table lock mysql-test/t/insert_notembedded.test: Locked -> Table lock mysql-test/t/lock_multi.test: Locked -> Table lock mysql-test/t/merge-big.test: Locked -> Table lock mysql-test/t/multi_update.test: Locked -> Table lock mysql-test/t/query_cache_28249.test: Locked -> Table lock mysql-test/t/sp_notembedded.test: Locked -> Table lock mysql-test/t/sp_sync.test: Locked -> Table lock mysql-test/t/status.test: Locked -> Table lock mysql-test/t/trigger_notembedded.test: Locked -> Table lock mysys/thr_alarm.c: Added option to disable thr_alarm mysys/thr_lock.c: Detect loops scripts/mysql_install_db.sh: Give better error message if something goes wrong sql/Makefile.am: Added sql_handler.h sql/lock.cc: Split functions to allow one to cache value if store_lock() (for HANDLER functions). - Split mysql_lock_tables() into two functions, where first one allocates MYSQL_LOCK and other other one uses it. - Made get_lock_data() an external function. - Added argument to mysql_unlock_tables() to not free sql_lock. - Added argument to reset_lock_data() to reset lock structure to initial state (as after get_lock_data()) sql/mysql_priv.h: Moved handler function prototypes to sql_handler.h Added new lock functions. sql/mysqld.cc: Added --thread-alarm startup option sql/net_serv.cc: Don't call vio_blocking() if not needed sql/sql_base.cc: include sql_handler.h sql/sql_class.cc: include sql_handler.h Remove not anymore used 'thd->locked' member sql/sql_class.h: Remove not anymore used 'thd->locked' member sql/sql_db.cc: include sql_handler.h sql/sql_delete.cc: include sql_handler.h sql/sql_handler.cc: Rewrote all code to use SQL_HANDLER instead of TABLE_LIST (original interface) Rewrote mysql_ha_open() to cache all things from TABLE_LIST and items for field list, where etc. In mysql_ha_open() also cache MYSQL_LOCK structure from get_lock_data(). Split functions into smaller sub functions (needed to be able to implement mysql_ha_read_prepare()) Added mysql_ha_read_prepare() to allow one to prepare HANDLER READ. sql/sql_handler.h: Interface to sql_handler.cc sql/sql_parse.cc: include sql_handler.h sql/sql_prepare.cc: Added mysql_test_handler_read(), prepare for HANDLER READ sql/sql_rename.cc: include sql_handler.h sql/sql_show.cc: Removed usage of thd->locked sql/sql_table.cc: include sql_handler.h sql/sql_trigger.cc: include sql_handler.h
2011-01-04 00:55:41 +02:00
execute stmt using @a,@b;
execute stmt using @a,@b;
deallocate prepare stmt;
prepare stmt from 'handler t1 read a=(?)';
Fixed build issues - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client - Fixed bug in heap tables when doing handler read next-prev over last row BUILD/compile-dist: - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client cmd-line-utils/libedit/vi.c: Fixed compiler warning about not checking return value for write mysql-test/r/index_intersect.result: Updated results (missed this file in my last push) mysql-test/suite/handler/aria.result: Updated test results mysql-test/suite/handler/handler.inc: Changed test to use read next/read prev on key where there are duplicates that can come in different order depending on system Added testing of read next-prev over last row and read prev-next around first row mysql-test/suite/handler/heap.result: Updated test results mysql-test/suite/handler/init.inc: More rows to test mysql-test/suite/handler/innodb.result: Updated test results mysql-test/suite/handler/interface.result: Updated test results mysql-test/suite/handler/myisam.result: Updated test results mysql-test/t/variables-big.test: Fixed test to not fail on windows mysql-test/valgrind.supp: Removed not matching fun: to get rid of valgrind warning storage/heap/hp_rfirst.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rkey.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rnext.c: Handle reading several next after finding the last row (this caused a crash before) storage/heap/hp_rprev.c: Handle reading several prev after finding the first row (this caused a crash before) storage/xtradb/buf/buf0buf.c: Fixed compiler warning about uninitialized value
2011-02-23 14:46:16 +02:00
set @a=17;
Implementation of MWL#172: Add support for prepared statements to HANDLER READ It includes speed optimizations for HANDLER READ by caching as much as possible in HANDLER OPEN Other things: - Added mysqld option --disable-thr-alarm to be able to benchmark things without thr_alarm - Changed 'Locked' state to 'System lock' and 'Table lock' (these where used in the code but never shown to end user) - Better error message if mysql_install_db.sh fails - Moved handler function prototypes to sql_handler.h - Remove not anymore used 'thd->locked' member include/thr_alarm.h: Added my_disable_thr_alarm include/thr_lock.h: Add new member to THR_LOCK_DATA to remember original lock type state. This is needed as thr_unlock() resets type to TL_UNLOCK. mysql-test/include/check_no_concurrent_insert.inc: Locked -> Table lock mysql-test/include/handler.inc: Locked -> Table lock mysql-test/r/handler_innodb.result: Updated results for new tests mysql-test/r/handler_myisam.result: Updated results for new tests mysql-test/r/sp-threads.result: Locked -> Table lock mysql-test/suite/binlog/t/binlog_stm_row.test: Locked -> Table lock mysql-test/suite/funcs_1/datadict/processlist_val.inc: Locked -> Table lock mysql-test/suite/pbxt/t/lock_multi.test: Locked -> Table lock mysql-test/suite/sys_vars/r/concurrent_insert_func.result: Locked -> Table lock mysql-test/suite/sys_vars/t/concurrent_insert_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/delayed_insert_limit_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/sql_low_priority_updates_func.test: Locked -> Table lock mysql-test/t/insert_notembedded.test: Locked -> Table lock mysql-test/t/lock_multi.test: Locked -> Table lock mysql-test/t/merge-big.test: Locked -> Table lock mysql-test/t/multi_update.test: Locked -> Table lock mysql-test/t/query_cache_28249.test: Locked -> Table lock mysql-test/t/sp_notembedded.test: Locked -> Table lock mysql-test/t/sp_sync.test: Locked -> Table lock mysql-test/t/status.test: Locked -> Table lock mysql-test/t/trigger_notembedded.test: Locked -> Table lock mysys/thr_alarm.c: Added option to disable thr_alarm mysys/thr_lock.c: Detect loops scripts/mysql_install_db.sh: Give better error message if something goes wrong sql/Makefile.am: Added sql_handler.h sql/lock.cc: Split functions to allow one to cache value if store_lock() (for HANDLER functions). - Split mysql_lock_tables() into two functions, where first one allocates MYSQL_LOCK and other other one uses it. - Made get_lock_data() an external function. - Added argument to mysql_unlock_tables() to not free sql_lock. - Added argument to reset_lock_data() to reset lock structure to initial state (as after get_lock_data()) sql/mysql_priv.h: Moved handler function prototypes to sql_handler.h Added new lock functions. sql/mysqld.cc: Added --thread-alarm startup option sql/net_serv.cc: Don't call vio_blocking() if not needed sql/sql_base.cc: include sql_handler.h sql/sql_class.cc: include sql_handler.h Remove not anymore used 'thd->locked' member sql/sql_class.h: Remove not anymore used 'thd->locked' member sql/sql_db.cc: include sql_handler.h sql/sql_delete.cc: include sql_handler.h sql/sql_handler.cc: Rewrote all code to use SQL_HANDLER instead of TABLE_LIST (original interface) Rewrote mysql_ha_open() to cache all things from TABLE_LIST and items for field list, where etc. In mysql_ha_open() also cache MYSQL_LOCK structure from get_lock_data(). Split functions into smaller sub functions (needed to be able to implement mysql_ha_read_prepare()) Added mysql_ha_read_prepare() to allow one to prepare HANDLER READ. sql/sql_handler.h: Interface to sql_handler.cc sql/sql_parse.cc: include sql_handler.h sql/sql_prepare.cc: Added mysql_test_handler_read(), prepare for HANDLER READ sql/sql_rename.cc: include sql_handler.h sql/sql_show.cc: Removed usage of thd->locked sql/sql_table.cc: include sql_handler.h sql/sql_trigger.cc: include sql_handler.h
2011-01-04 00:55:41 +02:00
execute stmt using @a;
alter table t1 add c int;
--error 1109
execute stmt using @a;
deallocate prepare stmt;
--error 1109
handler t1 close;
handler t1 open;
prepare stmt from 'handler t1 read a=(?)';
flush tables;
Fixed build issues - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client - Fixed bug in heap tables when doing handler read next-prev over last row BUILD/compile-dist: - Linking now with g++ instead of gcc with 'compile-dist' to solve problems with handlersocket/client cmd-line-utils/libedit/vi.c: Fixed compiler warning about not checking return value for write mysql-test/r/index_intersect.result: Updated results (missed this file in my last push) mysql-test/suite/handler/aria.result: Updated test results mysql-test/suite/handler/handler.inc: Changed test to use read next/read prev on key where there are duplicates that can come in different order depending on system Added testing of read next-prev over last row and read prev-next around first row mysql-test/suite/handler/heap.result: Updated test results mysql-test/suite/handler/init.inc: More rows to test mysql-test/suite/handler/innodb.result: Updated test results mysql-test/suite/handler/interface.result: Updated test results mysql-test/suite/handler/myisam.result: Updated test results mysql-test/t/variables-big.test: Fixed test to not fail on windows mysql-test/valgrind.supp: Removed not matching fun: to get rid of valgrind warning storage/heap/hp_rfirst.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rkey.c: Added state so that we know if we have an active position in the index. storage/heap/hp_rnext.c: Handle reading several next after finding the last row (this caused a crash before) storage/heap/hp_rprev.c: Handle reading several prev after finding the first row (this caused a crash before) storage/xtradb/buf/buf0buf.c: Fixed compiler warning about uninitialized value
2011-02-23 14:46:16 +02:00
set @a=17;
Implementation of MWL#172: Add support for prepared statements to HANDLER READ It includes speed optimizations for HANDLER READ by caching as much as possible in HANDLER OPEN Other things: - Added mysqld option --disable-thr-alarm to be able to benchmark things without thr_alarm - Changed 'Locked' state to 'System lock' and 'Table lock' (these where used in the code but never shown to end user) - Better error message if mysql_install_db.sh fails - Moved handler function prototypes to sql_handler.h - Remove not anymore used 'thd->locked' member include/thr_alarm.h: Added my_disable_thr_alarm include/thr_lock.h: Add new member to THR_LOCK_DATA to remember original lock type state. This is needed as thr_unlock() resets type to TL_UNLOCK. mysql-test/include/check_no_concurrent_insert.inc: Locked -> Table lock mysql-test/include/handler.inc: Locked -> Table lock mysql-test/r/handler_innodb.result: Updated results for new tests mysql-test/r/handler_myisam.result: Updated results for new tests mysql-test/r/sp-threads.result: Locked -> Table lock mysql-test/suite/binlog/t/binlog_stm_row.test: Locked -> Table lock mysql-test/suite/funcs_1/datadict/processlist_val.inc: Locked -> Table lock mysql-test/suite/pbxt/t/lock_multi.test: Locked -> Table lock mysql-test/suite/sys_vars/r/concurrent_insert_func.result: Locked -> Table lock mysql-test/suite/sys_vars/t/concurrent_insert_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/delayed_insert_limit_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Locked -> Table lock mysql-test/suite/sys_vars/t/sql_low_priority_updates_func.test: Locked -> Table lock mysql-test/t/insert_notembedded.test: Locked -> Table lock mysql-test/t/lock_multi.test: Locked -> Table lock mysql-test/t/merge-big.test: Locked -> Table lock mysql-test/t/multi_update.test: Locked -> Table lock mysql-test/t/query_cache_28249.test: Locked -> Table lock mysql-test/t/sp_notembedded.test: Locked -> Table lock mysql-test/t/sp_sync.test: Locked -> Table lock mysql-test/t/status.test: Locked -> Table lock mysql-test/t/trigger_notembedded.test: Locked -> Table lock mysys/thr_alarm.c: Added option to disable thr_alarm mysys/thr_lock.c: Detect loops scripts/mysql_install_db.sh: Give better error message if something goes wrong sql/Makefile.am: Added sql_handler.h sql/lock.cc: Split functions to allow one to cache value if store_lock() (for HANDLER functions). - Split mysql_lock_tables() into two functions, where first one allocates MYSQL_LOCK and other other one uses it. - Made get_lock_data() an external function. - Added argument to mysql_unlock_tables() to not free sql_lock. - Added argument to reset_lock_data() to reset lock structure to initial state (as after get_lock_data()) sql/mysql_priv.h: Moved handler function prototypes to sql_handler.h Added new lock functions. sql/mysqld.cc: Added --thread-alarm startup option sql/net_serv.cc: Don't call vio_blocking() if not needed sql/sql_base.cc: include sql_handler.h sql/sql_class.cc: include sql_handler.h Remove not anymore used 'thd->locked' member sql/sql_class.h: Remove not anymore used 'thd->locked' member sql/sql_db.cc: include sql_handler.h sql/sql_delete.cc: include sql_handler.h sql/sql_handler.cc: Rewrote all code to use SQL_HANDLER instead of TABLE_LIST (original interface) Rewrote mysql_ha_open() to cache all things from TABLE_LIST and items for field list, where etc. In mysql_ha_open() also cache MYSQL_LOCK structure from get_lock_data(). Split functions into smaller sub functions (needed to be able to implement mysql_ha_read_prepare()) Added mysql_ha_read_prepare() to allow one to prepare HANDLER READ. sql/sql_handler.h: Interface to sql_handler.cc sql/sql_parse.cc: include sql_handler.h sql/sql_prepare.cc: Added mysql_test_handler_read(), prepare for HANDLER READ sql/sql_rename.cc: include sql_handler.h sql/sql_show.cc: Removed usage of thd->locked sql/sql_table.cc: include sql_handler.h sql/sql_trigger.cc: include sql_handler.h
2011-01-04 00:55:41 +02:00
execute stmt using @a;
deallocate prepare stmt;
handler t1 close;
#
2003-02-22 18:22:39 +01:00
# DROP TABLE / ALTER TABLE
#
handler t1 open as t2;
drop table t1;
- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
create table t1 (a int not null);
insert into t1 values (17);
--error 1109
handler t2 read first;
2003-02-22 18:22:39 +01:00
handler t1 open as t2;
alter table t1 engine=csv;
2003-02-22 18:22:39 +01:00
--error 1109
handler t2 read first;
drop table t1;
#
After merge fixes Use server character set if --default-character-set is not used Added convert_string() for more efficient alloc+character-set convert of strings BitKeeper/deleted/.del-convert.result~a3b56e1db6f498e9: Delete: mysql-test/r/convert.result BitKeeper/deleted/.del-convert.test~f4ceb743194dfe72: Delete: mysql-test/t/convert.test BitKeeper/deleted/.del-make_win_src_distribution.old~5c9ebdc4a852b43b: Delete: scripts/make_win_src_distribution.old client/mysql.cc: Use server character set if --default-character-set is not used client/mysqltest.c: Code cleanup (merge identical code) More debug messages heap/hp_create.c: After merge fix include/m_ctype.h: After merge fix include/my_global.h: Remove size_str (we already have size_s) include/mysql_com.h: After merge fix libmysql/libmysql.c: After merge fix libmysqld/Makefile.am: After merge fix mysql-test/r/auto_increment.result: After merge fix mysql-test/r/create.result: After merge fix mysql-test/r/ctype_latin1_de.result: After merge fix mysql-test/r/distinct.result: After merge fix mysql-test/r/drop.result: After merge fix mysql-test/r/fulltext.result: After merge fix mysql-test/r/func_gconcat.result: After merge fix mysql-test/r/func_str.result: After merge fix mysql-test/r/func_test.result: After merge fix mysql-test/r/grant.result: After merge fix mysql-test/r/group_by.result: After merge fix mysql-test/r/handler.result: After merge fix mysql-test/r/heap.result: After merge fix mysql-test/r/heap_btree.result: After merge fix mysql-test/r/heap_hash.result: After merge fix mysql-test/r/innodb.result: After merge fix mysql-test/r/insert.result: After merge fix mysql-test/r/insert_select.result: After merge fix mysql-test/r/join_outer.result: After merge fix mysql-test/r/key.result: After merge fix mysql-test/r/key_cache.result: After merge fix mysql-test/r/loaddata.result: After merge fix mysql-test/r/myisam.result: After merge fix mysql-test/r/null.result: After merge fix mysql-test/r/null_key.result: After merge fix mysql-test/r/order_by.result: After merge fix mysql-test/r/rpl_do_grant.result: After merge fix mysql-test/r/rpl_error_ignored_table.result: After merge fix mysql-test/r/rpl_ignore_grant.result: After merge fix mysql-test/r/rpl_loaddata.result: After merge fix mysql-test/r/rpl_log.result: After merge fix mysql-test/r/rpl_log_pos.result: After merge fix mysql-test/r/rpl_max_relay_size.result: After merge fix mysql-test/r/rpl_replicate_do.result: After merge fix mysql-test/r/rpl_reset_slave.result: After merge fix mysql-test/r/rpl_rotate_logs.result: After merge fix mysql-test/r/rpl_user_variables.result: After merge fix mysql-test/r/select.result: After merge fix mysql-test/r/select_safe.result: After merge fix mysql-test/r/subselect.result: After merge fix mysql-test/r/type_blob.result: After merge fix mysql-test/r/type_decimal.result: After merge fix mysql-test/r/type_float.result: After merge fix mysql-test/r/type_ranges.result: After merge fix mysql-test/r/type_time.result: After merge fix mysql-test/r/type_uint.result: After merge fix mysql-test/r/union.result: After merge fix mysql-test/r/warnings.result: After merge fix mysql-test/t/auto_increment.test: After merge fix mysql-test/t/case.test: After merge fix mysql-test/t/ctype_collate.test: After merge fix mysql-test/t/ctype_latin1_de.test: After merge fix mysql-test/t/drop.test: After merge fix mysql-test/t/func_in.test: After merge fix mysql-test/t/func_set.test: After merge fix mysql-test/t/func_str.test: After merge fix mysql-test/t/func_test.test: After merge fix mysql-test/t/grant.test: After merge fix mysql-test/t/group_by.test: After merge fix mysql-test/t/handler.test: After merge fix mysql-test/t/heap.test: After merge fix mysql-test/t/heap_btree.test: After merge fix mysql-test/t/heap_hash.test: After merge fix mysql-test/t/innodb.test: After merge fix mysql-test/t/insert_select.test: After merge fix mysql-test/t/key.test: After merge fix mysql-test/t/key_cache.test: After merge fix mysql-test/t/lock_tables_lost_commit-master.opt: After merge fix mysql-test/t/lock_tables_lost_commit.test: After merge fix mysql-test/t/myisam.test: After merge fix mysql-test/t/row.test: After merge fix mysql-test/t/subselect.test: After merge fix mysql-test/t/type_decimal.test: After merge fix mysql-test/t/type_ranges.test: After merge fix mysql-test/t/type_uint.test: After merge fix mysql-test/t/variables.test: After merge fix mysql-test/t/warnings.test: After merge fix scripts/make_win_src_distribution.sh: after merge fixes sql-common/client.c: After merge fix Change my_connect() to use poll() If character set is not given, use servers character set. sql/field.cc: After merge fix Don't give warnings when storing data in fields in optimizer. sql/ha_myisammrg.h: After merge fix sql/log.cc: After merge fix sql/log_event.cc: After merge fix sql/mysqld.cc: After merge fix sql/opt_range.cc: After merge fix sql/set_var.cc: Code cleanup Fixed wrong usage of base_names (like medium.key_buffer) that caused core dumps sql/set_var.h: Fixed wrong usage of base_names (like medium.key_buffer) that caused core dumps sql/slave.cc: After merge fix sql/sql_acl.cc: After merge fix Code cleanup sql/sql_class.cc: Added convert_string() for more efficient alloc+character-set convert of strings Add cached flags to avoid calling mysql_charset_same() during parsing. sql/sql_class.h: Added convert_string() for more efficient alloc+character-set convert of strings Add cached flags to avoid calling mysql_charset_same() during parsing. sql/sql_handler.cc: After merge fix sql/sql_lex.h: After merge fix sql/sql_parse.cc: Optimize and fix memory reference errors reported by valgrind sql/sql_repl.cc: After merge fix sql/sql_yacc.yy: After merge fix Avoid calling mysql_charset_same() when parsing identifiers strings/ctype-latin1.c: Port latin_de conversion code from 4.0
2003-08-19 00:08:08 +03:00
# Test case for the bug #787
#
create table t1 (a int);
insert into t1 values (1),(2),(3),(4),(5),(6);
delete from t1 limit 2;
handler t1 open;
handler t1 read first;
handler t1 read first limit 1,1;
handler t1 read first limit 2,2;
delete from t1 limit 3;
handler t1 read first;
drop table t1;
#
After merge fixes Use server character set if --default-character-set is not used Added convert_string() for more efficient alloc+character-set convert of strings BitKeeper/deleted/.del-convert.result~a3b56e1db6f498e9: Delete: mysql-test/r/convert.result BitKeeper/deleted/.del-convert.test~f4ceb743194dfe72: Delete: mysql-test/t/convert.test BitKeeper/deleted/.del-make_win_src_distribution.old~5c9ebdc4a852b43b: Delete: scripts/make_win_src_distribution.old client/mysql.cc: Use server character set if --default-character-set is not used client/mysqltest.c: Code cleanup (merge identical code) More debug messages heap/hp_create.c: After merge fix include/m_ctype.h: After merge fix include/my_global.h: Remove size_str (we already have size_s) include/mysql_com.h: After merge fix libmysql/libmysql.c: After merge fix libmysqld/Makefile.am: After merge fix mysql-test/r/auto_increment.result: After merge fix mysql-test/r/create.result: After merge fix mysql-test/r/ctype_latin1_de.result: After merge fix mysql-test/r/distinct.result: After merge fix mysql-test/r/drop.result: After merge fix mysql-test/r/fulltext.result: After merge fix mysql-test/r/func_gconcat.result: After merge fix mysql-test/r/func_str.result: After merge fix mysql-test/r/func_test.result: After merge fix mysql-test/r/grant.result: After merge fix mysql-test/r/group_by.result: After merge fix mysql-test/r/handler.result: After merge fix mysql-test/r/heap.result: After merge fix mysql-test/r/heap_btree.result: After merge fix mysql-test/r/heap_hash.result: After merge fix mysql-test/r/innodb.result: After merge fix mysql-test/r/insert.result: After merge fix mysql-test/r/insert_select.result: After merge fix mysql-test/r/join_outer.result: After merge fix mysql-test/r/key.result: After merge fix mysql-test/r/key_cache.result: After merge fix mysql-test/r/loaddata.result: After merge fix mysql-test/r/myisam.result: After merge fix mysql-test/r/null.result: After merge fix mysql-test/r/null_key.result: After merge fix mysql-test/r/order_by.result: After merge fix mysql-test/r/rpl_do_grant.result: After merge fix mysql-test/r/rpl_error_ignored_table.result: After merge fix mysql-test/r/rpl_ignore_grant.result: After merge fix mysql-test/r/rpl_loaddata.result: After merge fix mysql-test/r/rpl_log.result: After merge fix mysql-test/r/rpl_log_pos.result: After merge fix mysql-test/r/rpl_max_relay_size.result: After merge fix mysql-test/r/rpl_replicate_do.result: After merge fix mysql-test/r/rpl_reset_slave.result: After merge fix mysql-test/r/rpl_rotate_logs.result: After merge fix mysql-test/r/rpl_user_variables.result: After merge fix mysql-test/r/select.result: After merge fix mysql-test/r/select_safe.result: After merge fix mysql-test/r/subselect.result: After merge fix mysql-test/r/type_blob.result: After merge fix mysql-test/r/type_decimal.result: After merge fix mysql-test/r/type_float.result: After merge fix mysql-test/r/type_ranges.result: After merge fix mysql-test/r/type_time.result: After merge fix mysql-test/r/type_uint.result: After merge fix mysql-test/r/union.result: After merge fix mysql-test/r/warnings.result: After merge fix mysql-test/t/auto_increment.test: After merge fix mysql-test/t/case.test: After merge fix mysql-test/t/ctype_collate.test: After merge fix mysql-test/t/ctype_latin1_de.test: After merge fix mysql-test/t/drop.test: After merge fix mysql-test/t/func_in.test: After merge fix mysql-test/t/func_set.test: After merge fix mysql-test/t/func_str.test: After merge fix mysql-test/t/func_test.test: After merge fix mysql-test/t/grant.test: After merge fix mysql-test/t/group_by.test: After merge fix mysql-test/t/handler.test: After merge fix mysql-test/t/heap.test: After merge fix mysql-test/t/heap_btree.test: After merge fix mysql-test/t/heap_hash.test: After merge fix mysql-test/t/innodb.test: After merge fix mysql-test/t/insert_select.test: After merge fix mysql-test/t/key.test: After merge fix mysql-test/t/key_cache.test: After merge fix mysql-test/t/lock_tables_lost_commit-master.opt: After merge fix mysql-test/t/lock_tables_lost_commit.test: After merge fix mysql-test/t/myisam.test: After merge fix mysql-test/t/row.test: After merge fix mysql-test/t/subselect.test: After merge fix mysql-test/t/type_decimal.test: After merge fix mysql-test/t/type_ranges.test: After merge fix mysql-test/t/type_uint.test: After merge fix mysql-test/t/variables.test: After merge fix mysql-test/t/warnings.test: After merge fix scripts/make_win_src_distribution.sh: after merge fixes sql-common/client.c: After merge fix Change my_connect() to use poll() If character set is not given, use servers character set. sql/field.cc: After merge fix Don't give warnings when storing data in fields in optimizer. sql/ha_myisammrg.h: After merge fix sql/log.cc: After merge fix sql/log_event.cc: After merge fix sql/mysqld.cc: After merge fix sql/opt_range.cc: After merge fix sql/set_var.cc: Code cleanup Fixed wrong usage of base_names (like medium.key_buffer) that caused core dumps sql/set_var.h: Fixed wrong usage of base_names (like medium.key_buffer) that caused core dumps sql/slave.cc: After merge fix sql/sql_acl.cc: After merge fix Code cleanup sql/sql_class.cc: Added convert_string() for more efficient alloc+character-set convert of strings Add cached flags to avoid calling mysql_charset_same() during parsing. sql/sql_class.h: Added convert_string() for more efficient alloc+character-set convert of strings Add cached flags to avoid calling mysql_charset_same() during parsing. sql/sql_handler.cc: After merge fix sql/sql_lex.h: After merge fix sql/sql_parse.cc: Optimize and fix memory reference errors reported by valgrind sql/sql_repl.cc: After merge fix sql/sql_yacc.yy: After merge fix Avoid calling mysql_charset_same() when parsing identifiers strings/ctype-latin1.c: Port latin_de conversion code from 4.0
2003-08-19 00:08:08 +03:00
# Test for #751
#
create table t1(a int, index using btree (a));
insert into t1 values (1), (2), (3);
handler t1 open;
--error 1054
handler t1 read a=(W);
--error 1210
handler t1 read a=(a);
drop table t1;
#
# BUG#2304
#
create table t1 (a char(5));
insert into t1 values ("Ok");
handler t1 open as t;
handler t read first;
use mysql;
handler t read first;
handler t close;
handler test.t1 open as t;
handler t read first;
handler t close;
use test;
drop table t1;
#
# BUG#3649
#
create table t1 ( a int, b int, INDEX a using btree (a) );
insert into t1 values (1,2), (2,1);
handler t1 open;
handler t1 read a=(1) where b=2;
handler t1 read a=(1) where b=3;
handler t1 read a=(1) where b=1;
handler t1 close;
drop table t1;
BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the HANDLER functions and interface. Using a HASH to store information on open tables that survives FLUSH TABLE. HANDLER tables alias names must now be unique, though it is allowed in 4.0 to qualify them with the database name of the base table. mysql-test/r/flush_table.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results to handler.result. Added the new test results. mysql-test/r/handler.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results from flush_table.result to here. mysql-test/t/flush_table.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests to handler.test. Added new tests. mysql-test/t/handler.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests from flush_table.test to here. sql/mysql_priv.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the handler interface. sql/sql_base.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Replaced mysql_ha_close_list() by the better named function mysql_ha_flush() with readable options. sql/sql_class.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added initialization for the handler tables hash. Changed the handler tables clean-up code. Unreleted to bug: Changed the order of THD initialization to avoid warning messages on Linux with gcc. sql/sql_class.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added the handler tables HASH to THD. sql/sql_handler.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Completely reworked the handler functions. Added an introducing comment, describing the new functionality. sql/sql_table.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. replaced mysql_ha_close() by the better named function mysql_ha_flush() with readable options.
2004-09-24 18:39:25 +02:00
#
# Test if fix for BUG#4286 correctly closes handler tables.
#
create table t1 (c1 char(20));
insert into t1 values ("t1");
handler t1 open as h1;
handler h1 read first limit 9;
create table t2 (c1 char(20));
insert into t2 values ("t2");
handler t2 open as h2;
handler h2 read first limit 9;
create table t3 (c1 char(20));
insert into t3 values ("t3");
handler t3 open as h3;
handler h3 read first limit 9;
create table t4 (c1 char(20));
insert into t4 values ("t4");
handler t4 open as h4;
handler h4 read first limit 9;
create table t5 (c1 char(20));
insert into t5 values ("t5");
handler t5 open as h5;
handler h5 read first limit 9;
# close first
2006-08-16 19:29:49 +02:00
eval alter table t1 engine=$other_handler_engine_type;
--error 1109
BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the HANDLER functions and interface. Using a HASH to store information on open tables that survives FLUSH TABLE. HANDLER tables alias names must now be unique, though it is allowed in 4.0 to qualify them with the database name of the base table. mysql-test/r/flush_table.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results to handler.result. Added the new test results. mysql-test/r/handler.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results from flush_table.result to here. mysql-test/t/flush_table.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests to handler.test. Added new tests. mysql-test/t/handler.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests from flush_table.test to here. sql/mysql_priv.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the handler interface. sql/sql_base.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Replaced mysql_ha_close_list() by the better named function mysql_ha_flush() with readable options. sql/sql_class.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added initialization for the handler tables hash. Changed the handler tables clean-up code. Unreleted to bug: Changed the order of THD initialization to avoid warning messages on Linux with gcc. sql/sql_class.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added the handler tables HASH to THD. sql/sql_handler.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Completely reworked the handler functions. Added an introducing comment, describing the new functionality. sql/sql_table.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. replaced mysql_ha_close() by the better named function mysql_ha_flush() with readable options.
2004-09-24 18:39:25 +02:00
handler h1 read first limit 9;
handler h2 read first limit 9;
handler h3 read first limit 9;
handler h4 read first limit 9;
handler h5 read first limit 9;
# close last
2006-08-16 19:29:49 +02:00
eval alter table t5 engine=$other_handler_engine_type;
--error 1109
BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the HANDLER functions and interface. Using a HASH to store information on open tables that survives FLUSH TABLE. HANDLER tables alias names must now be unique, though it is allowed in 4.0 to qualify them with the database name of the base table. mysql-test/r/flush_table.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results to handler.result. Added the new test results. mysql-test/r/handler.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results from flush_table.result to here. mysql-test/t/flush_table.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests to handler.test. Added new tests. mysql-test/t/handler.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests from flush_table.test to here. sql/mysql_priv.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the handler interface. sql/sql_base.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Replaced mysql_ha_close_list() by the better named function mysql_ha_flush() with readable options. sql/sql_class.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added initialization for the handler tables hash. Changed the handler tables clean-up code. Unreleted to bug: Changed the order of THD initialization to avoid warning messages on Linux with gcc. sql/sql_class.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added the handler tables HASH to THD. sql/sql_handler.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Completely reworked the handler functions. Added an introducing comment, describing the new functionality. sql/sql_table.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. replaced mysql_ha_close() by the better named function mysql_ha_flush() with readable options.
2004-09-24 18:39:25 +02:00
handler h1 read first limit 9;
handler h2 read first limit 9;
handler h3 read first limit 9;
handler h4 read first limit 9;
--error 1109
BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the HANDLER functions and interface. Using a HASH to store information on open tables that survives FLUSH TABLE. HANDLER tables alias names must now be unique, though it is allowed in 4.0 to qualify them with the database name of the base table. mysql-test/r/flush_table.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results to handler.result. Added the new test results. mysql-test/r/handler.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results from flush_table.result to here. mysql-test/t/flush_table.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests to handler.test. Added new tests. mysql-test/t/handler.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests from flush_table.test to here. sql/mysql_priv.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the handler interface. sql/sql_base.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Replaced mysql_ha_close_list() by the better named function mysql_ha_flush() with readable options. sql/sql_class.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added initialization for the handler tables hash. Changed the handler tables clean-up code. Unreleted to bug: Changed the order of THD initialization to avoid warning messages on Linux with gcc. sql/sql_class.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added the handler tables HASH to THD. sql/sql_handler.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Completely reworked the handler functions. Added an introducing comment, describing the new functionality. sql/sql_table.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. replaced mysql_ha_close() by the better named function mysql_ha_flush() with readable options.
2004-09-24 18:39:25 +02:00
handler h5 read first limit 9;
# close middle
2006-08-16 19:29:49 +02:00
eval alter table t3 engine=$other_handler_engine_type;
--error 1109
BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the HANDLER functions and interface. Using a HASH to store information on open tables that survives FLUSH TABLE. HANDLER tables alias names must now be unique, though it is allowed in 4.0 to qualify them with the database name of the base table. mysql-test/r/flush_table.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results to handler.result. Added the new test results. mysql-test/r/handler.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results from flush_table.result to here. mysql-test/t/flush_table.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests to handler.test. Added new tests. mysql-test/t/handler.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests from flush_table.test to here. sql/mysql_priv.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the handler interface. sql/sql_base.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Replaced mysql_ha_close_list() by the better named function mysql_ha_flush() with readable options. sql/sql_class.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added initialization for the handler tables hash. Changed the handler tables clean-up code. Unreleted to bug: Changed the order of THD initialization to avoid warning messages on Linux with gcc. sql/sql_class.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added the handler tables HASH to THD. sql/sql_handler.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Completely reworked the handler functions. Added an introducing comment, describing the new functionality. sql/sql_table.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. replaced mysql_ha_close() by the better named function mysql_ha_flush() with readable options.
2004-09-24 18:39:25 +02:00
handler h1 read first limit 9;
handler h2 read first limit 9;
--error 1109
BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the HANDLER functions and interface. Using a HASH to store information on open tables that survives FLUSH TABLE. HANDLER tables alias names must now be unique, though it is allowed in 4.0 to qualify them with the database name of the base table. mysql-test/r/flush_table.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results to handler.result. Added the new test results. mysql-test/r/handler.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results from flush_table.result to here. mysql-test/t/flush_table.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests to handler.test. Added new tests. mysql-test/t/handler.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests from flush_table.test to here. sql/mysql_priv.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the handler interface. sql/sql_base.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Replaced mysql_ha_close_list() by the better named function mysql_ha_flush() with readable options. sql/sql_class.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added initialization for the handler tables hash. Changed the handler tables clean-up code. Unreleted to bug: Changed the order of THD initialization to avoid warning messages on Linux with gcc. sql/sql_class.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added the handler tables HASH to THD. sql/sql_handler.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Completely reworked the handler functions. Added an introducing comment, describing the new functionality. sql/sql_table.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. replaced mysql_ha_close() by the better named function mysql_ha_flush() with readable options.
2004-09-24 18:39:25 +02:00
handler h3 read first limit 9;
handler h4 read first limit 9;
--error 1109
BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the HANDLER functions and interface. Using a HASH to store information on open tables that survives FLUSH TABLE. HANDLER tables alias names must now be unique, though it is allowed in 4.0 to qualify them with the database name of the base table. mysql-test/r/flush_table.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results to handler.result. Added the new test results. mysql-test/r/handler.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results from flush_table.result to here. mysql-test/t/flush_table.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests to handler.test. Added new tests. mysql-test/t/handler.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests from flush_table.test to here. sql/mysql_priv.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the handler interface. sql/sql_base.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Replaced mysql_ha_close_list() by the better named function mysql_ha_flush() with readable options. sql/sql_class.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added initialization for the handler tables hash. Changed the handler tables clean-up code. Unreleted to bug: Changed the order of THD initialization to avoid warning messages on Linux with gcc. sql/sql_class.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added the handler tables HASH to THD. sql/sql_handler.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Completely reworked the handler functions. Added an introducing comment, describing the new functionality. sql/sql_table.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. replaced mysql_ha_close() by the better named function mysql_ha_flush() with readable options.
2004-09-24 18:39:25 +02:00
handler h5 read first limit 9;
handler h2 close;
handler h4 close;
# close all depending handler tables
handler t1 open as h1_1;
handler t1 open as h1_2;
handler t1 open as h1_3;
handler h1_1 read first limit 9;
handler h1_2 read first limit 9;
handler h1_3 read first limit 9;
2006-08-16 19:29:49 +02:00
eval alter table t1 engine=$engine_type;
--error 1109
BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the HANDLER functions and interface. Using a HASH to store information on open tables that survives FLUSH TABLE. HANDLER tables alias names must now be unique, though it is allowed in 4.0 to qualify them with the database name of the base table. mysql-test/r/flush_table.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results to handler.result. Added the new test results. mysql-test/r/handler.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results from flush_table.result to here. mysql-test/t/flush_table.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests to handler.test. Added new tests. mysql-test/t/handler.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests from flush_table.test to here. sql/mysql_priv.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the handler interface. sql/sql_base.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Replaced mysql_ha_close_list() by the better named function mysql_ha_flush() with readable options. sql/sql_class.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added initialization for the handler tables hash. Changed the handler tables clean-up code. Unreleted to bug: Changed the order of THD initialization to avoid warning messages on Linux with gcc. sql/sql_class.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added the handler tables HASH to THD. sql/sql_handler.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Completely reworked the handler functions. Added an introducing comment, describing the new functionality. sql/sql_table.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. replaced mysql_ha_close() by the better named function mysql_ha_flush() with readable options.
2004-09-24 18:39:25 +02:00
handler h1_1 read first limit 9;
--error 1109
BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the HANDLER functions and interface. Using a HASH to store information on open tables that survives FLUSH TABLE. HANDLER tables alias names must now be unique, though it is allowed in 4.0 to qualify them with the database name of the base table. mysql-test/r/flush_table.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results to handler.result. Added the new test results. mysql-test/r/handler.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results from flush_table.result to here. mysql-test/t/flush_table.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests to handler.test. Added new tests. mysql-test/t/handler.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests from flush_table.test to here. sql/mysql_priv.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the handler interface. sql/sql_base.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Replaced mysql_ha_close_list() by the better named function mysql_ha_flush() with readable options. sql/sql_class.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added initialization for the handler tables hash. Changed the handler tables clean-up code. Unreleted to bug: Changed the order of THD initialization to avoid warning messages on Linux with gcc. sql/sql_class.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added the handler tables HASH to THD. sql/sql_handler.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Completely reworked the handler functions. Added an introducing comment, describing the new functionality. sql/sql_table.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. replaced mysql_ha_close() by the better named function mysql_ha_flush() with readable options.
2004-09-24 18:39:25 +02:00
handler h1_2 read first limit 9;
--error 1109
BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the HANDLER functions and interface. Using a HASH to store information on open tables that survives FLUSH TABLE. HANDLER tables alias names must now be unique, though it is allowed in 4.0 to qualify them with the database name of the base table. mysql-test/r/flush_table.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results to handler.result. Added the new test results. mysql-test/r/handler.result: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler test results from flush_table.result to here. mysql-test/t/flush_table.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests to handler.test. Added new tests. mysql-test/t/handler.test: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Moved pure handler tests from flush_table.test to here. sql/mysql_priv.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Reworked the handler interface. sql/sql_base.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Replaced mysql_ha_close_list() by the better named function mysql_ha_flush() with readable options. sql/sql_class.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added initialization for the handler tables hash. Changed the handler tables clean-up code. Unreleted to bug: Changed the order of THD initialization to avoid warning messages on Linux with gcc. sql/sql_class.h: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Added the handler tables HASH to THD. sql/sql_handler.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. Completely reworked the handler functions. Added an introducing comment, describing the new functionality. sql/sql_table.cc: BUG#4286 - HANDLER tables are closed by FLUSH TABLE(S). BUG#4335 - one name can be handler open'ed many times. replaced mysql_ha_close() by the better named function mysql_ha_flush() with readable options.
2004-09-24 18:39:25 +02:00
handler h1_3 read first limit 9;
drop table t1;
drop table t2;
drop table t3;
drop table t4;
drop table t5;
Added end marker for tests to make future merges easier mysql-test/t/alias.test: Added end marker for test to make future merges easier mysql-test/t/alter_table.test: Added end marker for test to make future merges easier mysql-test/t/analyse.test: Added end marker for test to make future merges easier mysql-test/t/analyze.test: Added end marker for test to make future merges easier Fixed length of comment lines mysql-test/t/ansi.test: Added end marker for test to make future merges easier mysql-test/t/archive.test: Added end marker for test to make future merges easier mysql-test/t/auto_increment.test: Added end marker for test to make future merges easier mysql-test/t/backup.test: Added end marker for test to make future merges easier mysql-test/t/bdb-alter-table-1.test: Added end marker for test to make future merges easier mysql-test/t/bdb-alter-table-2.test: Added end marker for test to make future merges easier mysql-test/t/bdb-crash.test: Added end marker for test to make future merges easier mysql-test/t/bdb-deadlock.test: Added end marker for test to make future merges easier mysql-test/t/bdb-deadlock.tminus: Added end marker for test to make future merges easier mysql-test/t/bdb.test: Added end marker for test to make future merges easier mysql-test/t/bdb_cache.test: Added end marker for test to make future merges easier mysql-test/t/bench_count_distinct.test: Added end marker for test to make future merges easier mysql-test/t/bigint.test: Added end marker for test to make future merges easier mysql-test/t/binary.test: Added end marker for test to make future merges easier mysql-test/t/blackhole.test: Added end marker for test to make future merges easier mysql-test/t/bool.test: Added end marker for test to make future merges easier mysql-test/t/bulk_replace.test: Added end marker for test to make future merges easier mysql-test/t/case.test: Added end marker for test to make future merges easier mysql-test/t/cast.test: Added end marker for test to make future merges easier mysql-test/t/check.test: Added end marker for test to make future merges easier mysql-test/t/comments.test: Added end marker for test to make future merges easier mysql-test/t/compare.test: Added end marker for test to make future merges easier mysql-test/t/connect.test: Added end marker for test to make future merges easier mysql-test/t/consistent_snapshot.test: Added end marker for test to make future merges easier mysql-test/t/constraints.test: Added end marker for test to make future merges easier mysql-test/t/count_distinct.test: Added end marker for test to make future merges easier mysql-test/t/count_distinct2.test: Added end marker for test to make future merges easier mysql-test/t/count_distinct3.test: Added end marker for test to make future merges easier mysql-test/t/create.test: Added end marker for test to make future merges easier mysql-test/t/create_select_tmp.test: Added end marker for test to make future merges easier mysql-test/t/csv.test: Added end marker for test to make future merges easier mysql-test/t/ctype_big5.test: Added end marker for test to make future merges easier mysql-test/t/ctype_collate.test: Added end marker for test to make future merges easier mysql-test/t/ctype_cp1250_ch.test: Added end marker for test to make future merges easier mysql-test/t/ctype_cp1251.test: Added end marker for test to make future merges easier mysql-test/t/ctype_cp932.test: Added end marker for test to make future merges easier mysql-test/t/ctype_create.test: Added end marker for test to make future merges easier mysql-test/t/ctype_gbk.test: Added end marker for test to make future merges easier mysql-test/t/ctype_latin1.test: Added end marker for test to make future merges easier mysql-test/t/ctype_latin1_de.test: Added end marker for test to make future merges easier mysql-test/t/ctype_latin2.test: Added end marker for test to make future merges easier mysql-test/t/ctype_many.test: Added end marker for test to make future merges easier mysql-test/t/ctype_mb.test: Added end marker for test to make future merges easier mysql-test/t/ctype_recoding.test: Added end marker for test to make future merges easier mysql-test/t/ctype_sjis.test: Added end marker for test to make future merges easier mysql-test/t/ctype_tis620.test: Added end marker for test to make future merges easier mysql-test/t/ctype_uca.test: Added end marker for test to make future merges easier mysql-test/t/ctype_ucs.test: Added end marker for test to make future merges easier mysql-test/t/ctype_ucs_binlog.test: Added end marker for test to make future merges easier mysql-test/t/ctype_ujis.test: Added end marker for test to make future merges easier mysql-test/t/ctype_utf8.test: Added end marker for test to make future merges easier mysql-test/t/date_formats.test: Added end marker for test to make future merges easier mysql-test/t/delayed.test: Added end marker for test to make future merges easier mysql-test/t/delete.test: Added end marker for test to make future merges easier mysql-test/t/derived.test: Added end marker for test to make future merges easier mysql-test/t/dirty_close.test: Added end marker for test to make future merges easier mysql-test/t/distinct.test: Added end marker for test to make future merges easier mysql-test/t/drop.test: Added end marker for test to make future merges easier mysql-test/t/drop_temp_table.test: Added end marker for test to make future merges easier mysql-test/t/empty_table.test: Added end marker for test to make future merges easier mysql-test/t/endspace.test: Added end marker for test to make future merges easier mysql-test/t/errors.test: Added end marker for test to make future merges easier mysql-test/t/exampledb.test: Added end marker for test to make future merges easier mysql-test/t/explain.test: Added end marker for test to make future merges easier mysql-test/t/flush.test: Added end marker for test to make future merges easier mysql-test/t/flush_block_commit.test: Added end marker for test to make future merges easier mysql-test/t/flush_table.test: Added end marker for test to make future merges easier mysql-test/t/foreign_key.test: Added end marker for test to make future merges easier mysql-test/t/fulltext.test: Added end marker for test to make future merges easier mysql-test/t/fulltext2.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_cache.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_distinct.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_left_join.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_multi.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_order_by.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_update.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_var.test: Added end marker for test to make future merges easier mysql-test/t/func_compress.test: Added end marker for test to make future merges easier mysql-test/t/func_concat.test: Added end marker for test to make future merges easier mysql-test/t/func_crypt.test: Added end marker for test to make future merges easier mysql-test/t/func_date_add.test: Added end marker for test to make future merges easier mysql-test/t/func_default.test: Added end marker for test to make future merges easier mysql-test/t/func_des_encrypt.test: Added end marker for test to make future merges easier mysql-test/t/func_encrypt.test: Added end marker for test to make future merges easier mysql-test/t/func_encrypt_nossl.test: Added end marker for test to make future merges easier mysql-test/t/func_equal.test: Added end marker for test to make future merges easier mysql-test/t/func_gconcat.test: Added end marker for test to make future merges easier mysql-test/t/func_group.test: Added end marker for test to make future merges easier mysql-test/t/func_if.test: Added end marker for test to make future merges easier mysql-test/t/func_in.test: Added end marker for test to make future merges easier mysql-test/t/func_isnull.test: Added end marker for test to make future merges easier mysql-test/t/func_like.test: Added end marker for test to make future merges easier mysql-test/t/func_math.test: Added end marker for test to make future merges easier mysql-test/t/func_misc.test: Added end marker for test to make future merges easier mysql-test/t/func_op.test: Added end marker for test to make future merges easier mysql-test/t/func_regexp.test: Added end marker for test to make future merges easier mysql-test/t/func_sapdb.test: Added end marker for test to make future merges easier mysql-test/t/func_set.test: Added end marker for test to make future merges easier mysql-test/t/func_str.test: Added end marker for test to make future merges easier mysql-test/t/func_system.test: Added end marker for test to make future merges easier mysql-test/t/func_test.test: Added end marker for test to make future merges easier mysql-test/t/func_time.test: Added end marker for test to make future merges easier mysql-test/t/func_timestamp.test: Added end marker for test to make future merges easier mysql-test/t/gcc296.test: Added end marker for test to make future merges easier mysql-test/t/gis-rtree.test: Added end marker for test to make future merges easier mysql-test/t/gis.test: Added end marker for test to make future merges easier mysql-test/t/grant.test: Added end marker for test to make future merges easier mysql-test/t/grant2.test: Added end marker for test to make future merges easier mysql-test/t/grant_cache.test: Added end marker for test to make future merges easier mysql-test/t/group_by.test: Added end marker for test to make future merges easier mysql-test/t/handler.test: Added end marker for test to make future merges easier mysql-test/t/having.test: Added end marker for test to make future merges easier mysql-test/t/heap.test: Added end marker for test to make future merges easier mysql-test/t/heap_auto_increment.test: Added end marker for test to make future merges easier mysql-test/t/heap_btree.test: Added end marker for test to make future merges easier mysql-test/t/heap_hash.test: Added end marker for test to make future merges easier mysql-test/t/help.test: Added end marker for test to make future merges easier mysql-test/t/init_connect.test: Added end marker for test to make future merges easier mysql-test/t/init_file.test: Added end marker for test to make future merges easier mysql-test/t/innodb-deadlock.test: Added end marker for test to make future merges easier mysql-test/t/innodb-lock.test: Added end marker for test to make future merges easier mysql-test/t/innodb-replace.test: Added end marker for test to make future merges easier mysql-test/t/innodb.test: Added end marker for test to make future merges easier mysql-test/t/innodb_cache.test: Added end marker for test to make future merges easier mysql-test/t/innodb_handler.test: Added end marker for test to make future merges easier mysql-test/t/insert.test: Added end marker for test to make future merges easier mysql-test/t/insert_select-binlog.test: Added end marker for test to make future merges easier mysql-test/t/insert_select.test: Added end marker for test to make future merges easier mysql-test/t/insert_update.test: Added end marker for test to make future merges easier mysql-test/t/isam.test: Added end marker for test to make future merges easier mysql-test/t/join.test: Added end marker for test to make future merges easier mysql-test/t/join_crash.test: Added end marker for test to make future merges easier mysql-test/t/join_outer.test: Added end marker for test to make future merges easier mysql-test/t/key.test: Added end marker for test to make future merges easier mysql-test/t/key_cache.test: Added end marker for test to make future merges easier mysql-test/t/key_diff.test: Added end marker for test to make future merges easier mysql-test/t/key_primary.test: Added end marker for test to make future merges easier mysql-test/t/keywords.test: Added end marker for test to make future merges easier mysql-test/t/kill.test: Added end marker for test to make future merges easier mysql-test/t/limit.test: Added end marker for test to make future merges easier mysql-test/t/loaddata.test: Added end marker for test to make future merges easier mysql-test/t/lock.test: Added end marker for test to make future merges easier mysql-test/t/lock_multi.test: Added end marker for test to make future merges easier mysql-test/t/lock_tables_lost_commit.test: Added end marker for test to make future merges easier mysql-test/t/lowercase_table.test: Added end marker for test to make future merges easier mysql-test/t/lowercase_table2.test: Added end marker for test to make future merges easier mysql-test/t/lowercase_table3.test: Added end marker for test to make future merges easier mysql-test/t/lowercase_table_grant.test: Added end marker for test to make future merges easier mysql-test/t/lowercase_table_qcache.test: Added end marker for test to make future merges easier mysql-test/t/merge.test: Added end marker for test to make future merges easier mysql-test/t/metadata.test: Added end marker for test to make future merges easier mysql-test/t/mix_innodb_myisam_binlog.test: Added end marker for test to make future merges easier mysql-test/t/multi_statement.test: Added end marker for test to make future merges easier mysql-test/t/multi_update.test: Added end marker for test to make future merges easier mysql-test/t/myisam-blob.test: Added end marker for test to make future merges easier mysql-test/t/myisam.test: Added end marker for test to make future merges easier mysql-test/t/mysql_client_test.test: Added end marker for test to make future merges easier mysql-test/t/mysql_protocols.test: Added end marker for test to make future merges easier mysql-test/t/mysqlbinlog.test: Added end marker for test to make future merges easier mysql-test/t/mysqlbinlog2.test: Added end marker for test to make future merges easier mysql-test/t/mysqldump.test: Added end marker for test to make future merges easier mysql-test/t/mysqltest.test: Added end marker for test to make future merges easier mysql-test/t/ndb_alter_table.test: Added end marker for test to make future merges easier mysql-test/t/ndb_autodiscover.test: Added end marker for test to make future merges easier mysql-test/t/ndb_autodiscover2.test: Added end marker for test to make future merges easier mysql-test/t/ndb_basic.test: Added end marker for test to make future merges easier mysql-test/t/ndb_blob.test: Added end marker for test to make future merges easier mysql-test/t/ndb_cache.test: Added end marker for test to make future merges easier mysql-test/t/ndb_charset.test: Added end marker for test to make future merges easier mysql-test/t/ndb_config.test: Added end marker for test to make future merges easier mysql-test/t/ndb_database.test: Added end marker for test to make future merges easier mysql-test/t/ndb_grant.later: Added end marker for test to make future merges easier mysql-test/t/ndb_index.test: Added end marker for test to make future merges easier mysql-test/t/ndb_index_ordered.test: Added end marker for test to make future merges easier mysql-test/t/ndb_index_unique.test: Added end marker for test to make future merges easier mysql-test/t/ndb_insert.test: Added end marker for test to make future merges easier mysql-test/t/ndb_limit.test: Added end marker for test to make future merges easier mysql-test/t/ndb_lock.test: Added end marker for test to make future merges easier mysql-test/t/ndb_minmax.test: Added end marker for test to make future merges easier mysql-test/t/ndb_multi.test: Added end marker for test to make future merges easier mysql-test/t/ndb_replace.test: Added end marker for test to make future merges easier mysql-test/t/ndb_restore.test: Added end marker for test to make future merges easier mysql-test/t/ndb_subquery.test: Added end marker for test to make future merges easier mysql-test/t/ndb_transaction.test: Added end marker for test to make future merges easier mysql-test/t/ndb_truncate.test: Added end marker for test to make future merges easier mysql-test/t/ndb_types.test: Added end marker for test to make future merges easier mysql-test/t/ndb_update.test: Added end marker for test to make future merges easier mysql-test/t/negation_elimination.test: Added end marker for test to make future merges easier mysql-test/t/not_embedded_server.test: Added end marker for test to make future merges easier mysql-test/t/null.test: Added end marker for test to make future merges easier mysql-test/t/null_key.test: Added end marker for test to make future merges easier mysql-test/t/odbc.test: Added end marker for test to make future merges easier mysql-test/t/olap.test: Added end marker for test to make future merges easier mysql-test/t/openssl_1.test: Added end marker for test to make future merges easier mysql-test/t/order_by.test: Added end marker for test to make future merges easier mysql-test/t/order_fill_sortbuf.test: Added end marker for test to make future merges easier mysql-test/t/outfile.test: Added end marker for test to make future merges easier mysql-test/t/overflow.test: Added end marker for test to make future merges easier mysql-test/t/packet.test: Added end marker for test to make future merges easier mysql-test/t/preload.test: Added end marker for test to make future merges easier mysql-test/t/ps.test: Added end marker for test to make future merges easier mysql-test/t/ps_10nestset.test: Added end marker for test to make future merges easier mysql-test/t/ps_11bugs.test: Added end marker for test to make future merges easier mysql-test/t/ps_1general.test: Added end marker for test to make future merges easier mysql-test/t/ps_2myisam.test: Added end marker for test to make future merges easier mysql-test/t/ps_3innodb.test: Added end marker for test to make future merges easier mysql-test/t/ps_4heap.test: Added end marker for test to make future merges easier mysql-test/t/ps_5merge.test: Added end marker for test to make future merges easier mysql-test/t/ps_6bdb.test: Added end marker for test to make future merges easier mysql-test/t/ps_7ndb.test: Added end marker for test to make future merges easier mysql-test/t/ps_grant.test: Added end marker for test to make future merges easier mysql-test/t/query_cache.test: Added end marker for test to make future merges easier mysql-test/t/query_cache_merge.test: Added end marker for test to make future merges easier mysql-test/t/raid.test: Added end marker for test to make future merges easier mysql-test/t/range.test: Added end marker for test to make future merges easier mysql-test/t/rename.test: Added end marker for test to make future merges easier mysql-test/t/repair.test: Added end marker for test to make future merges easier mysql-test/t/replace.test: Added end marker for test to make future merges easier mysql-test/t/rollback.test: Added end marker for test to make future merges easier mysql-test/t/row.test: Added end marker for test to make future merges easier mysql-test/t/rpl000001.test: Added end marker for test to make future merges easier mysql-test/t/rpl000002.test: Added end marker for test to make future merges easier mysql-test/t/rpl000004.test: Added end marker for test to make future merges easier mysql-test/t/rpl000005.test: Added end marker for test to make future merges easier mysql-test/t/rpl000006.test: Added end marker for test to make future merges easier mysql-test/t/rpl000008.test: Added end marker for test to make future merges easier mysql-test/t/rpl000009.test: Added end marker for test to make future merges easier mysql-test/t/rpl000010.test: Added end marker for test to make future merges easier mysql-test/t/rpl000011.test: Added end marker for test to make future merges easier mysql-test/t/rpl000012.test: Added end marker for test to make future merges easier mysql-test/t/rpl000013.test: Added end marker for test to make future merges easier mysql-test/t/rpl000015.test: Added end marker for test to make future merges easier mysql-test/t/rpl000017.test: Added end marker for test to make future merges easier mysql-test/t/rpl000018.test: Added end marker for test to make future merges easier mysql-test/t/rpl_EE_error.test: Added end marker for test to make future merges easier mysql-test/t/rpl_alter.test: Added end marker for test to make future merges easier mysql-test/t/rpl_chain_temp_table.test: Added end marker for test to make future merges easier mysql-test/t/rpl_change_master.test: Added end marker for test to make future merges easier mysql-test/t/rpl_charset.test: Added end marker for test to make future merges easier mysql-test/t/rpl_commit_after_flush.test: Added end marker for test to make future merges easier mysql-test/t/rpl_create_database.test: Added end marker for test to make future merges easier mysql-test/t/rpl_ddl.test: Added end marker for test to make future merges easier mysql-test/t/rpl_deadlock.test: Added end marker for test to make future merges easier mysql-test/t/rpl_delete_all.test: Added end marker for test to make future merges easier mysql-test/t/rpl_do_grant.test: Added end marker for test to make future merges easier mysql-test/t/rpl_drop.test: Added end marker for test to make future merges easier mysql-test/t/rpl_drop_temp.test: Added end marker for test to make future merges easier mysql-test/t/rpl_empty_master_crash.test: Added end marker for test to make future merges easier mysql-test/t/rpl_error_ignored_table.test: Added end marker for test to make future merges easier mysql-test/t/rpl_failed_optimize.test: Added end marker for test to make future merges easier mysql-test/t/rpl_failsafe.test: Added end marker for test to make future merges easier mysql-test/t/rpl_flush_log_loop.test: Added end marker for test to make future merges easier mysql-test/t/rpl_flush_tables.test: Added end marker for test to make future merges easier mysql-test/t/rpl_free_items.test: Added end marker for test to make future merges easier mysql-test/t/rpl_get_lock.test: Added end marker for test to make future merges easier mysql-test/t/rpl_heap.test: Added end marker for test to make future merges easier mysql-test/t/rpl_ignore_grant.test: Added end marker for test to make future merges easier mysql-test/t/rpl_init_slave.test: Added end marker for test to make future merges easier mysql-test/t/rpl_innodb.test: Added end marker for test to make future merges easier mysql-test/t/rpl_insert_id.test: Added end marker for test to make future merges easier mysql-test/t/rpl_insert_ignore.test: Added end marker for test to make future merges easier mysql-test/t/rpl_loaddata.test: Added end marker for test to make future merges easier mysql-test/t/rpl_loaddata_rule_m.test: Added end marker for test to make future merges easier mysql-test/t/rpl_loaddata_rule_s.test: Added end marker for test to make future merges easier mysql-test/t/rpl_loaddatalocal.test: Added end marker for test to make future merges easier mysql-test/t/rpl_log.test: Added end marker for test to make future merges easier mysql-test/t/rpl_log_pos.test: Added end marker for test to make future merges easier mysql-test/t/rpl_many_optimize.test: Added end marker for test to make future merges easier mysql-test/t/rpl_master_pos_wait.test: Added end marker for test to make future merges easier mysql-test/t/rpl_max_relay_size.test: Added end marker for test to make future merges easier mysql-test/t/rpl_misc_functions.test: Added end marker for test to make future merges easier mysql-test/t/rpl_multi_delete.test: Added end marker for test to make future merges easier mysql-test/t/rpl_multi_delete2.test: Added end marker for test to make future merges easier mysql-test/t/rpl_multi_query.test: Added end marker for test to make future merges easier mysql-test/t/rpl_multi_update.test: Added end marker for test to make future merges easier mysql-test/t/rpl_multi_update2.test: Added end marker for test to make future merges easier mysql-test/t/rpl_multi_update3.test: Added end marker for test to make future merges easier mysql-test/t/rpl_mystery22.test: Added end marker for test to make future merges easier mysql-test/t/rpl_openssl.test: Added end marker for test to make future merges easier mysql-test/t/rpl_optimize.test: Added end marker for test to make future merges easier mysql-test/t/rpl_ps.test: Added end marker for test to make future merges easier mysql-test/t/rpl_redirect.test: Added end marker for test to make future merges easier mysql-test/t/rpl_relayrotate.test: Added end marker for test to make future merges easier mysql-test/t/rpl_relayspace.test: Added end marker for test to make future merges easier mysql-test/t/rpl_replicate_do.test: Added end marker for test to make future merges easier mysql-test/t/rpl_reset_slave.test: Added end marker for test to make future merges easier mysql-test/t/rpl_rewrite_db.test: Added end marker for test to make future merges easier mysql-test/t/rpl_rotate_logs.test: Added end marker for test to make future merges easier mysql-test/t/rpl_server_id1.test: Added end marker for test to make future merges easier mysql-test/t/rpl_server_id2.test: Added end marker for test to make future merges easier mysql-test/t/rpl_set_charset.test: Added end marker for test to make future merges easier mysql-test/t/rpl_skip_error.test: Added end marker for test to make future merges easier mysql-test/t/rpl_sporadic_master.test: Added end marker for test to make future merges easier mysql-test/t/rpl_start_stop_slave.test: Added end marker for test to make future merges easier mysql-test/t/rpl_temporary.test: Added end marker for test to make future merges easier mysql-test/t/rpl_timezone.test: Added end marker for test to make future merges easier mysql-test/t/rpl_trunc_binlog.test: Added end marker for test to make future merges easier mysql-test/t/rpl_until.test: Added end marker for test to make future merges easier mysql-test/t/rpl_user_variables.test: Added end marker for test to make future merges easier mysql-test/t/rpl_variables.test: Added end marker for test to make future merges easier mysql-test/t/select.test: Added end marker for test to make future merges easier mysql-test/t/select_found.test: Added end marker for test to make future merges easier mysql-test/t/select_safe.test: Added end marker for test to make future merges easier mysql-test/t/show_check.test: Added end marker for test to make future merges easier mysql-test/t/skip_name_resolve.test: Added end marker for test to make future merges easier mysql-test/t/sql_mode.test: Added end marker for test to make future merges easier mysql-test/t/status.test: Added end marker for test to make future merges easier mysql-test/t/subselect.test: Added end marker for test to make future merges easier mysql-test/t/subselect2.test: Added end marker for test to make future merges easier mysql-test/t/subselect_gis.test: Added end marker for test to make future merges easier mysql-test/t/subselect_innodb.test: Added end marker for test to make future merges easier mysql-test/t/symlink.test: Added end marker for test to make future merges easier mysql-test/t/synchronization.test: Added end marker for test to make future merges easier mysql-test/t/system_mysql_db.test: Added end marker for test to make future merges easier mysql-test/t/system_mysql_db_fix.test: Added end marker for test to make future merges easier mysql-test/t/system_mysql_db_refs.test: Added end marker for test to make future merges easier mysql-test/t/tablelock.test: Added end marker for test to make future merges easier mysql-test/t/temp_table.test: Added end marker for test to make future merges easier mysql-test/t/timezone.test: Added end marker for test to make future merges easier mysql-test/t/timezone2.test: Added end marker for test to make future merges easier mysql-test/t/timezone3.test: Added end marker for test to make future merges easier mysql-test/t/timezone_grant.test: Added end marker for test to make future merges easier mysql-test/t/truncate.test: Added end marker for test to make future merges easier mysql-test/t/type_blob.test: Added end marker for test to make future merges easier mysql-test/t/type_date.test: Added end marker for test to make future merges easier mysql-test/t/type_datetime.test: Added end marker for test to make future merges easier mysql-test/t/type_decimal.test: Added end marker for test to make future merges easier mysql-test/t/type_enum.test: Added end marker for test to make future merges easier mysql-test/t/type_float.test: Added end marker for test to make future merges easier mysql-test/t/type_nchar.test: Added end marker for test to make future merges easier mysql-test/t/type_ranges.test: Added end marker for test to make future merges easier mysql-test/t/type_set.test: Added end marker for test to make future merges easier mysql-test/t/type_time.test: Added end marker for test to make future merges easier mysql-test/t/type_timestamp.test: Added end marker for test to make future merges easier mysql-test/t/type_uint.test: Added end marker for test to make future merges easier mysql-test/t/type_year.test: Added end marker for test to make future merges easier mysql-test/t/union.test: Added end marker for test to make future merges easier mysql-test/t/update.test: Added end marker for test to make future merges easier mysql-test/t/user_var-binlog.test: Added end marker for test to make future merges easier mysql-test/t/user_var.test: Added end marker for test to make future merges easier mysql-test/t/varbinary.test: Added end marker for test to make future merges easier mysql-test/t/variables.test: Added end marker for test to make future merges easier mysql-test/t/warnings.test: Added end marker for test to make future merges easier
2005-07-28 03:22:47 +03:00
Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Version for 5.0. It fixes three problems: 1. The cause of the bug was that we did not check the table version for the HANDLER ... READ commands. We did not notice when a table was replaced by a new one. This can happen during ALTER TABLE, REPAIR TABLE, and OPTIMIZE TABLE (there might be more cases). I call the fix for this problem "the primary bug fix". 2. mysql_ha_flush() was not always called with a locked LOCK_open. Though the function comment clearly said it must. I changed the code so that the locking is done when required. I call the fix for this problem "the secondary fix". 3. In 5.0 (not in 4.1 or 4.0) DROP TABLE had a possible deadlock flaw in concur with FLUSH TABLES WITH READ LOCK. I call the fix for this problem "the 5.0 addendum fix". include/my_pthread.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Added a new macro for the 5.0 addendum fix. mysql-test/r/handler.result: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test result. mysql-test/t/handler.test: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test case. sql/lock.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a comment which did confuse me and which is not fully correct anymore after the 5.0 addendum fix. Added an assertion which would fire without the 5.0 addendum fix. sql/mysql_priv.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a definition for the secondary fix. sql/sql_base.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed function calls for the secondary fix. sql/sql_class.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a function call for the secondary fix. sql/sql_handler.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first two diffs make the primary bug fix. The rest is for the secondary fix. sql/sql_table.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first diff (four changed places) make the 5.0 addendum fix. The other three are changed function calls for the secondary fix.
2005-11-15 21:57:02 +01:00
#
# Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
#
create table t1 (c1 int);
insert into t1 values (1);
# client 1
handler t1 open;
handler t1 read first;
# client 2
connect (con2,localhost,root,,);
connection con2;
--echo send the below to another connection, do not wait for the result
Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Version for 5.0. It fixes three problems: 1. The cause of the bug was that we did not check the table version for the HANDLER ... READ commands. We did not notice when a table was replaced by a new one. This can happen during ALTER TABLE, REPAIR TABLE, and OPTIMIZE TABLE (there might be more cases). I call the fix for this problem "the primary bug fix". 2. mysql_ha_flush() was not always called with a locked LOCK_open. Though the function comment clearly said it must. I changed the code so that the locking is done when required. I call the fix for this problem "the secondary fix". 3. In 5.0 (not in 4.1 or 4.0) DROP TABLE had a possible deadlock flaw in concur with FLUSH TABLES WITH READ LOCK. I call the fix for this problem "the 5.0 addendum fix". include/my_pthread.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Added a new macro for the 5.0 addendum fix. mysql-test/r/handler.result: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test result. mysql-test/t/handler.test: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test case. sql/lock.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a comment which did confuse me and which is not fully correct anymore after the 5.0 addendum fix. Added an assertion which would fire without the 5.0 addendum fix. sql/mysql_priv.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a definition for the secondary fix. sql/sql_base.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed function calls for the secondary fix. sql/sql_class.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a function call for the secondary fix. sql/sql_handler.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first two diffs make the primary bug fix. The rest is for the secondary fix. sql/sql_table.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first diff (four changed places) make the 5.0 addendum fix. The other three are changed function calls for the secondary fix.
2005-11-15 21:57:02 +01:00
send optimize table t1;
--sleep 1
# client 1
--echo proceed with the normal connection
Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Version for 5.0. It fixes three problems: 1. The cause of the bug was that we did not check the table version for the HANDLER ... READ commands. We did not notice when a table was replaced by a new one. This can happen during ALTER TABLE, REPAIR TABLE, and OPTIMIZE TABLE (there might be more cases). I call the fix for this problem "the primary bug fix". 2. mysql_ha_flush() was not always called with a locked LOCK_open. Though the function comment clearly said it must. I changed the code so that the locking is done when required. I call the fix for this problem "the secondary fix". 3. In 5.0 (not in 4.1 or 4.0) DROP TABLE had a possible deadlock flaw in concur with FLUSH TABLES WITH READ LOCK. I call the fix for this problem "the 5.0 addendum fix". include/my_pthread.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Added a new macro for the 5.0 addendum fix. mysql-test/r/handler.result: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test result. mysql-test/t/handler.test: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test case. sql/lock.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a comment which did confuse me and which is not fully correct anymore after the 5.0 addendum fix. Added an assertion which would fire without the 5.0 addendum fix. sql/mysql_priv.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a definition for the secondary fix. sql/sql_base.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed function calls for the secondary fix. sql/sql_class.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a function call for the secondary fix. sql/sql_handler.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first two diffs make the primary bug fix. The rest is for the secondary fix. sql/sql_table.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first diff (four changed places) make the 5.0 addendum fix. The other three are changed function calls for the secondary fix.
2005-11-15 21:57:02 +01:00
connection default;
handler t1 read next;
handler t1 close;
# client 2
--echo read the result from the other connection
Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Version for 5.0. It fixes three problems: 1. The cause of the bug was that we did not check the table version for the HANDLER ... READ commands. We did not notice when a table was replaced by a new one. This can happen during ALTER TABLE, REPAIR TABLE, and OPTIMIZE TABLE (there might be more cases). I call the fix for this problem "the primary bug fix". 2. mysql_ha_flush() was not always called with a locked LOCK_open. Though the function comment clearly said it must. I changed the code so that the locking is done when required. I call the fix for this problem "the secondary fix". 3. In 5.0 (not in 4.1 or 4.0) DROP TABLE had a possible deadlock flaw in concur with FLUSH TABLES WITH READ LOCK. I call the fix for this problem "the 5.0 addendum fix". include/my_pthread.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Added a new macro for the 5.0 addendum fix. mysql-test/r/handler.result: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test result. mysql-test/t/handler.test: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test case. sql/lock.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a comment which did confuse me and which is not fully correct anymore after the 5.0 addendum fix. Added an assertion which would fire without the 5.0 addendum fix. sql/mysql_priv.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a definition for the secondary fix. sql/sql_base.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed function calls for the secondary fix. sql/sql_class.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a function call for the secondary fix. sql/sql_handler.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first two diffs make the primary bug fix. The rest is for the secondary fix. sql/sql_table.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first diff (four changed places) make the 5.0 addendum fix. The other three are changed function calls for the secondary fix.
2005-11-15 21:57:02 +01:00
connection con2;
reap;
# client 1
--echo proceed with the normal connection
Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Version for 5.0. It fixes three problems: 1. The cause of the bug was that we did not check the table version for the HANDLER ... READ commands. We did not notice when a table was replaced by a new one. This can happen during ALTER TABLE, REPAIR TABLE, and OPTIMIZE TABLE (there might be more cases). I call the fix for this problem "the primary bug fix". 2. mysql_ha_flush() was not always called with a locked LOCK_open. Though the function comment clearly said it must. I changed the code so that the locking is done when required. I call the fix for this problem "the secondary fix". 3. In 5.0 (not in 4.1 or 4.0) DROP TABLE had a possible deadlock flaw in concur with FLUSH TABLES WITH READ LOCK. I call the fix for this problem "the 5.0 addendum fix". include/my_pthread.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Added a new macro for the 5.0 addendum fix. mysql-test/r/handler.result: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test result. mysql-test/t/handler.test: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test case. sql/lock.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a comment which did confuse me and which is not fully correct anymore after the 5.0 addendum fix. Added an assertion which would fire without the 5.0 addendum fix. sql/mysql_priv.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a definition for the secondary fix. sql/sql_base.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed function calls for the secondary fix. sql/sql_class.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a function call for the secondary fix. sql/sql_handler.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first two diffs make the primary bug fix. The rest is for the secondary fix. sql/sql_table.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first diff (four changed places) make the 5.0 addendum fix. The other three are changed function calls for the secondary fix.
2005-11-15 21:57:02 +01:00
connection default;
drop table t1;
CREATE TABLE t1 ( no1 smallint(5) NOT NULL default '0', no2 int(10) NOT NULL default '0', PRIMARY KEY using btree (no1,no2));
This changeset belongs to WL#3397 Refactoring storage engine test cases (for falcon) It contains also fixes according to code review. Contents: Testcases which were in history dedicated to InnoDB or MyISAM only. Modifications: 1. Shift the main testing code into include/<testing field>.inc Introduce $variables which can be used to omit tests for features which are not supported by certain storage engines. 2. The storage engine to be tested is assigned within the toplevel script (t/<whatever>_<engine>.test) via variable $engine_type and the the main testing code is sourced from include/<testing field>.inc 3. Some toplevel testscripts have to be renamed to - avoid immediate or future namespace clashes - show via filename which storage engine is tested 4. Minor code cleanup like remove trailing spaces, some additional comments .... mysql-test/t/unsafe_binlog_innodb-master.opt: Rename: mysql-test/t/innodb_unsafe_binlog-master.opt -> mysql-test/t/unsafe_binlog_innodb-master.opt mysql-test/r/read_many_rows_innodb.result: Rename: mysql-test/r/innodb-big.result -> mysql-test/r/read_many_rows_innodb.result mysql-test/t/cache_innodb-master.opt: Rename: mysql-test/t/innodb_cache-master.opt -> mysql-test/t/cache_innodb-master.opt mysql-test/t/concurrent_innodb-master.opt: Rename: mysql-test/t/innodb_concurrent-master.opt -> mysql-test/t/concurrent_innodb-master.opt BitKeeper/deleted/.del-index_merge.result: Delete: mysql-test/r/index_merge.result BitKeeper/deleted/.del-index_merge_innodb.result: Delete: mysql-test/r/index_merge_innodb.result BitKeeper/deleted/.del-index_merge_innodb2.result: Delete: mysql-test/r/index_merge_innodb2.result BitKeeper/deleted/.del-index_merge_ror.result: Delete: mysql-test/r/index_merge_ror.result BitKeeper/deleted/.del-index_merge_ror_cpk.result: Delete: mysql-test/r/index_merge_ror_cpk.result mysql-test/r/index_merge_innodb.result: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/r/index_merge_innodb.result mysql-test/t/index_merge_innodb.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_innodb.test mysql-test/t/index_merge_myisam.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_myisam.test mysql-test/include/concurrent.inc: 1. This file contains now the main testing code of the former t/innodb_concurrent.test. 2. It is now sourced by t/concurrent_innodb.test. mysql-test/include/deadlock.inc: 1. This file contains now the main testing code of the former t/innodb-deadlock.test 2. It is now sourced by t/deadlock_innodb.test. mysql-test/include/handler.inc: 1. This file contains now the main testing code of the former t/innodb_handler.test + t/handler.test. 2. It is now sourced by t/handler_myisam.test and t/handler_innodb.test. mysql-test/include/index_merge1.inc: 1. This file contains now the main testing code of the former t/index_merge.test. 2. It is now sourced by t/index_merge_myisam.test. mysql-test/include/index_merge2.inc: 1. This file contains now the main code of t/index_merge_innodb.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_2sweeps.inc: 1. This file contains now the main code of the former t/index_merge_innodb2.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_ror.inc: 1. This file contains now the main code of the former t/index_merge_ror.test. 2. It is sourced by t/index_merge_myisam.test. mysql-test/include/index_merge_ror_cpk.inc: 1. This file contains now the main testing code of the former t/index_merge_ror_cpk.test. 2. It is now sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/mix1.inc: 1. This file contains now the main testing code of the t/innodb_mysql.test 2. The name mix1.inc was used because the test contains subtests for different fields. 3. It is sourced by t/innodb_mysql.test. 4. Fixes: - Assign $other_engine_type instead of hardcoded MyISAM. - improve comment - remove redundant subtest - analyze table t4 instead of wrong table t1 - remove not needed "eval set storage_engine = $engine_type;" mysql-test/include/mix2.inc: 1. This file is a copy of the main testing code of the t/innodb.test A copy has to be used, because t/innodb.test is to be maintained by INNOBASE only. 2. The name mix2.inc was used because the test contains subtests for different fields. 3. It is sourced by t/mix2_myisam.test. 4. Fixes: - improved comment - additional "eval SET SESSION STORAGE_ENGINE = $other_engine_type;" at beginning of tests - assign $other_engine_type instead of hardcoded MyISAM or HEAP - assign $other_engine_type where it is needed to preserve test logics - correct logical bugs - improve(extend) "checksum table" test mysql-test/include/query_cache.inc: 1. This file contains now the main testing code of the former t/innodb_cache.test. 2. It is now sourced by t/cache_innodb.test mysql-test/include/read_many_rows.inc: 1. This file contains now the main testing code of the former t/innodb_big.test. 2. It is now sourced by t/read_many_rows_innodb.test. mysql-test/include/rowid_order.inc: 1. This file contains now the main testing code of t/rowid_order_innodb.test. 2. It is now sourced by t/rowid_order_innodb.test. mysql-test/include/unsafe_binlog.inc: 1. This file contains now the main testing code of the former t/innodb_unsafe_binlog.test. 2. It is now sourced by t/unsafe_binlog_innodb.test. mysql-test/r/cache_innodb.result: Updated result mysql-test/r/concurrent_innodb.result: Updated result mysql-test/r/deadlock_innodb.result: Updated result mysql-test/r/handler_innodb.result: Updated result mysql-test/r/handler_myisam.result: Updated result mysql-test/r/index_merge_myisam.result: Updated result mysql-test/r/innodb_mysql.result: Updated result mysql-test/r/mix2_myisam.result: Updated result mysql-test/r/rowid_order_innodb.result: Updated result mysql-test/r/unsafe_binlog_innodb.result: Updated result mysql-test/t/cache_innodb.test: 1. Renaming of t/innodb_cache.test to t/cache_innodb.test 2. Main code is now sourced from include/query_cache.inc. mysql-test/t/concurrent_innodb.test: 1. Renaming of t/innodb_concurrent.test to t/concurrent_innodb.test 2. Main code is now sourced from include/concurrent.inc. Attention: This test fails even in the old version. (BUG#21579). --> added to t/disabled.def mysql-test/t/deadlock_innodb.test: 1. Renaming of t/innodb_deadlock.test to t/deadlock_innodb.test 2. Main code is now sourced from include/deadlock.inc. mysql-test/t/disabled.def: Add the test concurrent_innodb because of BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences mysql-test/t/handler_innodb.test: 1. Renaming of t/innodb_handler.test to t/handler_innodb.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/innodb_handler.test mysql-test/t/handler_myisam.test: 1. Renaming of t/handler.test to t/handler_myisam.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/handler_innodb.test. mysql-test/t/innodb_mysql.test: 1. Main code is now sourced from include/mix1.inc. 2. Test was not renamed because t/innodb.test refers to it. mysql-test/t/mix2_myisam.test: New test: MyISAM variant of mix2 ( = t/innodb.test) mysql-test/t/read_many_rows_innodb.test: 1. Renaming of t/innodb_big.test to t/read_many_rows_innodb.test 2. Main code is now sourced from include/read_many_rows.inc. mysql-test/t/rowid_order_innodb.test: Main code is now sourced from t/rowid_order.inc. mysql-test/t/unsafe_binlog_innodb.test: 1. Renaming of t/innodb_unsafe_binlog.test to t/unsafe_binlog_innodb.test 2. Main code is now sourced from include/unsafe_binlog.inc.
2006-08-16 14:58:49 +02:00
INSERT INTO t1 VALUES (1,274),(1,275),(2,6),(2,8),(4,1),(4,2);
HANDLER t1 OPEN;
HANDLER t1 READ `primary` = (1, 1000);
HANDLER t1 READ `primary` PREV;
- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
HANDLER t1 READ `primary` = (1, 1000);
HANDLER t1 READ `primary` NEXT;
This changeset belongs to WL#3397 Refactoring storage engine test cases (for falcon) It contains also fixes according to code review. Contents: Testcases which were in history dedicated to InnoDB or MyISAM only. Modifications: 1. Shift the main testing code into include/<testing field>.inc Introduce $variables which can be used to omit tests for features which are not supported by certain storage engines. 2. The storage engine to be tested is assigned within the toplevel script (t/<whatever>_<engine>.test) via variable $engine_type and the the main testing code is sourced from include/<testing field>.inc 3. Some toplevel testscripts have to be renamed to - avoid immediate or future namespace clashes - show via filename which storage engine is tested 4. Minor code cleanup like remove trailing spaces, some additional comments .... mysql-test/t/unsafe_binlog_innodb-master.opt: Rename: mysql-test/t/innodb_unsafe_binlog-master.opt -> mysql-test/t/unsafe_binlog_innodb-master.opt mysql-test/r/read_many_rows_innodb.result: Rename: mysql-test/r/innodb-big.result -> mysql-test/r/read_many_rows_innodb.result mysql-test/t/cache_innodb-master.opt: Rename: mysql-test/t/innodb_cache-master.opt -> mysql-test/t/cache_innodb-master.opt mysql-test/t/concurrent_innodb-master.opt: Rename: mysql-test/t/innodb_concurrent-master.opt -> mysql-test/t/concurrent_innodb-master.opt BitKeeper/deleted/.del-index_merge.result: Delete: mysql-test/r/index_merge.result BitKeeper/deleted/.del-index_merge_innodb.result: Delete: mysql-test/r/index_merge_innodb.result BitKeeper/deleted/.del-index_merge_innodb2.result: Delete: mysql-test/r/index_merge_innodb2.result BitKeeper/deleted/.del-index_merge_ror.result: Delete: mysql-test/r/index_merge_ror.result BitKeeper/deleted/.del-index_merge_ror_cpk.result: Delete: mysql-test/r/index_merge_ror_cpk.result mysql-test/r/index_merge_innodb.result: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/r/index_merge_innodb.result mysql-test/t/index_merge_innodb.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_innodb.test mysql-test/t/index_merge_myisam.test: BitKeeper file /home/matthias/Arbeit/mysql-5.1-engines/src-1/mysql-test/t/index_merge_myisam.test mysql-test/include/concurrent.inc: 1. This file contains now the main testing code of the former t/innodb_concurrent.test. 2. It is now sourced by t/concurrent_innodb.test. mysql-test/include/deadlock.inc: 1. This file contains now the main testing code of the former t/innodb-deadlock.test 2. It is now sourced by t/deadlock_innodb.test. mysql-test/include/handler.inc: 1. This file contains now the main testing code of the former t/innodb_handler.test + t/handler.test. 2. It is now sourced by t/handler_myisam.test and t/handler_innodb.test. mysql-test/include/index_merge1.inc: 1. This file contains now the main testing code of the former t/index_merge.test. 2. It is now sourced by t/index_merge_myisam.test. mysql-test/include/index_merge2.inc: 1. This file contains now the main code of t/index_merge_innodb.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_2sweeps.inc: 1. This file contains now the main code of the former t/index_merge_innodb2.test. 2. It is sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/index_merge_ror.inc: 1. This file contains now the main code of the former t/index_merge_ror.test. 2. It is sourced by t/index_merge_myisam.test. mysql-test/include/index_merge_ror_cpk.inc: 1. This file contains now the main testing code of the former t/index_merge_ror_cpk.test. 2. It is now sourced by t/index_merge_myisam.test and t/index_merge_innodb.test. mysql-test/include/mix1.inc: 1. This file contains now the main testing code of the t/innodb_mysql.test 2. The name mix1.inc was used because the test contains subtests for different fields. 3. It is sourced by t/innodb_mysql.test. 4. Fixes: - Assign $other_engine_type instead of hardcoded MyISAM. - improve comment - remove redundant subtest - analyze table t4 instead of wrong table t1 - remove not needed "eval set storage_engine = $engine_type;" mysql-test/include/mix2.inc: 1. This file is a copy of the main testing code of the t/innodb.test A copy has to be used, because t/innodb.test is to be maintained by INNOBASE only. 2. The name mix2.inc was used because the test contains subtests for different fields. 3. It is sourced by t/mix2_myisam.test. 4. Fixes: - improved comment - additional "eval SET SESSION STORAGE_ENGINE = $other_engine_type;" at beginning of tests - assign $other_engine_type instead of hardcoded MyISAM or HEAP - assign $other_engine_type where it is needed to preserve test logics - correct logical bugs - improve(extend) "checksum table" test mysql-test/include/query_cache.inc: 1. This file contains now the main testing code of the former t/innodb_cache.test. 2. It is now sourced by t/cache_innodb.test mysql-test/include/read_many_rows.inc: 1. This file contains now the main testing code of the former t/innodb_big.test. 2. It is now sourced by t/read_many_rows_innodb.test. mysql-test/include/rowid_order.inc: 1. This file contains now the main testing code of t/rowid_order_innodb.test. 2. It is now sourced by t/rowid_order_innodb.test. mysql-test/include/unsafe_binlog.inc: 1. This file contains now the main testing code of the former t/innodb_unsafe_binlog.test. 2. It is now sourced by t/unsafe_binlog_innodb.test. mysql-test/r/cache_innodb.result: Updated result mysql-test/r/concurrent_innodb.result: Updated result mysql-test/r/deadlock_innodb.result: Updated result mysql-test/r/handler_innodb.result: Updated result mysql-test/r/handler_myisam.result: Updated result mysql-test/r/index_merge_myisam.result: Updated result mysql-test/r/innodb_mysql.result: Updated result mysql-test/r/mix2_myisam.result: Updated result mysql-test/r/rowid_order_innodb.result: Updated result mysql-test/r/unsafe_binlog_innodb.result: Updated result mysql-test/t/cache_innodb.test: 1. Renaming of t/innodb_cache.test to t/cache_innodb.test 2. Main code is now sourced from include/query_cache.inc. mysql-test/t/concurrent_innodb.test: 1. Renaming of t/innodb_concurrent.test to t/concurrent_innodb.test 2. Main code is now sourced from include/concurrent.inc. Attention: This test fails even in the old version. (BUG#21579). --> added to t/disabled.def mysql-test/t/deadlock_innodb.test: 1. Renaming of t/innodb_deadlock.test to t/deadlock_innodb.test 2. Main code is now sourced from include/deadlock.inc. mysql-test/t/disabled.def: Add the test concurrent_innodb because of BUG#21579 2006-08-11 mleich innodb_concurrent random failures with varying differences mysql-test/t/handler_innodb.test: 1. Renaming of t/innodb_handler.test to t/handler_innodb.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/innodb_handler.test mysql-test/t/handler_myisam.test: 1. Renaming of t/handler.test to t/handler_myisam.test 2. Main code is now sourced from include/handler.inc. include/handler.inc = united code of former t/handler.test and t/handler_innodb.test. mysql-test/t/innodb_mysql.test: 1. Main code is now sourced from include/mix1.inc. 2. Test was not renamed because t/innodb.test refers to it. mysql-test/t/mix2_myisam.test: New test: MyISAM variant of mix2 ( = t/innodb.test) mysql-test/t/read_many_rows_innodb.test: 1. Renaming of t/innodb_big.test to t/read_many_rows_innodb.test 2. Main code is now sourced from include/read_many_rows.inc. mysql-test/t/rowid_order_innodb.test: Main code is now sourced from t/rowid_order.inc. mysql-test/t/unsafe_binlog_innodb.test: 1. Renaming of t/innodb_unsafe_binlog.test to t/unsafe_binlog_innodb.test 2. Main code is now sourced from include/unsafe_binlog.inc.
2006-08-16 14:58:49 +02:00
DROP TABLE t1;
Added end marker for tests to make future merges easier mysql-test/t/alias.test: Added end marker for test to make future merges easier mysql-test/t/alter_table.test: Added end marker for test to make future merges easier mysql-test/t/analyse.test: Added end marker for test to make future merges easier mysql-test/t/analyze.test: Added end marker for test to make future merges easier Fixed length of comment lines mysql-test/t/ansi.test: Added end marker for test to make future merges easier mysql-test/t/archive.test: Added end marker for test to make future merges easier mysql-test/t/auto_increment.test: Added end marker for test to make future merges easier mysql-test/t/backup.test: Added end marker for test to make future merges easier mysql-test/t/bdb-alter-table-1.test: Added end marker for test to make future merges easier mysql-test/t/bdb-alter-table-2.test: Added end marker for test to make future merges easier mysql-test/t/bdb-crash.test: Added end marker for test to make future merges easier mysql-test/t/bdb-deadlock.test: Added end marker for test to make future merges easier mysql-test/t/bdb-deadlock.tminus: Added end marker for test to make future merges easier mysql-test/t/bdb.test: Added end marker for test to make future merges easier mysql-test/t/bdb_cache.test: Added end marker for test to make future merges easier mysql-test/t/bench_count_distinct.test: Added end marker for test to make future merges easier mysql-test/t/bigint.test: Added end marker for test to make future merges easier mysql-test/t/binary.test: Added end marker for test to make future merges easier mysql-test/t/blackhole.test: Added end marker for test to make future merges easier mysql-test/t/bool.test: Added end marker for test to make future merges easier mysql-test/t/bulk_replace.test: Added end marker for test to make future merges easier mysql-test/t/case.test: Added end marker for test to make future merges easier mysql-test/t/cast.test: Added end marker for test to make future merges easier mysql-test/t/check.test: Added end marker for test to make future merges easier mysql-test/t/comments.test: Added end marker for test to make future merges easier mysql-test/t/compare.test: Added end marker for test to make future merges easier mysql-test/t/connect.test: Added end marker for test to make future merges easier mysql-test/t/consistent_snapshot.test: Added end marker for test to make future merges easier mysql-test/t/constraints.test: Added end marker for test to make future merges easier mysql-test/t/count_distinct.test: Added end marker for test to make future merges easier mysql-test/t/count_distinct2.test: Added end marker for test to make future merges easier mysql-test/t/count_distinct3.test: Added end marker for test to make future merges easier mysql-test/t/create.test: Added end marker for test to make future merges easier mysql-test/t/create_select_tmp.test: Added end marker for test to make future merges easier mysql-test/t/csv.test: Added end marker for test to make future merges easier mysql-test/t/ctype_big5.test: Added end marker for test to make future merges easier mysql-test/t/ctype_collate.test: Added end marker for test to make future merges easier mysql-test/t/ctype_cp1250_ch.test: Added end marker for test to make future merges easier mysql-test/t/ctype_cp1251.test: Added end marker for test to make future merges easier mysql-test/t/ctype_cp932.test: Added end marker for test to make future merges easier mysql-test/t/ctype_create.test: Added end marker for test to make future merges easier mysql-test/t/ctype_gbk.test: Added end marker for test to make future merges easier mysql-test/t/ctype_latin1.test: Added end marker for test to make future merges easier mysql-test/t/ctype_latin1_de.test: Added end marker for test to make future merges easier mysql-test/t/ctype_latin2.test: Added end marker for test to make future merges easier mysql-test/t/ctype_many.test: Added end marker for test to make future merges easier mysql-test/t/ctype_mb.test: Added end marker for test to make future merges easier mysql-test/t/ctype_recoding.test: Added end marker for test to make future merges easier mysql-test/t/ctype_sjis.test: Added end marker for test to make future merges easier mysql-test/t/ctype_tis620.test: Added end marker for test to make future merges easier mysql-test/t/ctype_uca.test: Added end marker for test to make future merges easier mysql-test/t/ctype_ucs.test: Added end marker for test to make future merges easier mysql-test/t/ctype_ucs_binlog.test: Added end marker for test to make future merges easier mysql-test/t/ctype_ujis.test: Added end marker for test to make future merges easier mysql-test/t/ctype_utf8.test: Added end marker for test to make future merges easier mysql-test/t/date_formats.test: Added end marker for test to make future merges easier mysql-test/t/delayed.test: Added end marker for test to make future merges easier mysql-test/t/delete.test: Added end marker for test to make future merges easier mysql-test/t/derived.test: Added end marker for test to make future merges easier mysql-test/t/dirty_close.test: Added end marker for test to make future merges easier mysql-test/t/distinct.test: Added end marker for test to make future merges easier mysql-test/t/drop.test: Added end marker for test to make future merges easier mysql-test/t/drop_temp_table.test: Added end marker for test to make future merges easier mysql-test/t/empty_table.test: Added end marker for test to make future merges easier mysql-test/t/endspace.test: Added end marker for test to make future merges easier mysql-test/t/errors.test: Added end marker for test to make future merges easier mysql-test/t/exampledb.test: Added end marker for test to make future merges easier mysql-test/t/explain.test: Added end marker for test to make future merges easier mysql-test/t/flush.test: Added end marker for test to make future merges easier mysql-test/t/flush_block_commit.test: Added end marker for test to make future merges easier mysql-test/t/flush_table.test: Added end marker for test to make future merges easier mysql-test/t/foreign_key.test: Added end marker for test to make future merges easier mysql-test/t/fulltext.test: Added end marker for test to make future merges easier mysql-test/t/fulltext2.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_cache.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_distinct.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_left_join.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_multi.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_order_by.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_update.test: Added end marker for test to make future merges easier mysql-test/t/fulltext_var.test: Added end marker for test to make future merges easier mysql-test/t/func_compress.test: Added end marker for test to make future merges easier mysql-test/t/func_concat.test: Added end marker for test to make future merges easier mysql-test/t/func_crypt.test: Added end marker for test to make future merges easier mysql-test/t/func_date_add.test: Added end marker for test to make future merges easier mysql-test/t/func_default.test: Added end marker for test to make future merges easier mysql-test/t/func_des_encrypt.test: Added end marker for test to make future merges easier mysql-test/t/func_encrypt.test: Added end marker for test to make future merges easier mysql-test/t/func_encrypt_nossl.test: Added end marker for test to make future merges easier mysql-test/t/func_equal.test: Added end marker for test to make future merges easier mysql-test/t/func_gconcat.test: Added end marker for test to make future merges easier mysql-test/t/func_group.test: Added end marker for test to make future merges easier mysql-test/t/func_if.test: Added end marker for test to make future merges easier mysql-test/t/func_in.test: Added end marker for test to make future merges easier mysql-test/t/func_isnull.test: Added end marker for test to make future merges easier mysql-test/t/func_like.test: Added end marker for test to make future merges easier mysql-test/t/func_math.test: Added end marker for test to make future merges easier mysql-test/t/func_misc.test: Added end marker for test to make future merges easier mysql-test/t/func_op.test: Added end marker for test to make future merges easier mysql-test/t/func_regexp.test: Added end marker for test to make future merges easier mysql-test/t/func_sapdb.test: Added end marker for test to make future merges easier mysql-test/t/func_set.test: Added end marker for test to make future merges easier mysql-test/t/func_str.test: Added end marker for test to make future merges easier mysql-test/t/func_system.test: Added end marker for test to make future merges easier mysql-test/t/func_test.test: Added end marker for test to make future merges easier mysql-test/t/func_time.test: Added end marker for test to make future merges easier mysql-test/t/func_timestamp.test: Added end marker for test to make future merges easier mysql-test/t/gcc296.test: Added end marker for test to make future merges easier mysql-test/t/gis-rtree.test: Added end marker for test to make future merges easier mysql-test/t/gis.test: Added end marker for test to make future merges easier mysql-test/t/grant.test: Added end marker for test to make future merges easier mysql-test/t/grant2.test: Added end marker for test to make future merges easier mysql-test/t/grant_cache.test: Added end marker for test to make future merges easier mysql-test/t/group_by.test: Added end marker for test to make future merges easier mysql-test/t/handler.test: Added end marker for test to make future merges easier mysql-test/t/having.test: Added end marker for test to make future merges easier mysql-test/t/heap.test: Added end marker for test to make future merges easier mysql-test/t/heap_auto_increment.test: Added end marker for test to make future merges easier mysql-test/t/heap_btree.test: Added end marker for test to make future merges easier mysql-test/t/heap_hash.test: Added end marker for test to make future merges easier mysql-test/t/help.test: Added end marker for test to make future merges easier mysql-test/t/init_connect.test: Added end marker for test to make future merges easier mysql-test/t/init_file.test: Added end marker for test to make future merges easier mysql-test/t/innodb-deadlock.test: Added end marker for test to make future merges easier mysql-test/t/innodb-lock.test: Added end marker for test to make future merges easier mysql-test/t/innodb-replace.test: Added end marker for test to make future merges easier mysql-test/t/innodb.test: Added end marker for test to make future merges easier mysql-test/t/innodb_cache.test: Added end marker for test to make future merges easier mysql-test/t/innodb_handler.test: Added end marker for test to make future merges easier mysql-test/t/insert.test: Added end marker for test to make future merges easier mysql-test/t/insert_select-binlog.test: Added end marker for test to make future merges easier mysql-test/t/insert_select.test: Added end marker for test to make future merges easier mysql-test/t/insert_update.test: Added end marker for test to make future merges easier mysql-test/t/isam.test: Added end marker for test to make future merges easier mysql-test/t/join.test: Added end marker for test to make future merges easier mysql-test/t/join_crash.test: Added end marker for test to make future merges easier mysql-test/t/join_outer.test: Added end marker for test to make future merges easier mysql-test/t/key.test: Added end marker for test to make future merges easier mysql-test/t/key_cache.test: Added end marker for test to make future merges easier mysql-test/t/key_diff.test: Added end marker for test to make future merges easier mysql-test/t/key_primary.test: Added end marker for test to make future merges easier mysql-test/t/keywords.test: Added end marker for test to make future merges easier mysql-test/t/kill.test: Added end marker for test to make future merges easier mysql-test/t/limit.test: Added end marker for test to make future merges easier mysql-test/t/loaddata.test: Added end marker for test to make future merges easier mysql-test/t/lock.test: Added end marker for test to make future merges easier mysql-test/t/lock_multi.test: Added end marker for test to make future merges easier mysql-test/t/lock_tables_lost_commit.test: Added end marker for test to make future merges easier mysql-test/t/lowercase_table.test: Added end marker for test to make future merges easier mysql-test/t/lowercase_table2.test: Added end marker for test to make future merges easier mysql-test/t/lowercase_table3.test: Added end marker for test to make future merges easier mysql-test/t/lowercase_table_grant.test: Added end marker for test to make future merges easier mysql-test/t/lowercase_table_qcache.test: Added end marker for test to make future merges easier mysql-test/t/merge.test: Added end marker for test to make future merges easier mysql-test/t/metadata.test: Added end marker for test to make future merges easier mysql-test/t/mix_innodb_myisam_binlog.test: Added end marker for test to make future merges easier mysql-test/t/multi_statement.test: Added end marker for test to make future merges easier mysql-test/t/multi_update.test: Added end marker for test to make future merges easier mysql-test/t/myisam-blob.test: Added end marker for test to make future merges easier mysql-test/t/myisam.test: Added end marker for test to make future merges easier mysql-test/t/mysql_client_test.test: Added end marker for test to make future merges easier mysql-test/t/mysql_protocols.test: Added end marker for test to make future merges easier mysql-test/t/mysqlbinlog.test: Added end marker for test to make future merges easier mysql-test/t/mysqlbinlog2.test: Added end marker for test to make future merges easier mysql-test/t/mysqldump.test: Added end marker for test to make future merges easier mysql-test/t/mysqltest.test: Added end marker for test to make future merges easier mysql-test/t/ndb_alter_table.test: Added end marker for test to make future merges easier mysql-test/t/ndb_autodiscover.test: Added end marker for test to make future merges easier mysql-test/t/ndb_autodiscover2.test: Added end marker for test to make future merges easier mysql-test/t/ndb_basic.test: Added end marker for test to make future merges easier mysql-test/t/ndb_blob.test: Added end marker for test to make future merges easier mysql-test/t/ndb_cache.test: Added end marker for test to make future merges easier mysql-test/t/ndb_charset.test: Added end marker for test to make future merges easier mysql-test/t/ndb_config.test: Added end marker for test to make future merges easier mysql-test/t/ndb_database.test: Added end marker for test to make future merges easier mysql-test/t/ndb_grant.later: Added end marker for test to make future merges easier mysql-test/t/ndb_index.test: Added end marker for test to make future merges easier mysql-test/t/ndb_index_ordered.test: Added end marker for test to make future merges easier mysql-test/t/ndb_index_unique.test: Added end marker for test to make future merges easier mysql-test/t/ndb_insert.test: Added end marker for test to make future merges easier mysql-test/t/ndb_limit.test: Added end marker for test to make future merges easier mysql-test/t/ndb_lock.test: Added end marker for test to make future merges easier mysql-test/t/ndb_minmax.test: Added end marker for test to make future merges easier mysql-test/t/ndb_multi.test: Added end marker for test to make future merges easier mysql-test/t/ndb_replace.test: Added end marker for test to make future merges easier mysql-test/t/ndb_restore.test: Added end marker for test to make future merges easier mysql-test/t/ndb_subquery.test: Added end marker for test to make future merges easier mysql-test/t/ndb_transaction.test: Added end marker for test to make future merges easier mysql-test/t/ndb_truncate.test: Added end marker for test to make future merges easier mysql-test/t/ndb_types.test: Added end marker for test to make future merges easier mysql-test/t/ndb_update.test: Added end marker for test to make future merges easier mysql-test/t/negation_elimination.test: Added end marker for test to make future merges easier mysql-test/t/not_embedded_server.test: Added end marker for test to make future merges easier mysql-test/t/null.test: Added end marker for test to make future merges easier mysql-test/t/null_key.test: Added end marker for test to make future merges easier mysql-test/t/odbc.test: Added end marker for test to make future merges easier mysql-test/t/olap.test: Added end marker for test to make future merges easier mysql-test/t/openssl_1.test: Added end marker for test to make future merges easier mysql-test/t/order_by.test: Added end marker for test to make future merges easier mysql-test/t/order_fill_sortbuf.test: Added end marker for test to make future merges easier mysql-test/t/outfile.test: Added end marker for test to make future merges easier mysql-test/t/overflow.test: Added end marker for test to make future merges easier mysql-test/t/packet.test: Added end marker for test to make future merges easier mysql-test/t/preload.test: Added end marker for test to make future merges easier mysql-test/t/ps.test: Added end marker for test to make future merges easier mysql-test/t/ps_10nestset.test: Added end marker for test to make future merges easier mysql-test/t/ps_11bugs.test: Added end marker for test to make future merges easier mysql-test/t/ps_1general.test: Added end marker for test to make future merges easier mysql-test/t/ps_2myisam.test: Added end marker for test to make future merges easier mysql-test/t/ps_3innodb.test: Added end marker for test to make future merges easier mysql-test/t/ps_4heap.test: Added end marker for test to make future merges easier mysql-test/t/ps_5merge.test: Added end marker for test to make future merges easier mysql-test/t/ps_6bdb.test: Added end marker for test to make future merges easier mysql-test/t/ps_7ndb.test: Added end marker for test to make future merges easier mysql-test/t/ps_grant.test: Added end marker for test to make future merges easier mysql-test/t/query_cache.test: Added end marker for test to make future merges easier mysql-test/t/query_cache_merge.test: Added end marker for test to make future merges easier mysql-test/t/raid.test: Added end marker for test to make future merges easier mysql-test/t/range.test: Added end marker for test to make future merges easier mysql-test/t/rename.test: Added end marker for test to make future merges easier mysql-test/t/repair.test: Added end marker for test to make future merges easier mysql-test/t/replace.test: Added end marker for test to make future merges easier mysql-test/t/rollback.test: Added end marker for test to make future merges easier mysql-test/t/row.test: Added end marker for test to make future merges easier mysql-test/t/rpl000001.test: Added end marker for test to make future merges easier mysql-test/t/rpl000002.test: Added end marker for test to make future merges easier mysql-test/t/rpl000004.test: Added end marker for test to make future merges easier mysql-test/t/rpl000005.test: Added end marker for test to make future merges easier mysql-test/t/rpl000006.test: Added end marker for test to make future merges easier mysql-test/t/rpl000008.test: Added end marker for test to make future merges easier mysql-test/t/rpl000009.test: Added end marker for test to make future merges easier mysql-test/t/rpl000010.test: Added end marker for test to make future merges easier mysql-test/t/rpl000011.test: Added end marker for test to make future merges easier mysql-test/t/rpl000012.test: Added end marker for test to make future merges easier mysql-test/t/rpl000013.test: Added end marker for test to make future merges easier mysql-test/t/rpl000015.test: Added end marker for test to make future merges easier mysql-test/t/rpl000017.test: Added end marker for test to make future merges easier mysql-test/t/rpl000018.test: Added end marker for test to make future merges easier mysql-test/t/rpl_EE_error.test: Added end marker for test to make future merges easier mysql-test/t/rpl_alter.test: Added end marker for test to make future merges easier mysql-test/t/rpl_chain_temp_table.test: Added end marker for test to make future merges easier mysql-test/t/rpl_change_master.test: Added end marker for test to make future merges easier mysql-test/t/rpl_charset.test: Added end marker for test to make future merges easier mysql-test/t/rpl_commit_after_flush.test: Added end marker for test to make future merges easier mysql-test/t/rpl_create_database.test: Added end marker for test to make future merges easier mysql-test/t/rpl_ddl.test: Added end marker for test to make future merges easier mysql-test/t/rpl_deadlock.test: Added end marker for test to make future merges easier mysql-test/t/rpl_delete_all.test: Added end marker for test to make future merges easier mysql-test/t/rpl_do_grant.test: Added end marker for test to make future merges easier mysql-test/t/rpl_drop.test: Added end marker for test to make future merges easier mysql-test/t/rpl_drop_temp.test: Added end marker for test to make future merges easier mysql-test/t/rpl_empty_master_crash.test: Added end marker for test to make future merges easier mysql-test/t/rpl_error_ignored_table.test: Added end marker for test to make future merges easier mysql-test/t/rpl_failed_optimize.test: Added end marker for test to make future merges easier mysql-test/t/rpl_failsafe.test: Added end marker for test to make future merges easier mysql-test/t/rpl_flush_log_loop.test: Added end marker for test to make future merges easier mysql-test/t/rpl_flush_tables.test: Added end marker for test to make future merges easier mysql-test/t/rpl_free_items.test: Added end marker for test to make future merges easier mysql-test/t/rpl_get_lock.test: Added end marker for test to make future merges easier mysql-test/t/rpl_heap.test: Added end marker for test to make future merges easier mysql-test/t/rpl_ignore_grant.test: Added end marker for test to make future merges easier mysql-test/t/rpl_init_slave.test: Added end marker for test to make future merges easier mysql-test/t/rpl_innodb.test: Added end marker for test to make future merges easier mysql-test/t/rpl_insert_id.test: Added end marker for test to make future merges easier mysql-test/t/rpl_insert_ignore.test: Added end marker for test to make future merges easier mysql-test/t/rpl_loaddata.test: Added end marker for test to make future merges easier mysql-test/t/rpl_loaddata_rule_m.test: Added end marker for test to make future merges easier mysql-test/t/rpl_loaddata_rule_s.test: Added end marker for test to make future merges easier mysql-test/t/rpl_loaddatalocal.test: Added end marker for test to make future merges easier mysql-test/t/rpl_log.test: Added end marker for test to make future merges easier mysql-test/t/rpl_log_pos.test: Added end marker for test to make future merges easier mysql-test/t/rpl_many_optimize.test: Added end marker for test to make future merges easier mysql-test/t/rpl_master_pos_wait.test: Added end marker for test to make future merges easier mysql-test/t/rpl_max_relay_size.test: Added end marker for test to make future merges easier mysql-test/t/rpl_misc_functions.test: Added end marker for test to make future merges easier mysql-test/t/rpl_multi_delete.test: Added end marker for test to make future merges easier mysql-test/t/rpl_multi_delete2.test: Added end marker for test to make future merges easier mysql-test/t/rpl_multi_query.test: Added end marker for test to make future merges easier mysql-test/t/rpl_multi_update.test: Added end marker for test to make future merges easier mysql-test/t/rpl_multi_update2.test: Added end marker for test to make future merges easier mysql-test/t/rpl_multi_update3.test: Added end marker for test to make future merges easier mysql-test/t/rpl_mystery22.test: Added end marker for test to make future merges easier mysql-test/t/rpl_openssl.test: Added end marker for test to make future merges easier mysql-test/t/rpl_optimize.test: Added end marker for test to make future merges easier mysql-test/t/rpl_ps.test: Added end marker for test to make future merges easier mysql-test/t/rpl_redirect.test: Added end marker for test to make future merges easier mysql-test/t/rpl_relayrotate.test: Added end marker for test to make future merges easier mysql-test/t/rpl_relayspace.test: Added end marker for test to make future merges easier mysql-test/t/rpl_replicate_do.test: Added end marker for test to make future merges easier mysql-test/t/rpl_reset_slave.test: Added end marker for test to make future merges easier mysql-test/t/rpl_rewrite_db.test: Added end marker for test to make future merges easier mysql-test/t/rpl_rotate_logs.test: Added end marker for test to make future merges easier mysql-test/t/rpl_server_id1.test: Added end marker for test to make future merges easier mysql-test/t/rpl_server_id2.test: Added end marker for test to make future merges easier mysql-test/t/rpl_set_charset.test: Added end marker for test to make future merges easier mysql-test/t/rpl_skip_error.test: Added end marker for test to make future merges easier mysql-test/t/rpl_sporadic_master.test: Added end marker for test to make future merges easier mysql-test/t/rpl_start_stop_slave.test: Added end marker for test to make future merges easier mysql-test/t/rpl_temporary.test: Added end marker for test to make future merges easier mysql-test/t/rpl_timezone.test: Added end marker for test to make future merges easier mysql-test/t/rpl_trunc_binlog.test: Added end marker for test to make future merges easier mysql-test/t/rpl_until.test: Added end marker for test to make future merges easier mysql-test/t/rpl_user_variables.test: Added end marker for test to make future merges easier mysql-test/t/rpl_variables.test: Added end marker for test to make future merges easier mysql-test/t/select.test: Added end marker for test to make future merges easier mysql-test/t/select_found.test: Added end marker for test to make future merges easier mysql-test/t/select_safe.test: Added end marker for test to make future merges easier mysql-test/t/show_check.test: Added end marker for test to make future merges easier mysql-test/t/skip_name_resolve.test: Added end marker for test to make future merges easier mysql-test/t/sql_mode.test: Added end marker for test to make future merges easier mysql-test/t/status.test: Added end marker for test to make future merges easier mysql-test/t/subselect.test: Added end marker for test to make future merges easier mysql-test/t/subselect2.test: Added end marker for test to make future merges easier mysql-test/t/subselect_gis.test: Added end marker for test to make future merges easier mysql-test/t/subselect_innodb.test: Added end marker for test to make future merges easier mysql-test/t/symlink.test: Added end marker for test to make future merges easier mysql-test/t/synchronization.test: Added end marker for test to make future merges easier mysql-test/t/system_mysql_db.test: Added end marker for test to make future merges easier mysql-test/t/system_mysql_db_fix.test: Added end marker for test to make future merges easier mysql-test/t/system_mysql_db_refs.test: Added end marker for test to make future merges easier mysql-test/t/tablelock.test: Added end marker for test to make future merges easier mysql-test/t/temp_table.test: Added end marker for test to make future merges easier mysql-test/t/timezone.test: Added end marker for test to make future merges easier mysql-test/t/timezone2.test: Added end marker for test to make future merges easier mysql-test/t/timezone3.test: Added end marker for test to make future merges easier mysql-test/t/timezone_grant.test: Added end marker for test to make future merges easier mysql-test/t/truncate.test: Added end marker for test to make future merges easier mysql-test/t/type_blob.test: Added end marker for test to make future merges easier mysql-test/t/type_date.test: Added end marker for test to make future merges easier mysql-test/t/type_datetime.test: Added end marker for test to make future merges easier mysql-test/t/type_decimal.test: Added end marker for test to make future merges easier mysql-test/t/type_enum.test: Added end marker for test to make future merges easier mysql-test/t/type_float.test: Added end marker for test to make future merges easier mysql-test/t/type_nchar.test: Added end marker for test to make future merges easier mysql-test/t/type_ranges.test: Added end marker for test to make future merges easier mysql-test/t/type_set.test: Added end marker for test to make future merges easier mysql-test/t/type_time.test: Added end marker for test to make future merges easier mysql-test/t/type_timestamp.test: Added end marker for test to make future merges easier mysql-test/t/type_uint.test: Added end marker for test to make future merges easier mysql-test/t/type_year.test: Added end marker for test to make future merges easier mysql-test/t/union.test: Added end marker for test to make future merges easier mysql-test/t/update.test: Added end marker for test to make future merges easier mysql-test/t/user_var-binlog.test: Added end marker for test to make future merges easier mysql-test/t/user_var.test: Added end marker for test to make future merges easier mysql-test/t/varbinary.test: Added end marker for test to make future merges easier mysql-test/t/variables.test: Added end marker for test to make future merges easier mysql-test/t/warnings.test: Added end marker for test to make future merges easier
2005-07-28 03:22:47 +03:00
# End of 4.1 tests
Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Version for 5.0. It fixes three problems: 1. The cause of the bug was that we did not check the table version for the HANDLER ... READ commands. We did not notice when a table was replaced by a new one. This can happen during ALTER TABLE, REPAIR TABLE, and OPTIMIZE TABLE (there might be more cases). I call the fix for this problem "the primary bug fix". 2. mysql_ha_flush() was not always called with a locked LOCK_open. Though the function comment clearly said it must. I changed the code so that the locking is done when required. I call the fix for this problem "the secondary fix". 3. In 5.0 (not in 4.1 or 4.0) DROP TABLE had a possible deadlock flaw in concur with FLUSH TABLES WITH READ LOCK. I call the fix for this problem "the 5.0 addendum fix". include/my_pthread.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Added a new macro for the 5.0 addendum fix. mysql-test/r/handler.result: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test result. mysql-test/t/handler.test: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test case. sql/lock.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a comment which did confuse me and which is not fully correct anymore after the 5.0 addendum fix. Added an assertion which would fire without the 5.0 addendum fix. sql/mysql_priv.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a definition for the secondary fix. sql/sql_base.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed function calls for the secondary fix. sql/sql_class.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a function call for the secondary fix. sql/sql_handler.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first two diffs make the primary bug fix. The rest is for the secondary fix. sql/sql_table.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first diff (four changed places) make the 5.0 addendum fix. The other three are changed function calls for the secondary fix.
2005-11-15 21:57:02 +01:00
#
# Addendum to Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash
# Show that DROP TABLE can no longer deadlock against
# FLUSH TABLES WITH READ LOCK. This is a 5.0 issue.
#
create table t1 (c1 int);
insert into t1 values (14397);
flush tables with read lock;
# The thread with the global read lock cannot drop the table itself:
--error 1223
drop table t1;
#
# client 2
# We need a second connection to try the drop.
# The drop waits for the global read lock to go away.
# Without the addendum fix it locked LOCK_open before entering the wait loop.
connection con2;
--echo send the below to another connection, do not wait for the result
Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Version for 5.0. It fixes three problems: 1. The cause of the bug was that we did not check the table version for the HANDLER ... READ commands. We did not notice when a table was replaced by a new one. This can happen during ALTER TABLE, REPAIR TABLE, and OPTIMIZE TABLE (there might be more cases). I call the fix for this problem "the primary bug fix". 2. mysql_ha_flush() was not always called with a locked LOCK_open. Though the function comment clearly said it must. I changed the code so that the locking is done when required. I call the fix for this problem "the secondary fix". 3. In 5.0 (not in 4.1 or 4.0) DROP TABLE had a possible deadlock flaw in concur with FLUSH TABLES WITH READ LOCK. I call the fix for this problem "the 5.0 addendum fix". include/my_pthread.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Added a new macro for the 5.0 addendum fix. mysql-test/r/handler.result: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test result. mysql-test/t/handler.test: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test case. sql/lock.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a comment which did confuse me and which is not fully correct anymore after the 5.0 addendum fix. Added an assertion which would fire without the 5.0 addendum fix. sql/mysql_priv.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a definition for the secondary fix. sql/sql_base.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed function calls for the secondary fix. sql/sql_class.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a function call for the secondary fix. sql/sql_handler.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first two diffs make the primary bug fix. The rest is for the secondary fix. sql/sql_table.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first diff (four changed places) make the 5.0 addendum fix. The other three are changed function calls for the secondary fix.
2005-11-15 21:57:02 +01:00
send drop table t1;
--sleep 1
#
# client 1
# Now we need something that wants LOCK_open. A simple table access which
# opens the table does the trick.
--echo proceed with the normal connection
Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Version for 5.0. It fixes three problems: 1. The cause of the bug was that we did not check the table version for the HANDLER ... READ commands. We did not notice when a table was replaced by a new one. This can happen during ALTER TABLE, REPAIR TABLE, and OPTIMIZE TABLE (there might be more cases). I call the fix for this problem "the primary bug fix". 2. mysql_ha_flush() was not always called with a locked LOCK_open. Though the function comment clearly said it must. I changed the code so that the locking is done when required. I call the fix for this problem "the secondary fix". 3. In 5.0 (not in 4.1 or 4.0) DROP TABLE had a possible deadlock flaw in concur with FLUSH TABLES WITH READ LOCK. I call the fix for this problem "the 5.0 addendum fix". include/my_pthread.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Added a new macro for the 5.0 addendum fix. mysql-test/r/handler.result: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test result. mysql-test/t/handler.test: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test case. sql/lock.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a comment which did confuse me and which is not fully correct anymore after the 5.0 addendum fix. Added an assertion which would fire without the 5.0 addendum fix. sql/mysql_priv.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a definition for the secondary fix. sql/sql_base.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed function calls for the secondary fix. sql/sql_class.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a function call for the secondary fix. sql/sql_handler.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first two diffs make the primary bug fix. The rest is for the secondary fix. sql/sql_table.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first diff (four changed places) make the 5.0 addendum fix. The other three are changed function calls for the secondary fix.
2005-11-15 21:57:02 +01:00
connection default;
# This would hang on LOCK_open without the 5.0 addendum fix.
select * from t1;
# Release the read lock. This should make the DROP go through.
unlock tables;
#
# client 2
# Read the result of the drop command.
connection con2;
--echo read the result from the other connection
Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Version for 5.0. It fixes three problems: 1. The cause of the bug was that we did not check the table version for the HANDLER ... READ commands. We did not notice when a table was replaced by a new one. This can happen during ALTER TABLE, REPAIR TABLE, and OPTIMIZE TABLE (there might be more cases). I call the fix for this problem "the primary bug fix". 2. mysql_ha_flush() was not always called with a locked LOCK_open. Though the function comment clearly said it must. I changed the code so that the locking is done when required. I call the fix for this problem "the secondary fix". 3. In 5.0 (not in 4.1 or 4.0) DROP TABLE had a possible deadlock flaw in concur with FLUSH TABLES WITH READ LOCK. I call the fix for this problem "the 5.0 addendum fix". include/my_pthread.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Added a new macro for the 5.0 addendum fix. mysql-test/r/handler.result: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test result. mysql-test/t/handler.test: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test case. sql/lock.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a comment which did confuse me and which is not fully correct anymore after the 5.0 addendum fix. Added an assertion which would fire without the 5.0 addendum fix. sql/mysql_priv.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a definition for the secondary fix. sql/sql_base.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed function calls for the secondary fix. sql/sql_class.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a function call for the secondary fix. sql/sql_handler.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first two diffs make the primary bug fix. The rest is for the secondary fix. sql/sql_table.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first diff (four changed places) make the 5.0 addendum fix. The other three are changed function calls for the secondary fix.
2005-11-15 21:57:02 +01:00
reap;
#
# client 1
# Now back to normal operation. The table should not exist any more.
--echo proceed with the normal connection
Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Version for 5.0. It fixes three problems: 1. The cause of the bug was that we did not check the table version for the HANDLER ... READ commands. We did not notice when a table was replaced by a new one. This can happen during ALTER TABLE, REPAIR TABLE, and OPTIMIZE TABLE (there might be more cases). I call the fix for this problem "the primary bug fix". 2. mysql_ha_flush() was not always called with a locked LOCK_open. Though the function comment clearly said it must. I changed the code so that the locking is done when required. I call the fix for this problem "the secondary fix". 3. In 5.0 (not in 4.1 or 4.0) DROP TABLE had a possible deadlock flaw in concur with FLUSH TABLES WITH READ LOCK. I call the fix for this problem "the 5.0 addendum fix". include/my_pthread.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Added a new macro for the 5.0 addendum fix. mysql-test/r/handler.result: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test result. mysql-test/t/handler.test: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The test case. sql/lock.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a comment which did confuse me and which is not fully correct anymore after the 5.0 addendum fix. Added an assertion which would fire without the 5.0 addendum fix. sql/mysql_priv.h: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a definition for the secondary fix. sql/sql_base.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed function calls for the secondary fix. sql/sql_class.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash Changed a function call for the secondary fix. sql/sql_handler.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first two diffs make the primary bug fix. The rest is for the secondary fix. sql/sql_table.cc: Bug#14397 - OPTIMIZE TABLE with an open HANDLER causes a crash The first diff (four changed places) make the 5.0 addendum fix. The other three are changed function calls for the secondary fix.
2005-11-15 21:57:02 +01:00
connection default;
--error 1146
select * from t1;
# Just to be sure and not confuse the next test case writer.
drop table if exists t1;
#
# Bug#25856 - HANDLER table OPEN in one connection lock DROP TABLE in another one
#
create table t1 (a int not null) ENGINE=csv;
--echo --> client 2
connection con2;
--error 1031
handler t1 open;
--echo --> client 1
connection default;
drop table t1;
disconnect con2;
#
# Bug#30632 HANDLER read failure causes hang
#
create table t1 (a int);
handler t1 open as t1_alias;
--error 1176
handler t1_alias read a next;
--error 1054
handler t1_alias READ a next where inexistent > 0;
--error 1176
handler t1_alias read a next;
--error 1054
handler t1_alias READ a next where inexistent > 0;
handler t1_alias close;
drop table t1;
Bug#30882 Dropping a temporary table inside a stored function may cause a server crash If a stored function that contains a drop temporary table statement is invoked by a create temporary table of the same name may cause a server crash. The problem is that when dropping a table no check is done to ensure that table is not being used by some outer query (or outer statement), potentially leaving the outer query with a reference to a stale (freed) table. The solution is when dropping a temporary table, always check if the table is being used by some outer statement as a temporary table can be dropped inside stored procedures. The check is performed by looking at the TABLE::query_id value for temporary tables. To simplify this check and to solve a bug related to handling of temporary tables in prelocked mode, this patch changes the way in which this member is used to track the fact that table is used/unused. Now we ensure that TABLE::query_id is zero for unused temporary tables (which means that all temporary tables which were used by a statement should be marked as free for reuse after it's execution has been completed). mysql-test/include/handler.inc: Add test case for side effect of Bug#30882 mysql-test/r/handler_innodb.result: Add test case result for side effect of Bug#30882 mysql-test/r/handler_myisam.result: Add test case result for side effect of Bug#30882 mysql-test/r/sp-error.result: Add test case result for Bug#30882 mysql-test/t/sp-error.test: Add test case for Bug#30882 sql/event_db_repository.cc: Update close_thread_tables call, no more default values. sql/mysql_priv.h: Remove implicit default parameters values of the close_thread_tables function as no callers are using it. sql/slave.cc: Update close_thread_tables call, no more default values sql/sp_head.cc: Update close_thread_tables call, no more default values sql/sql_base.cc: Changed the approach to distinguishing currently unused temporary tables. Now we ensure that such tables always have TABLE::query_id set to 0 and use this fact to perform checks during opening and dropping of temporary tables. This means that we have to call close_thread_tables() even for statements which use only temporary tables. To make this call cheaper, we re-factored close_thread_tables() to not take LOCK_open unless there are open base tables. sql/sql_handler.cc: Properly close temporary tables associated with a handler. sql/sql_insert.cc: close_temporary_table is now merged into drop_temporary_table. sql/sql_parse.cc: Now the condition doesn't cover all cases because close_thread_tables() must be called even for statements that use only temporary tables. sql/sql_table.cc: Use drop_temporary_table which perform checks to verify if the table is not being used. Error path problem is due to a handler tables issue and is going to be addressed in bug 31397. sql/table.h: Rename previously unused clear_query_id and document the usage of query_id and open_by_handler.
2007-11-01 18:52:56 -02:00
#
# Bug#30882 Dropping a temporary table inside a stored function may cause a server crash
#
# Test HANDLER statements in conjunction with temporary tables. While the temporary table
# is open by a HANDLER, no other statement can access it.
#
create temporary table t1 (a int, b char(1), key a using btree (a), key b using btree (a,b));
Bug#30882 Dropping a temporary table inside a stored function may cause a server crash If a stored function that contains a drop temporary table statement is invoked by a create temporary table of the same name may cause a server crash. The problem is that when dropping a table no check is done to ensure that table is not being used by some outer query (or outer statement), potentially leaving the outer query with a reference to a stale (freed) table. The solution is when dropping a temporary table, always check if the table is being used by some outer statement as a temporary table can be dropped inside stored procedures. The check is performed by looking at the TABLE::query_id value for temporary tables. To simplify this check and to solve a bug related to handling of temporary tables in prelocked mode, this patch changes the way in which this member is used to track the fact that table is used/unused. Now we ensure that TABLE::query_id is zero for unused temporary tables (which means that all temporary tables which were used by a statement should be marked as free for reuse after it's execution has been completed). mysql-test/include/handler.inc: Add test case for side effect of Bug#30882 mysql-test/r/handler_innodb.result: Add test case result for side effect of Bug#30882 mysql-test/r/handler_myisam.result: Add test case result for side effect of Bug#30882 mysql-test/r/sp-error.result: Add test case result for Bug#30882 mysql-test/t/sp-error.test: Add test case for Bug#30882 sql/event_db_repository.cc: Update close_thread_tables call, no more default values. sql/mysql_priv.h: Remove implicit default parameters values of the close_thread_tables function as no callers are using it. sql/slave.cc: Update close_thread_tables call, no more default values sql/sp_head.cc: Update close_thread_tables call, no more default values sql/sql_base.cc: Changed the approach to distinguishing currently unused temporary tables. Now we ensure that such tables always have TABLE::query_id set to 0 and use this fact to perform checks during opening and dropping of temporary tables. This means that we have to call close_thread_tables() even for statements which use only temporary tables. To make this call cheaper, we re-factored close_thread_tables() to not take LOCK_open unless there are open base tables. sql/sql_handler.cc: Properly close temporary tables associated with a handler. sql/sql_insert.cc: close_temporary_table is now merged into drop_temporary_table. sql/sql_parse.cc: Now the condition doesn't cover all cases because close_thread_tables() must be called even for statements that use only temporary tables. sql/sql_table.cc: Use drop_temporary_table which perform checks to verify if the table is not being used. Error path problem is due to a handler tables issue and is going to be addressed in bug 31397. sql/table.h: Rename previously unused clear_query_id and document the usage of query_id and open_by_handler.
2007-11-01 18:52:56 -02:00
insert into t1 values (0,"a"),(1,"b"),(2,"c"),(3,"d"),(4,"e"),
- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
(5,"f"),(6,"g"),(7,"h"),(8,"i"),(9,"j"),(9,'k');
Bug#30882 Dropping a temporary table inside a stored function may cause a server crash If a stored function that contains a drop temporary table statement is invoked by a create temporary table of the same name may cause a server crash. The problem is that when dropping a table no check is done to ensure that table is not being used by some outer query (or outer statement), potentially leaving the outer query with a reference to a stale (freed) table. The solution is when dropping a temporary table, always check if the table is being used by some outer statement as a temporary table can be dropped inside stored procedures. The check is performed by looking at the TABLE::query_id value for temporary tables. To simplify this check and to solve a bug related to handling of temporary tables in prelocked mode, this patch changes the way in which this member is used to track the fact that table is used/unused. Now we ensure that TABLE::query_id is zero for unused temporary tables (which means that all temporary tables which were used by a statement should be marked as free for reuse after it's execution has been completed). mysql-test/include/handler.inc: Add test case for side effect of Bug#30882 mysql-test/r/handler_innodb.result: Add test case result for side effect of Bug#30882 mysql-test/r/handler_myisam.result: Add test case result for side effect of Bug#30882 mysql-test/r/sp-error.result: Add test case result for Bug#30882 mysql-test/t/sp-error.test: Add test case for Bug#30882 sql/event_db_repository.cc: Update close_thread_tables call, no more default values. sql/mysql_priv.h: Remove implicit default parameters values of the close_thread_tables function as no callers are using it. sql/slave.cc: Update close_thread_tables call, no more default values sql/sp_head.cc: Update close_thread_tables call, no more default values sql/sql_base.cc: Changed the approach to distinguishing currently unused temporary tables. Now we ensure that such tables always have TABLE::query_id set to 0 and use this fact to perform checks during opening and dropping of temporary tables. This means that we have to call close_thread_tables() even for statements which use only temporary tables. To make this call cheaper, we re-factored close_thread_tables() to not take LOCK_open unless there are open base tables. sql/sql_handler.cc: Properly close temporary tables associated with a handler. sql/sql_insert.cc: close_temporary_table is now merged into drop_temporary_table. sql/sql_parse.cc: Now the condition doesn't cover all cases because close_thread_tables() must be called even for statements that use only temporary tables. sql/sql_table.cc: Use drop_temporary_table which perform checks to verify if the table is not being used. Error path problem is due to a handler tables issue and is going to be addressed in bug 31397. sql/table.h: Rename previously unused clear_query_id and document the usage of query_id and open_by_handler.
2007-11-01 18:52:56 -02:00
select a,b from t1;
handler t1 open as a1;
- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
handler a1 read a=(1);
Bug#30882 Dropping a temporary table inside a stored function may cause a server crash If a stored function that contains a drop temporary table statement is invoked by a create temporary table of the same name may cause a server crash. The problem is that when dropping a table no check is done to ensure that table is not being used by some outer query (or outer statement), potentially leaving the outer query with a reference to a stale (freed) table. The solution is when dropping a temporary table, always check if the table is being used by some outer statement as a temporary table can be dropped inside stored procedures. The check is performed by looking at the TABLE::query_id value for temporary tables. To simplify this check and to solve a bug related to handling of temporary tables in prelocked mode, this patch changes the way in which this member is used to track the fact that table is used/unused. Now we ensure that TABLE::query_id is zero for unused temporary tables (which means that all temporary tables which were used by a statement should be marked as free for reuse after it's execution has been completed). mysql-test/include/handler.inc: Add test case for side effect of Bug#30882 mysql-test/r/handler_innodb.result: Add test case result for side effect of Bug#30882 mysql-test/r/handler_myisam.result: Add test case result for side effect of Bug#30882 mysql-test/r/sp-error.result: Add test case result for Bug#30882 mysql-test/t/sp-error.test: Add test case for Bug#30882 sql/event_db_repository.cc: Update close_thread_tables call, no more default values. sql/mysql_priv.h: Remove implicit default parameters values of the close_thread_tables function as no callers are using it. sql/slave.cc: Update close_thread_tables call, no more default values sql/sp_head.cc: Update close_thread_tables call, no more default values sql/sql_base.cc: Changed the approach to distinguishing currently unused temporary tables. Now we ensure that such tables always have TABLE::query_id set to 0 and use this fact to perform checks during opening and dropping of temporary tables. This means that we have to call close_thread_tables() even for statements which use only temporary tables. To make this call cheaper, we re-factored close_thread_tables() to not take LOCK_open unless there are open base tables. sql/sql_handler.cc: Properly close temporary tables associated with a handler. sql/sql_insert.cc: close_temporary_table is now merged into drop_temporary_table. sql/sql_parse.cc: Now the condition doesn't cover all cases because close_thread_tables() must be called even for statements that use only temporary tables. sql/sql_table.cc: Use drop_temporary_table which perform checks to verify if the table is not being used. Error path problem is due to a handler tables issue and is going to be addressed in bug 31397. sql/table.h: Rename previously unused clear_query_id and document the usage of query_id and open_by_handler.
2007-11-01 18:52:56 -02:00
handler a1 read a next;
handler a1 read a next;
--error ER_CANT_REOPEN_TABLE
select a,b from t1;
handler a1 read a prev;
handler a1 read a prev;
handler a1 read a=(6) where b="g";
handler a1 close;
select a,b from t1;
handler t1 open as a2;
Added HANDLER support for MEMORY tables Added key and file version numbers to MEMORY tables so that we can detect if someone has changed them between HANDLER calls. mysql-test/suite/handler/aria.result: Fixed result after test changes mysql-test/suite/handler/handler.inc: Changed test to use combined key to ensure rows are returned in a pre-determinated order. mysql-test/suite/handler/heap.result: New result mysql-test/suite/handler/heap.test: Added test for HANDLER + HEAP mysql-test/suite/handler/innodb.result: Fixed result after test changes mysql-test/suite/handler/myisam.result: Fixed result after test changes sql/sql_handler.cc: Fixed wrong parameter to ha_index_next_same() storage/heap/ha_heap.cc: Abort key scan if table has changed. Abort table scan if table has been recreated. storage/heap/ha_heap.h: Added support for HANDLER storage/heap/hp_clear.c: Increase version number so that we can notice changes if using HANDLER storage/heap/hp_delete.c: Increase key data version number on key changes. storage/heap/hp_rfirst.c: Remember version of key data Give error if using read-first on hash key. storage/heap/hp_rkey.c: Remember version of key data storage/heap/hp_rlast.c: Remember version of key data Give error if using read-last on hash key. storage/heap/hp_rnext.c: Fixed that we get next key from last search. storage/heap/hp_rprev.c: Fixed that we get previous key from last search. storage/heap/hp_scan.c: Remember version of key and file data storage/heap/hp_update.c: Increase key data version number on key changes. storage/heap/hp_write.c: Increase key data version number on key changes.
2011-01-11 18:51:59 +02:00
handler a2 read b=(9);
handler a2 read b next;
handler a2 read b prev limit 2;
- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
--error 0,1031
Added HANDLER support for MEMORY tables Added key and file version numbers to MEMORY tables so that we can detect if someone has changed them between HANDLER calls. mysql-test/suite/handler/aria.result: Fixed result after test changes mysql-test/suite/handler/handler.inc: Changed test to use combined key to ensure rows are returned in a pre-determinated order. mysql-test/suite/handler/heap.result: New result mysql-test/suite/handler/heap.test: Added test for HANDLER + HEAP mysql-test/suite/handler/innodb.result: Fixed result after test changes mysql-test/suite/handler/myisam.result: Fixed result after test changes sql/sql_handler.cc: Fixed wrong parameter to ha_index_next_same() storage/heap/ha_heap.cc: Abort key scan if table has changed. Abort table scan if table has been recreated. storage/heap/ha_heap.h: Added support for HANDLER storage/heap/hp_clear.c: Increase version number so that we can notice changes if using HANDLER storage/heap/hp_delete.c: Increase key data version number on key changes. storage/heap/hp_rfirst.c: Remember version of key data Give error if using read-first on hash key. storage/heap/hp_rkey.c: Remember version of key data storage/heap/hp_rlast.c: Remember version of key data Give error if using read-last on hash key. storage/heap/hp_rnext.c: Fixed that we get next key from last search. storage/heap/hp_rprev.c: Fixed that we get previous key from last search. storage/heap/hp_scan.c: Remember version of key and file data storage/heap/hp_update.c: Increase key data version number on key changes. storage/heap/hp_write.c: Increase key data version number on key changes.
2011-01-11 18:51:59 +02:00
handler a2 read b last;
handler a2 read b prev;
Bug#30882 Dropping a temporary table inside a stored function may cause a server crash If a stored function that contains a drop temporary table statement is invoked by a create temporary table of the same name may cause a server crash. The problem is that when dropping a table no check is done to ensure that table is not being used by some outer query (or outer statement), potentially leaving the outer query with a reference to a stale (freed) table. The solution is when dropping a temporary table, always check if the table is being used by some outer statement as a temporary table can be dropped inside stored procedures. The check is performed by looking at the TABLE::query_id value for temporary tables. To simplify this check and to solve a bug related to handling of temporary tables in prelocked mode, this patch changes the way in which this member is used to track the fact that table is used/unused. Now we ensure that TABLE::query_id is zero for unused temporary tables (which means that all temporary tables which were used by a statement should be marked as free for reuse after it's execution has been completed). mysql-test/include/handler.inc: Add test case for side effect of Bug#30882 mysql-test/r/handler_innodb.result: Add test case result for side effect of Bug#30882 mysql-test/r/handler_myisam.result: Add test case result for side effect of Bug#30882 mysql-test/r/sp-error.result: Add test case result for Bug#30882 mysql-test/t/sp-error.test: Add test case for Bug#30882 sql/event_db_repository.cc: Update close_thread_tables call, no more default values. sql/mysql_priv.h: Remove implicit default parameters values of the close_thread_tables function as no callers are using it. sql/slave.cc: Update close_thread_tables call, no more default values sql/sp_head.cc: Update close_thread_tables call, no more default values sql/sql_base.cc: Changed the approach to distinguishing currently unused temporary tables. Now we ensure that such tables always have TABLE::query_id set to 0 and use this fact to perform checks during opening and dropping of temporary tables. This means that we have to call close_thread_tables() even for statements which use only temporary tables. To make this call cheaper, we re-factored close_thread_tables() to not take LOCK_open unless there are open base tables. sql/sql_handler.cc: Properly close temporary tables associated with a handler. sql/sql_insert.cc: close_temporary_table is now merged into drop_temporary_table. sql/sql_parse.cc: Now the condition doesn't cover all cases because close_thread_tables() must be called even for statements that use only temporary tables. sql/sql_table.cc: Use drop_temporary_table which perform checks to verify if the table is not being used. Error path problem is due to a handler tables issue and is going to be addressed in bug 31397. sql/table.h: Rename previously unused clear_query_id and document the usage of query_id and open_by_handler.
2007-11-01 18:52:56 -02:00
handler a2 close;
drop table t1;
Bug#31397 Inconsistent drop table behavior of handler tables. The problem is that DROP TABLE and other DDL statements failed to automatically close handlers associated with tables that were marked for reopen (FLUSH TABLES). The current implementation fails to properly discard handlers of dropped tables (that were marked for reopen) because it searches on the open handler tables list and using the current alias of the table being dropped. The problem is that it must not use the open handler tables list to search because the table might have been closed (marked for reopen) by a flush tables command and also it must not use the current table alias at all since multiple different aliases may be associated with a single table. This is specially visible when a user has two open handlers (using alias) of a same table and a flush tables command is issued before the table is dropped (see test case). Scanning the handler table list is also useless for dropping handlers associated with temporary tables, because temporary tables are not kept in the THD::handler_tables list. The solution is to simple scan the handlers hash table searching for, and deleting all handlers with matching table names if the reopen flag is not passed to the flush function, indicating that the handlers should be deleted. All matching handlers are deleted even if the associated the table is not open. mysql-test/include/handler.inc: Add test case for Bug#31397 mysql-test/r/handler_innodb.result: Add test case result for Bug#31397 mysql-test/r/handler_myisam.result: Add test case result for Bug#31397 sql/mysql_priv.h: Rename flush functions to better match the intent of the caller and update functions prototypes and remove unused flags. sql/sql_base.cc: Rename flush functions to better match the intent of the caller. sql/sql_class.cc: Rename the flush functions to better match the intent of the caller. The hash_free function is moved to the cleanup. sql/sql_handler.cc: When dropping tables for a final close, scan the handler's hash table since the table might not be in the handlers open table list because the table was marked for reopen or because it's a temporary table. sql/sql_rename.cc: Drop handlers associated with tables that are being renamed. sql/sql_table.cc: Now that temporary tables are properly removed even when opened by a SQL HANDLER, enable the assert since this branch can't be taken outside of SF/trigger/prelocked mode.
2007-11-20 15:17:53 -02:00
# Test that temporary tables associated with handlers are properly dropped.
create table t1 (a int);
create temporary table t2 (a int, key using btree (a));
Bug#31397 Inconsistent drop table behavior of handler tables. The problem is that DROP TABLE and other DDL statements failed to automatically close handlers associated with tables that were marked for reopen (FLUSH TABLES). The current implementation fails to properly discard handlers of dropped tables (that were marked for reopen) because it searches on the open handler tables list and using the current alias of the table being dropped. The problem is that it must not use the open handler tables list to search because the table might have been closed (marked for reopen) by a flush tables command and also it must not use the current table alias at all since multiple different aliases may be associated with a single table. This is specially visible when a user has two open handlers (using alias) of a same table and a flush tables command is issued before the table is dropped (see test case). Scanning the handler table list is also useless for dropping handlers associated with temporary tables, because temporary tables are not kept in the THD::handler_tables list. The solution is to simple scan the handlers hash table searching for, and deleting all handlers with matching table names if the reopen flag is not passed to the flush function, indicating that the handlers should be deleted. All matching handlers are deleted even if the associated the table is not open. mysql-test/include/handler.inc: Add test case for Bug#31397 mysql-test/r/handler_innodb.result: Add test case result for Bug#31397 mysql-test/r/handler_myisam.result: Add test case result for Bug#31397 sql/mysql_priv.h: Rename flush functions to better match the intent of the caller and update functions prototypes and remove unused flags. sql/sql_base.cc: Rename flush functions to better match the intent of the caller. sql/sql_class.cc: Rename the flush functions to better match the intent of the caller. The hash_free function is moved to the cleanup. sql/sql_handler.cc: When dropping tables for a final close, scan the handler's hash table since the table might not be in the handlers open table list because the table was marked for reopen or because it's a temporary table. sql/sql_rename.cc: Drop handlers associated with tables that are being renamed. sql/sql_table.cc: Now that temporary tables are properly removed even when opened by a SQL HANDLER, enable the assert since this branch can't be taken outside of SF/trigger/prelocked mode.
2007-11-20 15:17:53 -02:00
handler t1 open as a1;
handler t2 open as a2;
handler a2 read a first;
drop table t1, t2;
--error ER_UNKNOWN_TABLE
handler a2 read a next;
--error ER_UNKNOWN_TABLE
handler a1 close;
# Alter table drop handlers
create table t1 (a int, key using btree (a));
Bug#31397 Inconsistent drop table behavior of handler tables. The problem is that DROP TABLE and other DDL statements failed to automatically close handlers associated with tables that were marked for reopen (FLUSH TABLES). The current implementation fails to properly discard handlers of dropped tables (that were marked for reopen) because it searches on the open handler tables list and using the current alias of the table being dropped. The problem is that it must not use the open handler tables list to search because the table might have been closed (marked for reopen) by a flush tables command and also it must not use the current table alias at all since multiple different aliases may be associated with a single table. This is specially visible when a user has two open handlers (using alias) of a same table and a flush tables command is issued before the table is dropped (see test case). Scanning the handler table list is also useless for dropping handlers associated with temporary tables, because temporary tables are not kept in the THD::handler_tables list. The solution is to simple scan the handlers hash table searching for, and deleting all handlers with matching table names if the reopen flag is not passed to the flush function, indicating that the handlers should be deleted. All matching handlers are deleted even if the associated the table is not open. mysql-test/include/handler.inc: Add test case for Bug#31397 mysql-test/r/handler_innodb.result: Add test case result for Bug#31397 mysql-test/r/handler_myisam.result: Add test case result for Bug#31397 sql/mysql_priv.h: Rename flush functions to better match the intent of the caller and update functions prototypes and remove unused flags. sql/sql_base.cc: Rename flush functions to better match the intent of the caller. sql/sql_class.cc: Rename the flush functions to better match the intent of the caller. The hash_free function is moved to the cleanup. sql/sql_handler.cc: When dropping tables for a final close, scan the handler's hash table since the table might not be in the handlers open table list because the table was marked for reopen or because it's a temporary table. sql/sql_rename.cc: Drop handlers associated with tables that are being renamed. sql/sql_table.cc: Now that temporary tables are properly removed even when opened by a SQL HANDLER, enable the assert since this branch can't be taken outside of SF/trigger/prelocked mode.
2007-11-20 15:17:53 -02:00
create table t2 like t1;
handler t1 open as a1;
handler t2 open as a2;
handler a1 read a first;
handler a2 read a first;
alter table t1 add b int;
--error ER_UNKNOWN_TABLE
handler a1 close;
handler a2 close;
drop table t1, t2;
# Rename table drop handlers
create table t1 (a int, key using btree (a));
Bug#31397 Inconsistent drop table behavior of handler tables. The problem is that DROP TABLE and other DDL statements failed to automatically close handlers associated with tables that were marked for reopen (FLUSH TABLES). The current implementation fails to properly discard handlers of dropped tables (that were marked for reopen) because it searches on the open handler tables list and using the current alias of the table being dropped. The problem is that it must not use the open handler tables list to search because the table might have been closed (marked for reopen) by a flush tables command and also it must not use the current table alias at all since multiple different aliases may be associated with a single table. This is specially visible when a user has two open handlers (using alias) of a same table and a flush tables command is issued before the table is dropped (see test case). Scanning the handler table list is also useless for dropping handlers associated with temporary tables, because temporary tables are not kept in the THD::handler_tables list. The solution is to simple scan the handlers hash table searching for, and deleting all handlers with matching table names if the reopen flag is not passed to the flush function, indicating that the handlers should be deleted. All matching handlers are deleted even if the associated the table is not open. mysql-test/include/handler.inc: Add test case for Bug#31397 mysql-test/r/handler_innodb.result: Add test case result for Bug#31397 mysql-test/r/handler_myisam.result: Add test case result for Bug#31397 sql/mysql_priv.h: Rename flush functions to better match the intent of the caller and update functions prototypes and remove unused flags. sql/sql_base.cc: Rename flush functions to better match the intent of the caller. sql/sql_class.cc: Rename the flush functions to better match the intent of the caller. The hash_free function is moved to the cleanup. sql/sql_handler.cc: When dropping tables for a final close, scan the handler's hash table since the table might not be in the handlers open table list because the table was marked for reopen or because it's a temporary table. sql/sql_rename.cc: Drop handlers associated with tables that are being renamed. sql/sql_table.cc: Now that temporary tables are properly removed even when opened by a SQL HANDLER, enable the assert since this branch can't be taken outside of SF/trigger/prelocked mode.
2007-11-20 15:17:53 -02:00
handler t1 open as a1;
handler a1 read a first;
rename table t1 to t2;
--error ER_UNKNOWN_TABLE
handler a1 read a first;
drop table t2;
# Optimize table drop handlers
create table t1 (a int, key using btree (a));
Bug#31397 Inconsistent drop table behavior of handler tables. The problem is that DROP TABLE and other DDL statements failed to automatically close handlers associated with tables that were marked for reopen (FLUSH TABLES). The current implementation fails to properly discard handlers of dropped tables (that were marked for reopen) because it searches on the open handler tables list and using the current alias of the table being dropped. The problem is that it must not use the open handler tables list to search because the table might have been closed (marked for reopen) by a flush tables command and also it must not use the current table alias at all since multiple different aliases may be associated with a single table. This is specially visible when a user has two open handlers (using alias) of a same table and a flush tables command is issued before the table is dropped (see test case). Scanning the handler table list is also useless for dropping handlers associated with temporary tables, because temporary tables are not kept in the THD::handler_tables list. The solution is to simple scan the handlers hash table searching for, and deleting all handlers with matching table names if the reopen flag is not passed to the flush function, indicating that the handlers should be deleted. All matching handlers are deleted even if the associated the table is not open. mysql-test/include/handler.inc: Add test case for Bug#31397 mysql-test/r/handler_innodb.result: Add test case result for Bug#31397 mysql-test/r/handler_myisam.result: Add test case result for Bug#31397 sql/mysql_priv.h: Rename flush functions to better match the intent of the caller and update functions prototypes and remove unused flags. sql/sql_base.cc: Rename flush functions to better match the intent of the caller. sql/sql_class.cc: Rename the flush functions to better match the intent of the caller. The hash_free function is moved to the cleanup. sql/sql_handler.cc: When dropping tables for a final close, scan the handler's hash table since the table might not be in the handlers open table list because the table was marked for reopen or because it's a temporary table. sql/sql_rename.cc: Drop handlers associated with tables that are being renamed. sql/sql_table.cc: Now that temporary tables are properly removed even when opened by a SQL HANDLER, enable the assert since this branch can't be taken outside of SF/trigger/prelocked mode.
2007-11-20 15:17:53 -02:00
create table t2 like t1;
handler t1 open as a1;
handler t2 open as a2;
handler a1 read a first;
handler a2 read a first;
optimize table t1;
--error ER_UNKNOWN_TABLE
handler a1 close;
handler a2 close;
drop table t1, t2;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo #
--echo # Add test coverage for HANDLER and LOCK TABLES, HANDLER and DDL.
--echo #
--disable_warnings
drop table if exists t1, t2, t3;
--enable_warnings
create table t1 (a int, key a (a));
insert into t1 (a) values (1), (2), (3), (4), (5);
create table t2 (a int, key a (a)) select * from t1;
create temporary table t3 (a int, key a (a)) select * from t2;
handler t1 open;
handler t2 open;
handler t3 open;
--echo #
Fix for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". Server was aborted due to assertion failure when one tried to execute statement requiring prelocking (i.e. firing triggers or using stored functions) while having open HANDLERs. The problem was that THD::enter_locked_tables_mode() method which was called at the beginning of execution of prelocked statement assumed there are no open HANDLERs. It had to do so because corresponding THD::leave_locked_tables_mode() method was unable to properly restore MDL sentinel when leaving LOCK TABLES/prelocked mode in the presence of open HANDLERs. This patch solves this problem by changing the latter method to properly restore MDL sentinel and thus removing need for this assumption. As a side-effect, it lifts unjustified limitation by allowing to keep HANDLERs open when entering LOCK TABLES mode. mysql-test/include/handler.inc: Adjusted tests after making LOCK TABLES not to close open HANDLERs. Added coverage for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". mysql-test/r/handler_innodb.result: Updated test results (see include/handler.inc). mysql-test/r/handler_myisam.result: Updated test results (see include/handler.inc). sql/mysql_priv.h: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_class.cc: Changed THD::leave_locked_tables_mode() to correctly restore MDL sentinel value in the presence of open HANDLERs. sql/sql_class.h: Removed assert from THD::enter_locked_tables_mode() as we no longer have to close HANDLERs when entering LOCK TABLES or prelocked modes. Instead we keep them open and correctly restore MDL sentinel value after leaving them. Removal of assert also fixes problem from the bug report. sql/sql_handler.cc: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_parse.cc: We no longer have to close HANDLERs when entering LOCK TABLES mode. Instead we keep them open and simply correctly restore MDL sentinel value after leaving this mode.
2010-02-12 10:05:43 +03:00
--echo # No HANDLER sql is allowed under LOCK TABLES.
--echo # But it does not implicitly closes all handlers.
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo #
Fix for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". Server was aborted due to assertion failure when one tried to execute statement requiring prelocking (i.e. firing triggers or using stored functions) while having open HANDLERs. The problem was that THD::enter_locked_tables_mode() method which was called at the beginning of execution of prelocked statement assumed there are no open HANDLERs. It had to do so because corresponding THD::leave_locked_tables_mode() method was unable to properly restore MDL sentinel when leaving LOCK TABLES/prelocked mode in the presence of open HANDLERs. This patch solves this problem by changing the latter method to properly restore MDL sentinel and thus removing need for this assumption. As a side-effect, it lifts unjustified limitation by allowing to keep HANDLERs open when entering LOCK TABLES mode. mysql-test/include/handler.inc: Adjusted tests after making LOCK TABLES not to close open HANDLERs. Added coverage for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". mysql-test/r/handler_innodb.result: Updated test results (see include/handler.inc). mysql-test/r/handler_myisam.result: Updated test results (see include/handler.inc). sql/mysql_priv.h: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_class.cc: Changed THD::leave_locked_tables_mode() to correctly restore MDL sentinel value in the presence of open HANDLERs. sql/sql_class.h: Removed assert from THD::enter_locked_tables_mode() as we no longer have to close HANDLERs when entering LOCK TABLES or prelocked modes. Instead we keep them open and correctly restore MDL sentinel value after leaving them. Removal of assert also fixes problem from the bug report. sql/sql_handler.cc: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_parse.cc: We no longer have to close HANDLERs when entering LOCK TABLES mode. Instead we keep them open and simply correctly restore MDL sentinel value after leaving this mode.
2010-02-12 10:05:43 +03:00
lock table t1 read;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--error ER_LOCK_OR_ACTIVE_TRANSACTION
handler t1 open;
--error ER_LOCK_OR_ACTIVE_TRANSACTION
handler t1 read next;
--error ER_LOCK_OR_ACTIVE_TRANSACTION
handler t2 close;
2013-07-12 21:41:20 +02:00
--error ER_CANT_REOPEN_TABLE
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
handler t3 open;
Fix for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". Server was aborted due to assertion failure when one tried to execute statement requiring prelocking (i.e. firing triggers or using stored functions) while having open HANDLERs. The problem was that THD::enter_locked_tables_mode() method which was called at the beginning of execution of prelocked statement assumed there are no open HANDLERs. It had to do so because corresponding THD::leave_locked_tables_mode() method was unable to properly restore MDL sentinel when leaving LOCK TABLES/prelocked mode in the presence of open HANDLERs. This patch solves this problem by changing the latter method to properly restore MDL sentinel and thus removing need for this assumption. As a side-effect, it lifts unjustified limitation by allowing to keep HANDLERs open when entering LOCK TABLES mode. mysql-test/include/handler.inc: Adjusted tests after making LOCK TABLES not to close open HANDLERs. Added coverage for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". mysql-test/r/handler_innodb.result: Updated test results (see include/handler.inc). mysql-test/r/handler_myisam.result: Updated test results (see include/handler.inc). sql/mysql_priv.h: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_class.cc: Changed THD::leave_locked_tables_mode() to correctly restore MDL sentinel value in the presence of open HANDLERs. sql/sql_class.h: Removed assert from THD::enter_locked_tables_mode() as we no longer have to close HANDLERs when entering LOCK TABLES or prelocked modes. Instead we keep them open and correctly restore MDL sentinel value after leaving them. Removal of assert also fixes problem from the bug report. sql/sql_handler.cc: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_parse.cc: We no longer have to close HANDLERs when entering LOCK TABLES mode. Instead we keep them open and simply correctly restore MDL sentinel value after leaving this mode.
2010-02-12 10:05:43 +03:00
--echo # After UNLOCK TABLES handlers should be around and
--echo # we should be able to continue reading through them.
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
unlock tables;
handler t1 read next;
Fix for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". Server was aborted due to assertion failure when one tried to execute statement requiring prelocking (i.e. firing triggers or using stored functions) while having open HANDLERs. The problem was that THD::enter_locked_tables_mode() method which was called at the beginning of execution of prelocked statement assumed there are no open HANDLERs. It had to do so because corresponding THD::leave_locked_tables_mode() method was unable to properly restore MDL sentinel when leaving LOCK TABLES/prelocked mode in the presence of open HANDLERs. This patch solves this problem by changing the latter method to properly restore MDL sentinel and thus removing need for this assumption. As a side-effect, it lifts unjustified limitation by allowing to keep HANDLERs open when entering LOCK TABLES mode. mysql-test/include/handler.inc: Adjusted tests after making LOCK TABLES not to close open HANDLERs. Added coverage for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". mysql-test/r/handler_innodb.result: Updated test results (see include/handler.inc). mysql-test/r/handler_myisam.result: Updated test results (see include/handler.inc). sql/mysql_priv.h: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_class.cc: Changed THD::leave_locked_tables_mode() to correctly restore MDL sentinel value in the presence of open HANDLERs. sql/sql_class.h: Removed assert from THD::enter_locked_tables_mode() as we no longer have to close HANDLERs when entering LOCK TABLES or prelocked modes. Instead we keep them open and correctly restore MDL sentinel value after leaving them. Removal of assert also fixes problem from the bug report. sql/sql_handler.cc: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_parse.cc: We no longer have to close HANDLERs when entering LOCK TABLES mode. Instead we keep them open and simply correctly restore MDL sentinel value after leaving this mode.
2010-02-12 10:05:43 +03:00
handler t1 close;
handler t2 read next;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
handler t2 close;
handler t3 read next;
Fix for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". Server was aborted due to assertion failure when one tried to execute statement requiring prelocking (i.e. firing triggers or using stored functions) while having open HANDLERs. The problem was that THD::enter_locked_tables_mode() method which was called at the beginning of execution of prelocked statement assumed there are no open HANDLERs. It had to do so because corresponding THD::leave_locked_tables_mode() method was unable to properly restore MDL sentinel when leaving LOCK TABLES/prelocked mode in the presence of open HANDLERs. This patch solves this problem by changing the latter method to properly restore MDL sentinel and thus removing need for this assumption. As a side-effect, it lifts unjustified limitation by allowing to keep HANDLERs open when entering LOCK TABLES mode. mysql-test/include/handler.inc: Adjusted tests after making LOCK TABLES not to close open HANDLERs. Added coverage for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". mysql-test/r/handler_innodb.result: Updated test results (see include/handler.inc). mysql-test/r/handler_myisam.result: Updated test results (see include/handler.inc). sql/mysql_priv.h: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_class.cc: Changed THD::leave_locked_tables_mode() to correctly restore MDL sentinel value in the presence of open HANDLERs. sql/sql_class.h: Removed assert from THD::enter_locked_tables_mode() as we no longer have to close HANDLERs when entering LOCK TABLES or prelocked modes. Instead we keep them open and correctly restore MDL sentinel value after leaving them. Removal of assert also fixes problem from the bug report. sql/sql_handler.cc: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_parse.cc: We no longer have to close HANDLERs when entering LOCK TABLES mode. Instead we keep them open and simply correctly restore MDL sentinel value after leaving this mode.
2010-02-12 10:05:43 +03:00
handler t3 close;
drop temporary table t3;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo #
Fix for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". Server was aborted due to assertion failure when one tried to execute statement requiring prelocking (i.e. firing triggers or using stored functions) while having open HANDLERs. The problem was that THD::enter_locked_tables_mode() method which was called at the beginning of execution of prelocked statement assumed there are no open HANDLERs. It had to do so because corresponding THD::leave_locked_tables_mode() method was unable to properly restore MDL sentinel when leaving LOCK TABLES/prelocked mode in the presence of open HANDLERs. This patch solves this problem by changing the latter method to properly restore MDL sentinel and thus removing need for this assumption. As a side-effect, it lifts unjustified limitation by allowing to keep HANDLERs open when entering LOCK TABLES mode. mysql-test/include/handler.inc: Adjusted tests after making LOCK TABLES not to close open HANDLERs. Added coverage for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". mysql-test/r/handler_innodb.result: Updated test results (see include/handler.inc). mysql-test/r/handler_myisam.result: Updated test results (see include/handler.inc). sql/mysql_priv.h: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_class.cc: Changed THD::leave_locked_tables_mode() to correctly restore MDL sentinel value in the presence of open HANDLERs. sql/sql_class.h: Removed assert from THD::enter_locked_tables_mode() as we no longer have to close HANDLERs when entering LOCK TABLES or prelocked modes. Instead we keep them open and correctly restore MDL sentinel value after leaving them. Removal of assert also fixes problem from the bug report. sql/sql_handler.cc: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_parse.cc: We no longer have to close HANDLERs when entering LOCK TABLES mode. Instead we keep them open and simply correctly restore MDL sentinel value after leaving this mode.
2010-02-12 10:05:43 +03:00
--echo # Other operations that implicitly close handler:
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo #
--echo # TRUNCATE
--echo #
handler t1 open;
truncate table t1;
--error ER_UNKNOWN_TABLE
handler t1 read next;
handler t1 open;
--echo #
--echo # CREATE TRIGGER
--echo #
create trigger t1_ai after insert on t1 for each row set @a=1;
--error ER_UNKNOWN_TABLE
handler t1 read next;
--echo #
--echo # DROP TRIGGER
--echo #
handler t1 open;
drop trigger t1_ai;
--error ER_UNKNOWN_TABLE
handler t1 read next;
--echo #
--echo # ALTER TABLE
--echo #
handler t1 open;
alter table t1 add column b int;
--error ER_UNKNOWN_TABLE
handler t1 read next;
--echo #
--echo # ANALYZE TABLE
--echo #
handler t1 open;
analyze table t1;
--error ER_UNKNOWN_TABLE
handler t1 read next;
--echo #
--echo # OPTIMIZE TABLE
--echo #
handler t1 open;
optimize table t1;
--error ER_UNKNOWN_TABLE
handler t1 read next;
--echo #
--echo # REPAIR TABLE
--echo #
handler t1 open;
repair table t1;
--error ER_UNKNOWN_TABLE
handler t1 read next;
--echo #
--echo # DROP TABLE, naturally.
--echo #
handler t1 open;
drop table t1;
--error ER_UNKNOWN_TABLE
handler t1 read next;
create table t1 (a int, b int, key a using btree (a)) select a from t2;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo #
--echo # RENAME TABLE, naturally
--echo #
handler t1 open;
rename table t1 to t3;
--error ER_UNKNOWN_TABLE
handler t1 read next;
--echo #
--echo # CREATE TABLE (even with IF NOT EXISTS clause,
--echo # and the table exists).
--echo #
handler t2 open;
create table if not exists t2 (a int);
--error ER_UNKNOWN_TABLE
handler t2 read next;
rename table t3 to t1;
drop table t2;
--echo #
--echo # FLUSH TABLE doesn't close the table but loses the position
--echo #
handler t1 open;
handler t1 read a prev;
flush table t1;
handler t1 read a prev;
handler t1 close;
--echo #
--echo # FLUSH TABLES WITH READ LOCK behaves like FLUSH TABLE.
--echo #
handler t1 open;
handler t1 read a prev;
flush tables with read lock;
handler t1 read a prev;
handler t1 close;
unlock tables;
--echo #
Fix for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". Server was aborted due to assertion failure when one tried to execute statement requiring prelocking (i.e. firing triggers or using stored functions) while having open HANDLERs. The problem was that THD::enter_locked_tables_mode() method which was called at the beginning of execution of prelocked statement assumed there are no open HANDLERs. It had to do so because corresponding THD::leave_locked_tables_mode() method was unable to properly restore MDL sentinel when leaving LOCK TABLES/prelocked mode in the presence of open HANDLERs. This patch solves this problem by changing the latter method to properly restore MDL sentinel and thus removing need for this assumption. As a side-effect, it lifts unjustified limitation by allowing to keep HANDLERs open when entering LOCK TABLES mode. mysql-test/include/handler.inc: Adjusted tests after making LOCK TABLES not to close open HANDLERs. Added coverage for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". mysql-test/r/handler_innodb.result: Updated test results (see include/handler.inc). mysql-test/r/handler_myisam.result: Updated test results (see include/handler.inc). sql/mysql_priv.h: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_class.cc: Changed THD::leave_locked_tables_mode() to correctly restore MDL sentinel value in the presence of open HANDLERs. sql/sql_class.h: Removed assert from THD::enter_locked_tables_mode() as we no longer have to close HANDLERs when entering LOCK TABLES or prelocked modes. Instead we keep them open and correctly restore MDL sentinel value after leaving them. Removal of assert also fixes problem from the bug report. sql/sql_handler.cc: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_parse.cc: We no longer have to close HANDLERs when entering LOCK TABLES mode. Instead we keep them open and simply correctly restore MDL sentinel value after leaving this mode.
2010-02-12 10:05:43 +03:00
--echo # Let us also check that these operations behave in similar
--echo # way under LOCK TABLES.
--echo #
--echo # TRUNCATE under LOCK TABLES.
--echo #
handler t1 open;
lock tables t1 write;
truncate table t1;
unlock tables;
--error ER_UNKNOWN_TABLE
handler t1 read next;
handler t1 open;
--echo #
--echo # CREATE TRIGGER under LOCK TABLES.
--echo #
lock tables t1 write;
create trigger t1_ai after insert on t1 for each row set @a=1;
unlock tables;
--error ER_UNKNOWN_TABLE
handler t1 read next;
--echo #
--echo # DROP TRIGGER under LOCK TABLES.
--echo #
handler t1 open;
lock tables t1 write;
drop trigger t1_ai;
unlock tables;
--error ER_UNKNOWN_TABLE
handler t1 read next;
--echo #
--echo # ALTER TABLE under LOCK TABLES.
--echo #
handler t1 open;
lock tables t1 write;
alter table t1 drop column b;
unlock tables;
--error ER_UNKNOWN_TABLE
handler t1 read next;
--echo #
--echo # ANALYZE TABLE under LOCK TABLES.
--echo #
handler t1 open;
lock tables t1 write;
analyze table t1;
unlock tables;
--error ER_UNKNOWN_TABLE
handler t1 read next;
--echo #
--echo # OPTIMIZE TABLE under LOCK TABLES.
--echo #
handler t1 open;
lock tables t1 write;
optimize table t1;
unlock tables;
--error ER_UNKNOWN_TABLE
handler t1 read next;
--echo #
--echo # REPAIR TABLE under LOCK TABLES.
--echo #
handler t1 open;
lock tables t1 write;
repair table t1;
unlock tables;
--error ER_UNKNOWN_TABLE
handler t1 read next;
--echo #
--echo # DROP TABLE under LOCK TABLES, naturally.
--echo #
handler t1 open;
lock tables t1 write;
drop table t1;
unlock tables;
--error ER_UNKNOWN_TABLE
handler t1 read next;
create table t1 (a int, b int, key a using btree (a));
Fix for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". Server was aborted due to assertion failure when one tried to execute statement requiring prelocking (i.e. firing triggers or using stored functions) while having open HANDLERs. The problem was that THD::enter_locked_tables_mode() method which was called at the beginning of execution of prelocked statement assumed there are no open HANDLERs. It had to do so because corresponding THD::leave_locked_tables_mode() method was unable to properly restore MDL sentinel when leaving LOCK TABLES/prelocked mode in the presence of open HANDLERs. This patch solves this problem by changing the latter method to properly restore MDL sentinel and thus removing need for this assumption. As a side-effect, it lifts unjustified limitation by allowing to keep HANDLERs open when entering LOCK TABLES mode. mysql-test/include/handler.inc: Adjusted tests after making LOCK TABLES not to close open HANDLERs. Added coverage for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". mysql-test/r/handler_innodb.result: Updated test results (see include/handler.inc). mysql-test/r/handler_myisam.result: Updated test results (see include/handler.inc). sql/mysql_priv.h: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_class.cc: Changed THD::leave_locked_tables_mode() to correctly restore MDL sentinel value in the presence of open HANDLERs. sql/sql_class.h: Removed assert from THD::enter_locked_tables_mode() as we no longer have to close HANDLERs when entering LOCK TABLES or prelocked modes. Instead we keep them open and correctly restore MDL sentinel value after leaving them. Removal of assert also fixes problem from the bug report. sql/sql_handler.cc: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_parse.cc: We no longer have to close HANDLERs when entering LOCK TABLES mode. Instead we keep them open and simply correctly restore MDL sentinel value after leaving this mode.
2010-02-12 10:05:43 +03:00
insert into t1 (a) values (1), (2), (3), (4), (5);
--echo #
--echo # FLUSH TABLE doesn't close the table but loses the position
--echo #
handler t1 open;
handler t1 read a prev;
lock tables t1 write;
flush table t1;
unlock tables;
handler t1 read a prev;
handler t1 close;
--echo #
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo # Explore the effect of HANDLER locks on concurrent DDL
--echo #
handler t1 open;
--echo # Establishing auxiliary connections con1, con2, con3
connect(con1, localhost, root,,);
connect(con2, localhost, root,,);
connect(con3, localhost, root,,);
--echo # --> connection con1;
connection con1;
--echo # Sending:
--send drop table t1
--echo # We can't use connection 'default' as wait_condition will
--echo # autoclose handlers.
--echo # --> connection con2
connection con2;
--echo # Waitng for 'drop table t1' to get blocked...
Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompatible" to be pushed as separate patch. Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. Also replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it more consistent with other thread state names. Updated test cases and their results according to these changes. Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. mysql-test/r/query_cache.result: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/t/query_cache.test: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysys/thr_lock.c: Replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it consistent with thread state names which are used while waiting for metadata locks and table flush. sql/mdl.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/mdl.h: To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/sql_base.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for table flush, with a more elaborate "Waiting for table flush".
2010-08-06 15:29:37 +04:00
let $wait_condition=select count(*)=1 from information_schema.processlist
where state='Waiting for table metadata lock' and
info='drop table t1';
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--source include/wait_condition.inc
--echo # --> connection default
connection default;
handler t1 read a prev;
handler t1 read a prev;
handler t1 close;
--echo # --> connection con1
connection con1;
--echo # Reaping 'drop table t1'...
--reap
--echo # --> connection default
connection default;
--echo #
--echo # Explore the effect of HANDLER locks in parallel with SELECT
--echo #
create table t1 (a int, key a using btree (a));
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
insert into t1 (a) values (1), (2), (3), (4), (5);
begin;
select * from t1;
handler t1 open;
handler t1 read a prev;
handler t1 read a prev;
handler t1 close;
--echo # --> connection con1;
connection con1;
--echo # Sending:
--send drop table t1
--echo # --> connection con2
connection con2;
--echo # Waiting for 'drop table t1' to get blocked...
Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompatible" to be pushed as separate patch. Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. Also replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it more consistent with other thread state names. Updated test cases and their results according to these changes. Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. mysql-test/r/query_cache.result: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/t/query_cache.test: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysys/thr_lock.c: Replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it consistent with thread state names which are used while waiting for metadata locks and table flush. sql/mdl.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/mdl.h: To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/sql_base.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for table flush, with a more elaborate "Waiting for table flush".
2010-08-06 15:29:37 +04:00
let $wait_condition=select count(*)=1 from information_schema.processlist
where state='Waiting for table metadata lock' and
info='drop table t1';
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--source include/wait_condition.inc
--echo # --> connection default
connection default;
--echo # We can still use the table, it's part of the transaction
select * from t1;
--echo # Such are the circumstances that t1 is a part of transaction,
--echo # thus we can reopen it in the handler
handler t1 open;
--echo # We can commit the transaction, it doesn't close the handler
--echo # and doesn't let DROP to proceed.
commit;
handler t1 read a prev;
handler t1 read a prev;
handler t1 read a prev;
handler t1 close;
--echo # --> connection con1
connection con1;
--echo # Now drop can proceed
--echo # Reaping 'drop table t1'...
--reap
--echo # --> connection default
connection default;
--echo #
--echo # Demonstrate that HANDLER locks and transaction locks
Fix for bug#14188793 - "DEADLOCK CAUSED BY ALTER TABLE DOEN'T CLEAR STATUS OF ROLLBACKED TRANSACTION" and bug #17054007 - "TRANSACTION IS NOT FULLY ROLLED BACK IN CASE OF INNODB DEADLOCK". The problem in the first bug report was that although deadlock involving metadata locks was reported using the same error code and message as InnoDB deadlock it didn't rollback transaction like the latter. This caused confusion to users as in some cases after ER_LOCK_DEADLOCK transaction could have been restarted immediately and in some cases rollback was required. The problem in the second bug report was that although InnoDB deadlock caused transaction rollback in all storage engines it didn't cause release of metadata locks. So concurrent DDL on the tables used in transaction was blocked until implicit or explicit COMMIT or ROLLBACK was issued in the connection which got InnoDB deadlock. The former issue has stemmed from the fact that when support for detection and reporting metadata locks deadlocks was added we erroneously assumed that InnoDB doesn't rollback transaction on deadlock but only last statement (while this is what happens on InnoDB lock timeout actually) and so didn't implement rollback of transactions on MDL deadlocks. The latter issue was caused by the fact that rollback of transaction due to deadlock is carried out by setting THD::transaction_rollback_request flag at the point where deadlock is detected and performing rollback inside of trans_rollback_stmt() call when this flag is set. And trans_rollback_stmt() is not aware of MDL locks, so no MDL locks are released. This patch solves these two problems in the following way: - In case when MDL deadlock is detect transaction rollback is requested by setting THD::transaction_rollback_request flag. - Code performing rollback of transaction if THD::transaction_rollback_request is moved out from trans_rollback_stmt(). Now we handle rollback request on the same level as we call trans_rollback_stmt() and release statement/ transaction MDL locks.
2013-08-20 13:12:34 +04:00
--echo # reside in the same context.
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo #
create table t1 (a int, key a (a));
insert into t1 (a) values (1), (2), (3), (4), (5);
create table t0 (a int, key a using btree (a));
Patch that changes metadata locking subsystem to use mutex per lock and condition variable per context instead of one mutex and one conditional variable for the whole subsystem. This should increase concurrency in this subsystem. It also opens the way for further changes which are necessary to solve such bugs as bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock" and bug #37346 "innodb does not detect deadlock between update and alter table". Two other notable changes done by this patch: - MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. - Instead of using separate MDL_context for opening system tables/tables for purposes of I_S we now create MDL savepoint in the main context before opening tables and rollback to this savepoint after closing them. This means that it is now possible to get ER_LOCK_DEADLOCK error even not inside a transaction. This might happen in unlikely case when one runs DDL on one of system tables while also running DDL on some other tables. Cases when this ER_LOCK_DEADLOCK error is not justified will be addressed by advanced deadlock detector for MDL subsystem which we plan to implement. mysql-test/include/handler.inc: Adjusted handler_myisam.test and handler_innodb.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/r/handler_innodb.result: Adjusted handler_myisam.test and handler_innodb.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/r/handler_myisam.result: Adjusted handler_myisam.test and handler_innodb.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/r/mdl_sync.result: Adjusted mdl_sync.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/t/mdl_sync.test: Adjusted mdl_sync.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. sql/events.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/ha_ndbcluster.cc: Since manipulations with open table state no longer install proxy MDL_context it does not make sense to perform them in order to satisfy assert in mysql_rm_tables_part2(). Removed them per agreement with Cluster team. This has not broken test suite since scenario in which deadlock can occur and assertion fails is not covered by tests. sql/lock.cc: MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object exclusive metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. sql/log.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/mdl.cc: Changed metadata locking subsystem to use mutex per lock and condition variable per context instead of one mutex and one conditional variable for the whole subsystem. Changed approach to handling of global metadata locks. Instead of implicitly acquiring intention exclusive locks when user requests per-object upgradeable or exclusive locks now we require them to be acquired explicitly in the same way as ordinary metadata locks. In fact global lock are now ordinary metadata locks in new GLOBAL namespace. To implement these changes: - Removed LOCK_mdl mutex and COND_mdl condition variable. - Introduced MDL_lock::m_mutex mutexes which protect individual lock objects. - Replaced mdl_locks hash with MDL_map class, which has hash for MDL_lock objects as a member and separate mutex which protects this hash. Methods of this class allow to find(), find_or_create() or remove() MDL_lock objects in concurrency-friendly fashion (i.e. for most common operation, find_or_create(), we don't acquire MDL_lock::m_mutex while holding MDL_map::m_mutex. Thanks to MikaelR for this idea and benchmarks!). Added three auxiliary members to MDL_lock class (m_is_destroyed, m_ref_usage, m_ref_release) to support this concurrency-friendly behavior. - Introduced MDL_context::m_ctx_wakeup_cond condition variable to be used for waiting until this context's pending request can be satisfied or its thread has to perform actions to resolve potential deadlock. Context which want to wait add ticket corresponding to the request to an appropriate queue of waiters in MDL_lock object so they can be noticed when other contexts change state of lock and be awaken by them by signalling on MDL_context::m_ctx_wakeup_cond. As consequence MDL_ticket objects has to be used for any waiting in metadata locking subsystem including one which happens in MDL_context::wait_for_locks() method. Another consequence is that MDL_context is no longer copyable and can't be saved/restored when working with system tables. - Made MDL_lock an abstract class, which delegates specifying exact compatibility matrix to its descendants. Added MDL_global_lock child class for global lock (The old is_lock_type_compatible() method became can_grant_lock() method of this class). Added MDL_object_lock class to represent per-object lock (The old MDL_lock::can_grant_lock() became its method). Choice between two classes happens based on MDL namespace in MDL_lock::create() method. - Got rid of MDL_lock::type member as its meaning became ambigous for global locks. - To simplify waking up of contexts waiting for lock split waiting queue in MDL_lock class in two queues. One for pending requests for exclusive (including intention exclusive) locks and another for requests for shared locks. - Added virtual wake_up_waiters() method to MDL_lock, MDL_global_lock and MDL_object_lock classes which allows to wake up waiting contexts after state of lock changes. Replaced old duplicated code with calls to this method. - Adjusted MDL_context::try_acquire_shared_lock()/exclusive_lock()/ global_shared_lock(), MDL_ticket::upgrade_shared_lock_to_exclusive_lock() and MDL_context::release_ticket() methods to use MDL_map and MDL_lock::m_mutex instead of single LOCK_mdl mutex and wake up waiters according to the approach described above. The latter method also was renamed to MDL_context::release_lock(). - Changed MDL_context::try_acquire_shared_lock()/exclusive_lock() and release_lock() not to handle global locks. They are now supposed to be taken explicitly like ordinary metadata locks. - Added helper MDL_context::try_acquire_global_intention_exclusive_lock() and acquire_global_intention_exclusive_lock() methods. - Moved common code from MDL_context::acquire_global_shared_lock() and acquire_global_intention_exclusive_lock() to new method - MDL_context::acquire_lock_impl(). - Moved common code from MDL_context::try_acquire_shared_lock(), try_acquire_global_intention_exclusive_lock()/exclusive_lock() to MDL_context::try_acquire_lock_impl(). - Since acquiring of several exclusive locks can no longer happen under single LOCK_mdl mutex the approach to it had to be changed. Now we do it in one by one fashion. This is done in alphabetical order to avoid deadlocks. Changed MDL_context::acquire_exclusive_locks() accordingly (as part of this change moved code responsible for acquiring single exclusive lock to new MDL_context::acquire_exclusive_lock_impl() method). - Since we no longer have single LOCK_mdl mutex which protects all MDL_context::m_is_waiting_in_mdl members using these members to determine if we have really awaken context holding conflicting shared lock became inconvinient. Got rid of this member and changed notify_shared_lock() helper function and process of acquiring of/upgrading to exclusive lock not to rely on such information. Now in MDL_context::acquire_exclusive_lock_impl() and MDL_ticket::upgrade_shared_lock_to_exclusive_lock() we simply re-try to wake up threads holding conflicting shared locks after small time out. - Adjusted MDL_context::can_wait_lead_to_deadlock() and MDL_ticket::has_pending_conflicting_lock() to use per-lock mutexes instead of LOCK_mdl. To do this introduced MDL_lock::has_pending_exclusive_lock() method. sql/mdl.h: Changed metadata locking subsystem to use mutex per lock and condition variable per context instead of one mutex and one conditional variable for the whole subsystem. In order to implement this change: - Added MDL_key::cmp() method to be able to sort MDL_key objects alphabetically. Changed length fields in MDL_key class to uint16 as 16-bit is enough for length of any key. - Changed MDL_ticket::get_ctx() to return pointer to non-const object in order to be able to use MDL_context::awake() method for such contexts. - Got rid of unlocked versions of can_wait_lead_to_deadlock()/ has_pending_conflicting_lock() methods in MDL_context and MDL_ticket. We no longer has single mutex which protects all locks. Thus one always has to use versions of these methods which acquire per-lock mutexes. - MDL_request_list type of list now counts its elements. - Added MDL_context::m_ctx_wakeup_cond condition variable to be used for waiting until this context's pending request can be satisfied or its thread has to perform actions to resolve potential deadlock. Added awake() method to wake up context from such wait. Addition of condition variable made MDL_context uncopyable. As result we no longer can save/restore MDL_context when working with system tables. Instead we create MDL savepoint before opening those tables and rollback to it once they are closed. - MDL_context::release_ticket() became release_lock() method. - Added auxiliary MDL_context::acquire_exclusive_lock_impl() method which does all necessary work to acquire exclusive lock on one object but should not be used directly as it does not enforce any asserts ensuring that no deadlocks are possible. - Since we no longer need to know if thread trying to acquire exclusive lock managed to wake up any threads having conflicting shared locks (as, anyway, we will try to wake up such threads again shortly) - MDL_context::m_is_waiting_in_mdl member became unnecessary and notify_shared_lock() no longer needs to be friend of MDL_context. Changed approach to handling of global metadata locks. Instead of implicitly acquiring intention exclusive locks when user requests per-object upgradeable or exclusive locks now we require them to be acquired explicitly in the same way as ordinary metadata locks. - Added new GLOBAL namespace for such locks. - Added new type of lock to be requested MDL_INTENTION_EXCLISIVE. - Added MDL_context::try_acquire_global_intention_exclusive_lock() and acquire_global_intention_exclusive_lock() methods. - Moved common code from MDL_context::acquire_global_shared_lock() and acquire_global_intention_exclusive_lock() to new method - MDL_context::acquire_lock_impl(). - Moved common code from MDL_context::try_acquire_shared_lock(), try_acquire_global_intention_exclusive_lock()/exclusive_lock() to MDL_context::try_acquire_lock_impl(). - Added helper MDL_context::is_global_lock_owner() method to be able easily to find what kind of global lock this context holds. - MDL_context::m_has_global_shared_lock became unnecessary as global read lock is now represented by ordinary ticket. - Removed assert in MDL_context::set_lt_or_ha_sentinel() which became false for cases when we execute LOCK TABLES under global read lock mode. sql/mysql_priv.h: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result calls opening/closing system tables were changed to use Open_tables_backup instead of Open_table_state class as well. sql/sp.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sp.h: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sql_base.cc: close_thread_tables(): Since we no longer use separate MDL_context for opening system tables we need to avoid releasing all transaction locks when closing system table. Releasing metadata lock on system table is now responsibility of THD::restore_backup_open_tables_state(). open_table_get_mdl_lock(), Open_table_context::recover_from_failed_open(): MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object upgradable or exclusive metadata lock is acquired. So this have to be done explicitly from these calls. Changed Open_table_context class to store MDL_request object for global intention exclusive lock acquired when opening tables. open_table(): Do not release metadata lock if we have failed to open table as this lock might have been acquired by one of previous statements in transaction, and therefore should not be released. open_system_tables_for_read()/close_system_tables()/ open_performance_schema_table(): Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. close_performance_schema_table(): Got rid of duplicated code. sql/sql_class.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. Also releasing metadata lock on system table is now responsibility of THD::restore_backup_open_tables_state(). Adjusted assert in THD::cleanup() to take into account fact that now we also use MDL sentinel for global read lock. sql/sql_class.h: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. As result: - 'mdl_context' member was moved out of Open_tables_state to THD class. enter_locked_tables_mode()/leave_locked_tables_mode() had to follow. - Methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. Changed Open_table_context class to store MDL_request object for global intention exclusive lock acquired when opening tables. sql/sql_delete.cc: MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object exclusive metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. sql/sql_help.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sql_parse.cc: Adjusted assert reload_acl_and_cache() to the fact that global read lock now takes full-blown metadata lock. sql/sql_plist.h: Added support for element counting to I_P_List list template. One can use policy classes to specify if such counting is needed or not needed for particular list. sql/sql_show.cc: Instead of using separate MDL_context for opening tables for I_S purposes we now create MDL savepoint in the main context before opening tables and rollback to this savepoint after closing them. To support this and similar change for system tables methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing tables for I_S purposes was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sql_table.cc: mysql_rm_tables_part2(): Since now global intention exclusive metadata lock is ordinary metadata lock we no longer can rely that by releasing MDL locks on all tables we will release all locks acquired by this routine. So in non-LOCK-TABLES mode we have to release all locks acquired explicitly. prepare_for_repair(), mysql_alter_table(): MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object exclusive metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. sql/tztime.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. Also changed code not to use special mechanism for open system tables when it is not really necessary.
2010-01-21 23:43:03 +03:00
insert into t0 (a) values (1), (2), (3), (4), (5);
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
begin;
select * from t1;
--echo # --> connection con2
connection con2;
--echo # Sending:
Patch that changes metadata locking subsystem to use mutex per lock and condition variable per context instead of one mutex and one conditional variable for the whole subsystem. This should increase concurrency in this subsystem. It also opens the way for further changes which are necessary to solve such bugs as bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock" and bug #37346 "innodb does not detect deadlock between update and alter table". Two other notable changes done by this patch: - MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. - Instead of using separate MDL_context for opening system tables/tables for purposes of I_S we now create MDL savepoint in the main context before opening tables and rollback to this savepoint after closing them. This means that it is now possible to get ER_LOCK_DEADLOCK error even not inside a transaction. This might happen in unlikely case when one runs DDL on one of system tables while also running DDL on some other tables. Cases when this ER_LOCK_DEADLOCK error is not justified will be addressed by advanced deadlock detector for MDL subsystem which we plan to implement. mysql-test/include/handler.inc: Adjusted handler_myisam.test and handler_innodb.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/r/handler_innodb.result: Adjusted handler_myisam.test and handler_innodb.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/r/handler_myisam.result: Adjusted handler_myisam.test and handler_innodb.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/r/mdl_sync.result: Adjusted mdl_sync.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/t/mdl_sync.test: Adjusted mdl_sync.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. sql/events.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/ha_ndbcluster.cc: Since manipulations with open table state no longer install proxy MDL_context it does not make sense to perform them in order to satisfy assert in mysql_rm_tables_part2(). Removed them per agreement with Cluster team. This has not broken test suite since scenario in which deadlock can occur and assertion fails is not covered by tests. sql/lock.cc: MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object exclusive metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. sql/log.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/mdl.cc: Changed metadata locking subsystem to use mutex per lock and condition variable per context instead of one mutex and one conditional variable for the whole subsystem. Changed approach to handling of global metadata locks. Instead of implicitly acquiring intention exclusive locks when user requests per-object upgradeable or exclusive locks now we require them to be acquired explicitly in the same way as ordinary metadata locks. In fact global lock are now ordinary metadata locks in new GLOBAL namespace. To implement these changes: - Removed LOCK_mdl mutex and COND_mdl condition variable. - Introduced MDL_lock::m_mutex mutexes which protect individual lock objects. - Replaced mdl_locks hash with MDL_map class, which has hash for MDL_lock objects as a member and separate mutex which protects this hash. Methods of this class allow to find(), find_or_create() or remove() MDL_lock objects in concurrency-friendly fashion (i.e. for most common operation, find_or_create(), we don't acquire MDL_lock::m_mutex while holding MDL_map::m_mutex. Thanks to MikaelR for this idea and benchmarks!). Added three auxiliary members to MDL_lock class (m_is_destroyed, m_ref_usage, m_ref_release) to support this concurrency-friendly behavior. - Introduced MDL_context::m_ctx_wakeup_cond condition variable to be used for waiting until this context's pending request can be satisfied or its thread has to perform actions to resolve potential deadlock. Context which want to wait add ticket corresponding to the request to an appropriate queue of waiters in MDL_lock object so they can be noticed when other contexts change state of lock and be awaken by them by signalling on MDL_context::m_ctx_wakeup_cond. As consequence MDL_ticket objects has to be used for any waiting in metadata locking subsystem including one which happens in MDL_context::wait_for_locks() method. Another consequence is that MDL_context is no longer copyable and can't be saved/restored when working with system tables. - Made MDL_lock an abstract class, which delegates specifying exact compatibility matrix to its descendants. Added MDL_global_lock child class for global lock (The old is_lock_type_compatible() method became can_grant_lock() method of this class). Added MDL_object_lock class to represent per-object lock (The old MDL_lock::can_grant_lock() became its method). Choice between two classes happens based on MDL namespace in MDL_lock::create() method. - Got rid of MDL_lock::type member as its meaning became ambigous for global locks. - To simplify waking up of contexts waiting for lock split waiting queue in MDL_lock class in two queues. One for pending requests for exclusive (including intention exclusive) locks and another for requests for shared locks. - Added virtual wake_up_waiters() method to MDL_lock, MDL_global_lock and MDL_object_lock classes which allows to wake up waiting contexts after state of lock changes. Replaced old duplicated code with calls to this method. - Adjusted MDL_context::try_acquire_shared_lock()/exclusive_lock()/ global_shared_lock(), MDL_ticket::upgrade_shared_lock_to_exclusive_lock() and MDL_context::release_ticket() methods to use MDL_map and MDL_lock::m_mutex instead of single LOCK_mdl mutex and wake up waiters according to the approach described above. The latter method also was renamed to MDL_context::release_lock(). - Changed MDL_context::try_acquire_shared_lock()/exclusive_lock() and release_lock() not to handle global locks. They are now supposed to be taken explicitly like ordinary metadata locks. - Added helper MDL_context::try_acquire_global_intention_exclusive_lock() and acquire_global_intention_exclusive_lock() methods. - Moved common code from MDL_context::acquire_global_shared_lock() and acquire_global_intention_exclusive_lock() to new method - MDL_context::acquire_lock_impl(). - Moved common code from MDL_context::try_acquire_shared_lock(), try_acquire_global_intention_exclusive_lock()/exclusive_lock() to MDL_context::try_acquire_lock_impl(). - Since acquiring of several exclusive locks can no longer happen under single LOCK_mdl mutex the approach to it had to be changed. Now we do it in one by one fashion. This is done in alphabetical order to avoid deadlocks. Changed MDL_context::acquire_exclusive_locks() accordingly (as part of this change moved code responsible for acquiring single exclusive lock to new MDL_context::acquire_exclusive_lock_impl() method). - Since we no longer have single LOCK_mdl mutex which protects all MDL_context::m_is_waiting_in_mdl members using these members to determine if we have really awaken context holding conflicting shared lock became inconvinient. Got rid of this member and changed notify_shared_lock() helper function and process of acquiring of/upgrading to exclusive lock not to rely on such information. Now in MDL_context::acquire_exclusive_lock_impl() and MDL_ticket::upgrade_shared_lock_to_exclusive_lock() we simply re-try to wake up threads holding conflicting shared locks after small time out. - Adjusted MDL_context::can_wait_lead_to_deadlock() and MDL_ticket::has_pending_conflicting_lock() to use per-lock mutexes instead of LOCK_mdl. To do this introduced MDL_lock::has_pending_exclusive_lock() method. sql/mdl.h: Changed metadata locking subsystem to use mutex per lock and condition variable per context instead of one mutex and one conditional variable for the whole subsystem. In order to implement this change: - Added MDL_key::cmp() method to be able to sort MDL_key objects alphabetically. Changed length fields in MDL_key class to uint16 as 16-bit is enough for length of any key. - Changed MDL_ticket::get_ctx() to return pointer to non-const object in order to be able to use MDL_context::awake() method for such contexts. - Got rid of unlocked versions of can_wait_lead_to_deadlock()/ has_pending_conflicting_lock() methods in MDL_context and MDL_ticket. We no longer has single mutex which protects all locks. Thus one always has to use versions of these methods which acquire per-lock mutexes. - MDL_request_list type of list now counts its elements. - Added MDL_context::m_ctx_wakeup_cond condition variable to be used for waiting until this context's pending request can be satisfied or its thread has to perform actions to resolve potential deadlock. Added awake() method to wake up context from such wait. Addition of condition variable made MDL_context uncopyable. As result we no longer can save/restore MDL_context when working with system tables. Instead we create MDL savepoint before opening those tables and rollback to it once they are closed. - MDL_context::release_ticket() became release_lock() method. - Added auxiliary MDL_context::acquire_exclusive_lock_impl() method which does all necessary work to acquire exclusive lock on one object but should not be used directly as it does not enforce any asserts ensuring that no deadlocks are possible. - Since we no longer need to know if thread trying to acquire exclusive lock managed to wake up any threads having conflicting shared locks (as, anyway, we will try to wake up such threads again shortly) - MDL_context::m_is_waiting_in_mdl member became unnecessary and notify_shared_lock() no longer needs to be friend of MDL_context. Changed approach to handling of global metadata locks. Instead of implicitly acquiring intention exclusive locks when user requests per-object upgradeable or exclusive locks now we require them to be acquired explicitly in the same way as ordinary metadata locks. - Added new GLOBAL namespace for such locks. - Added new type of lock to be requested MDL_INTENTION_EXCLISIVE. - Added MDL_context::try_acquire_global_intention_exclusive_lock() and acquire_global_intention_exclusive_lock() methods. - Moved common code from MDL_context::acquire_global_shared_lock() and acquire_global_intention_exclusive_lock() to new method - MDL_context::acquire_lock_impl(). - Moved common code from MDL_context::try_acquire_shared_lock(), try_acquire_global_intention_exclusive_lock()/exclusive_lock() to MDL_context::try_acquire_lock_impl(). - Added helper MDL_context::is_global_lock_owner() method to be able easily to find what kind of global lock this context holds. - MDL_context::m_has_global_shared_lock became unnecessary as global read lock is now represented by ordinary ticket. - Removed assert in MDL_context::set_lt_or_ha_sentinel() which became false for cases when we execute LOCK TABLES under global read lock mode. sql/mysql_priv.h: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result calls opening/closing system tables were changed to use Open_tables_backup instead of Open_table_state class as well. sql/sp.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sp.h: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sql_base.cc: close_thread_tables(): Since we no longer use separate MDL_context for opening system tables we need to avoid releasing all transaction locks when closing system table. Releasing metadata lock on system table is now responsibility of THD::restore_backup_open_tables_state(). open_table_get_mdl_lock(), Open_table_context::recover_from_failed_open(): MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object upgradable or exclusive metadata lock is acquired. So this have to be done explicitly from these calls. Changed Open_table_context class to store MDL_request object for global intention exclusive lock acquired when opening tables. open_table(): Do not release metadata lock if we have failed to open table as this lock might have been acquired by one of previous statements in transaction, and therefore should not be released. open_system_tables_for_read()/close_system_tables()/ open_performance_schema_table(): Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. close_performance_schema_table(): Got rid of duplicated code. sql/sql_class.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. Also releasing metadata lock on system table is now responsibility of THD::restore_backup_open_tables_state(). Adjusted assert in THD::cleanup() to take into account fact that now we also use MDL sentinel for global read lock. sql/sql_class.h: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. As result: - 'mdl_context' member was moved out of Open_tables_state to THD class. enter_locked_tables_mode()/leave_locked_tables_mode() had to follow. - Methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. Changed Open_table_context class to store MDL_request object for global intention exclusive lock acquired when opening tables. sql/sql_delete.cc: MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object exclusive metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. sql/sql_help.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sql_parse.cc: Adjusted assert reload_acl_and_cache() to the fact that global read lock now takes full-blown metadata lock. sql/sql_plist.h: Added support for element counting to I_P_List list template. One can use policy classes to specify if such counting is needed or not needed for particular list. sql/sql_show.cc: Instead of using separate MDL_context for opening tables for I_S purposes we now create MDL savepoint in the main context before opening tables and rollback to this savepoint after closing them. To support this and similar change for system tables methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing tables for I_S purposes was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sql_table.cc: mysql_rm_tables_part2(): Since now global intention exclusive metadata lock is ordinary metadata lock we no longer can rely that by releasing MDL locks on all tables we will release all locks acquired by this routine. So in non-LOCK-TABLES mode we have to release all locks acquired explicitly. prepare_for_repair(), mysql_alter_table(): MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object exclusive metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. sql/tztime.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. Also changed code not to use special mechanism for open system tables when it is not really necessary.
2010-01-21 23:43:03 +03:00
send rename table t0 to t3, t1 to t0, t3 to t1;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo # --> connection con1
connection con1;
Implementation of simple deadlock detection for metadata locks. This change is supposed to reduce number of ER_LOCK_DEADLOCK errors which occur when multi-statement transaction encounters conflicting metadata lock in cases when waiting is possible. The idea is not to fail ER_LOCK_DEADLOCK error immediately when we encounter conflicting metadata lock. Instead we release all metadata locks acquired by current statement and start to wait until conflicting lock go away. To avoid deadlocks we use simple empiric which aborts waiting with ER_LOCK_DEADLOCK error if it turns out that somebody is waiting for metadata locks owned by this transaction. This patch also fixes bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". The bug was that concurrent execution of UPDATE or MULTI-UPDATE statement as a part of multi-statement transaction that already has used table being updated and ALTER TABLE statement might have resulted of loss of isolation between this transaction and ALTER TABLE statement, which manifested itself as changes performed by ALTER TABLE becoming visible in transaction and wrong binary log order as a consequence. This problem occurred when UPDATE or MULTI-UPDATE's wait in mysql_lock_tables() call was aborted due to metadata lock upgrade performed by concurrent ALTER TABLE. After such abort all metadata locks held by transaction were released but transaction silently continued to be executed as if nothing has happened. We solve this problem by changing our code not to release all locks in such case. Instead we release only locks which were acquired by current statement and then try to reacquire them by restarting open/lock tables process. We piggyback on simple deadlock detector implementation since this change has to be done anyway for it. mysql-test/include/handler.inc: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/handler_innodb.result: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/handler_myisam.result: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/mdl_sync.result: Added test coverage for basic deadlock detection in metadata locking subsystem and for bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". mysql-test/r/sp-lock.result: Adjusted test coverage for metadata locking for stored routines since after introduction of basic deadlock detector for metadata locks number of scenarios in which ER_LOCK_DEADLOCK error in absence of deadlock has decreased. mysql-test/t/mdl_sync.test: Added test coverage for basic deadlock detection in metadata locking subsystem and for bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". mysql-test/t/sp-lock.test: Adjusted test coverage for metadata locking for stored routines since after introduction of basic deadlock detector for metadata locks number of scenarios in which ER_LOCK_DEADLOCK error in absence of deadlock has decreased. sql/log_event_old.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/mdl.cc: Changed metadata locking subsystem to support basic deadlock detection with a help of the following simple empiric -- we assume that there is a deadlock if there is a connection which has to wait for a metadata lock which is currently acquired by some connection which is itself waiting to be able to acquire some shared metadata lock. To implement this change: - Added MDL_context::can_wait_lead_to_deadlock()/_impl() methods which allow to find out if there is someone waiting for metadata lock which is held by the connection and therefore deadlocks are possible if this connection is going to wait for some metadata lock. To do this added version of MDL_ticket::has_pending_conflicting_lock() method which assumes that its caller already owns LOCK_mdl mutex. - Changed MDL_context::wait_for_locks() to use one of the above methods to check if somebody is waiting for metadata lock owned by this context (and therefore deadlock is possible) and emit ER_LOCK_DEADLOCK error in this case. Also now we mark context of connections waiting inside of this method by setting MDL_context::m_is_waiting_in_mdl member. Thanks to this such connection could be waken up if some other connection starts waiting for one of its metadata locks and so a deadlock can occur. - Adjusted notify_shared_lock() to wake up connections which wait inside MDL_context::wait_for_locks() while holding shared metadata lock. - Changed MDL_ticket::upgrade_shared_lock_to_exclusive() to add temporary ticket for exclusive lock to MDL_lock::waiting queue, so request for metadata lock upgrade can be properly detected by our empiric. Also now this method invokes a callback which forces transactions holding shared metadata lock on the table to call MDL_context:: can_wait_lead_to_deadlock() method even if they don't need any new metadata locks. Thanks to this such transactions can detect deadlocks/ livelocks between MDL and table-level locks. Also reduced timeouts between calls to notify_shared_lock() in MDL_ticket::upgrade_shared_lock_to_exclusive() and MDL_context::acquire_exclusive_locks(). This was necessary to get rid of call to mysql_lock_abort() in wait_while_table_is_used(). (Now we instead rely on notify_shared_lock() timely calling mysql_lock_abort_for_thread() for the table on which lock is being upgraded/acquired). sql/mdl.h: - Added a version of MDL_ticket::has_pending_conflicting_lock() method to be used in situations when caller already has acquired LOCK_mdl mutex. - Added MDL_context::can_wait_lead_to_deadlock()/_impl() methods which allow to find out if there is someone waiting for metadata lock which is held by this connection and thus deadlocks are possible if this connections will start waiting for some metadata lock. - Added MDL_context::m_is_waiting_in_mdl member to mark connections waiting in MDL_context::wait_for_locks() method of metadata locking subsystem. Added getter method for this private member to make it accessible in notify_shared_lock() auxiliary so we can wake-up such connections if they hold shared metadata locks. - Finally, added mysql_abort_transactions_with_shared_lock() callback to be able force transactions which don't need any new metadata locks still call MDL_context::can_wait_lead_to_deadlock() and detect some of deadlocks between metadata locks and table-level locks. sql/mysql_priv.h: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_base.cc: Changed approach to metadata locking for multi-statement transactions. We no longer fail ER_LOCK_DEADLOCK error immediately when we encounter conflicting metadata lock. Instead we release all metadata locks acquired by current statement and start to wait until conflicting locks to go away by calling MDL_context::wait_for_locks() method. To avoid deadlocks the latter implements simple empiric which aborts waiting with ER_LOCK_DEADLOCK error if it turns out that somebody is waiting for metadata locks owned by this transaction. To implement the change described above: - Introduced Open_table_context::m_start_of_statement_svp member to store state of metadata locks at the start of the statement. - Changed Open_table_context::request_backoff_action() not to fail with ER_LOCK_DEADLOCK immediately if back-off is requested due to conflicting metadata lock. - Added new argument for close_tables_for_reopen() procedure which allows to specify subset of metadata locks to be released. - Changed open_tables() not to release all metadata locks acquired by current transaction when metadata lock conflict is discovered. Instead we release only locks acquired by current statement. - Changed open_ltable() and open_and_lock_tables_derived() not to emit ER_LOCK_DEADLOCK error when mysql_lock_tables() is aborted in multi-statement transaction when somebody tries to acquire exclusive metadata lock on the table. Instead we release metadata locks acquired by current statement and try to wait until they can be re-acquired. - Adjusted tdc_wait_for_old_versions() to check if there is someone waiting for one of metadata locks held by this connection and run deadlock detection in order to avoid deadlocks in some situations. - Added mysql_abort_transactions_with_shared_lock() callback which allows to force transactions holding shared metadata lock on the table to call MDL_context::can_wait_lead_to_deadlock() even if they don't need any new metadata locks so they can detect potential deadlocks between metadata locking subsystem and table-level locks. - Adjusted wait_while_table_is_used() not to set TABLE::version to 0 as it is now done only when necessary by the above-mentioned callback. Also removed unnecessary call to mysql_lock_abort(). Instead we rely on code performing metadata lock upgrade aborting waits on the table-level lock for this table by calling mysql_lock_abort_for_thread() (invoked by mysql_notify_thread_having_shared_lock()). In future this should allow to reduce number of scenarios in which we produce ER_LOCK_DEADLOCK error even though no real deadlock exists. sql/sql_class.h: Introduced Open_table_context::m_start_of_statement_svp member to store state of metadata locks at the start of the statement. Replaced Open_table_context::m_can_deadlock member with m_has_locks member to reflect the fact that we no longer unconditionally emit ER_LOCK_DEADLOCK error for transaction having some metadata locks when conflicting metadata lock is discovered. sql/sql_insert.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_plist.h: Made I_P_List_iterator<T, B> usable with const lists. sql/sql_show.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_update.cc: Changed UPDATE and MULTI-UPDATE code not to release all metadata locks when calls to mysql_lock_tables() are aborted. Instead we release only locks which are acquired by this statement and then try to reacquire them by calling open_tables(). This solves bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER".
2009-12-30 20:53:30 +03:00
--echo # Waiting for 'rename table ...' to get blocked...
let $wait_condition=select count(*)=1 from information_schema.processlist
Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompatible" to be pushed as separate patch. Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. Also replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it more consistent with other thread state names. Updated test cases and their results according to these changes. Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. mysql-test/r/query_cache.result: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/t/query_cache.test: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysys/thr_lock.c: Replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it consistent with thread state names which are used while waiting for metadata locks and table flush. sql/mdl.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/mdl.h: To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/sql_base.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for table flush, with a more elaborate "Waiting for table flush".
2010-08-06 15:29:37 +04:00
where state='Waiting for table metadata lock' and
info='rename table t0 to t3, t1 to t0, t3 to t1';
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--source include/wait_condition.inc
--echo # --> connection default
connection default;
Fix for bug#14188793 - "DEADLOCK CAUSED BY ALTER TABLE DOEN'T CLEAR STATUS OF ROLLBACKED TRANSACTION" and bug #17054007 - "TRANSACTION IS NOT FULLY ROLLED BACK IN CASE OF INNODB DEADLOCK". The problem in the first bug report was that although deadlock involving metadata locks was reported using the same error code and message as InnoDB deadlock it didn't rollback transaction like the latter. This caused confusion to users as in some cases after ER_LOCK_DEADLOCK transaction could have been restarted immediately and in some cases rollback was required. The problem in the second bug report was that although InnoDB deadlock caused transaction rollback in all storage engines it didn't cause release of metadata locks. So concurrent DDL on the tables used in transaction was blocked until implicit or explicit COMMIT or ROLLBACK was issued in the connection which got InnoDB deadlock. The former issue has stemmed from the fact that when support for detection and reporting metadata locks deadlocks was added we erroneously assumed that InnoDB doesn't rollback transaction on deadlock but only last statement (while this is what happens on InnoDB lock timeout actually) and so didn't implement rollback of transactions on MDL deadlocks. The latter issue was caused by the fact that rollback of transaction due to deadlock is carried out by setting THD::transaction_rollback_request flag at the point where deadlock is detected and performing rollback inside of trans_rollback_stmt() call when this flag is set. And trans_rollback_stmt() is not aware of MDL locks, so no MDL locks are released. This patch solves these two problems in the following way: - In case when MDL deadlock is detect transaction rollback is requested by setting THD::transaction_rollback_request flag. - Code performing rollback of transaction if THD::transaction_rollback_request is moved out from trans_rollback_stmt(). Now we handle rollback request on the same level as we call trans_rollback_stmt() and release statement/ transaction MDL locks.
2013-08-20 13:12:34 +04:00
--echo # We back-off on hitting deadlock condition.
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--error ER_LOCK_DEADLOCK
Patch that changes metadata locking subsystem to use mutex per lock and condition variable per context instead of one mutex and one conditional variable for the whole subsystem. This should increase concurrency in this subsystem. It also opens the way for further changes which are necessary to solve such bugs as bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock" and bug #37346 "innodb does not detect deadlock between update and alter table". Two other notable changes done by this patch: - MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. - Instead of using separate MDL_context for opening system tables/tables for purposes of I_S we now create MDL savepoint in the main context before opening tables and rollback to this savepoint after closing them. This means that it is now possible to get ER_LOCK_DEADLOCK error even not inside a transaction. This might happen in unlikely case when one runs DDL on one of system tables while also running DDL on some other tables. Cases when this ER_LOCK_DEADLOCK error is not justified will be addressed by advanced deadlock detector for MDL subsystem which we plan to implement. mysql-test/include/handler.inc: Adjusted handler_myisam.test and handler_innodb.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/r/handler_innodb.result: Adjusted handler_myisam.test and handler_innodb.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/r/handler_myisam.result: Adjusted handler_myisam.test and handler_innodb.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/r/mdl_sync.result: Adjusted mdl_sync.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/t/mdl_sync.test: Adjusted mdl_sync.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. sql/events.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/ha_ndbcluster.cc: Since manipulations with open table state no longer install proxy MDL_context it does not make sense to perform them in order to satisfy assert in mysql_rm_tables_part2(). Removed them per agreement with Cluster team. This has not broken test suite since scenario in which deadlock can occur and assertion fails is not covered by tests. sql/lock.cc: MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object exclusive metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. sql/log.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/mdl.cc: Changed metadata locking subsystem to use mutex per lock and condition variable per context instead of one mutex and one conditional variable for the whole subsystem. Changed approach to handling of global metadata locks. Instead of implicitly acquiring intention exclusive locks when user requests per-object upgradeable or exclusive locks now we require them to be acquired explicitly in the same way as ordinary metadata locks. In fact global lock are now ordinary metadata locks in new GLOBAL namespace. To implement these changes: - Removed LOCK_mdl mutex and COND_mdl condition variable. - Introduced MDL_lock::m_mutex mutexes which protect individual lock objects. - Replaced mdl_locks hash with MDL_map class, which has hash for MDL_lock objects as a member and separate mutex which protects this hash. Methods of this class allow to find(), find_or_create() or remove() MDL_lock objects in concurrency-friendly fashion (i.e. for most common operation, find_or_create(), we don't acquire MDL_lock::m_mutex while holding MDL_map::m_mutex. Thanks to MikaelR for this idea and benchmarks!). Added three auxiliary members to MDL_lock class (m_is_destroyed, m_ref_usage, m_ref_release) to support this concurrency-friendly behavior. - Introduced MDL_context::m_ctx_wakeup_cond condition variable to be used for waiting until this context's pending request can be satisfied or its thread has to perform actions to resolve potential deadlock. Context which want to wait add ticket corresponding to the request to an appropriate queue of waiters in MDL_lock object so they can be noticed when other contexts change state of lock and be awaken by them by signalling on MDL_context::m_ctx_wakeup_cond. As consequence MDL_ticket objects has to be used for any waiting in metadata locking subsystem including one which happens in MDL_context::wait_for_locks() method. Another consequence is that MDL_context is no longer copyable and can't be saved/restored when working with system tables. - Made MDL_lock an abstract class, which delegates specifying exact compatibility matrix to its descendants. Added MDL_global_lock child class for global lock (The old is_lock_type_compatible() method became can_grant_lock() method of this class). Added MDL_object_lock class to represent per-object lock (The old MDL_lock::can_grant_lock() became its method). Choice between two classes happens based on MDL namespace in MDL_lock::create() method. - Got rid of MDL_lock::type member as its meaning became ambigous for global locks. - To simplify waking up of contexts waiting for lock split waiting queue in MDL_lock class in two queues. One for pending requests for exclusive (including intention exclusive) locks and another for requests for shared locks. - Added virtual wake_up_waiters() method to MDL_lock, MDL_global_lock and MDL_object_lock classes which allows to wake up waiting contexts after state of lock changes. Replaced old duplicated code with calls to this method. - Adjusted MDL_context::try_acquire_shared_lock()/exclusive_lock()/ global_shared_lock(), MDL_ticket::upgrade_shared_lock_to_exclusive_lock() and MDL_context::release_ticket() methods to use MDL_map and MDL_lock::m_mutex instead of single LOCK_mdl mutex and wake up waiters according to the approach described above. The latter method also was renamed to MDL_context::release_lock(). - Changed MDL_context::try_acquire_shared_lock()/exclusive_lock() and release_lock() not to handle global locks. They are now supposed to be taken explicitly like ordinary metadata locks. - Added helper MDL_context::try_acquire_global_intention_exclusive_lock() and acquire_global_intention_exclusive_lock() methods. - Moved common code from MDL_context::acquire_global_shared_lock() and acquire_global_intention_exclusive_lock() to new method - MDL_context::acquire_lock_impl(). - Moved common code from MDL_context::try_acquire_shared_lock(), try_acquire_global_intention_exclusive_lock()/exclusive_lock() to MDL_context::try_acquire_lock_impl(). - Since acquiring of several exclusive locks can no longer happen under single LOCK_mdl mutex the approach to it had to be changed. Now we do it in one by one fashion. This is done in alphabetical order to avoid deadlocks. Changed MDL_context::acquire_exclusive_locks() accordingly (as part of this change moved code responsible for acquiring single exclusive lock to new MDL_context::acquire_exclusive_lock_impl() method). - Since we no longer have single LOCK_mdl mutex which protects all MDL_context::m_is_waiting_in_mdl members using these members to determine if we have really awaken context holding conflicting shared lock became inconvinient. Got rid of this member and changed notify_shared_lock() helper function and process of acquiring of/upgrading to exclusive lock not to rely on such information. Now in MDL_context::acquire_exclusive_lock_impl() and MDL_ticket::upgrade_shared_lock_to_exclusive_lock() we simply re-try to wake up threads holding conflicting shared locks after small time out. - Adjusted MDL_context::can_wait_lead_to_deadlock() and MDL_ticket::has_pending_conflicting_lock() to use per-lock mutexes instead of LOCK_mdl. To do this introduced MDL_lock::has_pending_exclusive_lock() method. sql/mdl.h: Changed metadata locking subsystem to use mutex per lock and condition variable per context instead of one mutex and one conditional variable for the whole subsystem. In order to implement this change: - Added MDL_key::cmp() method to be able to sort MDL_key objects alphabetically. Changed length fields in MDL_key class to uint16 as 16-bit is enough for length of any key. - Changed MDL_ticket::get_ctx() to return pointer to non-const object in order to be able to use MDL_context::awake() method for such contexts. - Got rid of unlocked versions of can_wait_lead_to_deadlock()/ has_pending_conflicting_lock() methods in MDL_context and MDL_ticket. We no longer has single mutex which protects all locks. Thus one always has to use versions of these methods which acquire per-lock mutexes. - MDL_request_list type of list now counts its elements. - Added MDL_context::m_ctx_wakeup_cond condition variable to be used for waiting until this context's pending request can be satisfied or its thread has to perform actions to resolve potential deadlock. Added awake() method to wake up context from such wait. Addition of condition variable made MDL_context uncopyable. As result we no longer can save/restore MDL_context when working with system tables. Instead we create MDL savepoint before opening those tables and rollback to it once they are closed. - MDL_context::release_ticket() became release_lock() method. - Added auxiliary MDL_context::acquire_exclusive_lock_impl() method which does all necessary work to acquire exclusive lock on one object but should not be used directly as it does not enforce any asserts ensuring that no deadlocks are possible. - Since we no longer need to know if thread trying to acquire exclusive lock managed to wake up any threads having conflicting shared locks (as, anyway, we will try to wake up such threads again shortly) - MDL_context::m_is_waiting_in_mdl member became unnecessary and notify_shared_lock() no longer needs to be friend of MDL_context. Changed approach to handling of global metadata locks. Instead of implicitly acquiring intention exclusive locks when user requests per-object upgradeable or exclusive locks now we require them to be acquired explicitly in the same way as ordinary metadata locks. - Added new GLOBAL namespace for such locks. - Added new type of lock to be requested MDL_INTENTION_EXCLISIVE. - Added MDL_context::try_acquire_global_intention_exclusive_lock() and acquire_global_intention_exclusive_lock() methods. - Moved common code from MDL_context::acquire_global_shared_lock() and acquire_global_intention_exclusive_lock() to new method - MDL_context::acquire_lock_impl(). - Moved common code from MDL_context::try_acquire_shared_lock(), try_acquire_global_intention_exclusive_lock()/exclusive_lock() to MDL_context::try_acquire_lock_impl(). - Added helper MDL_context::is_global_lock_owner() method to be able easily to find what kind of global lock this context holds. - MDL_context::m_has_global_shared_lock became unnecessary as global read lock is now represented by ordinary ticket. - Removed assert in MDL_context::set_lt_or_ha_sentinel() which became false for cases when we execute LOCK TABLES under global read lock mode. sql/mysql_priv.h: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result calls opening/closing system tables were changed to use Open_tables_backup instead of Open_table_state class as well. sql/sp.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sp.h: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sql_base.cc: close_thread_tables(): Since we no longer use separate MDL_context for opening system tables we need to avoid releasing all transaction locks when closing system table. Releasing metadata lock on system table is now responsibility of THD::restore_backup_open_tables_state(). open_table_get_mdl_lock(), Open_table_context::recover_from_failed_open(): MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object upgradable or exclusive metadata lock is acquired. So this have to be done explicitly from these calls. Changed Open_table_context class to store MDL_request object for global intention exclusive lock acquired when opening tables. open_table(): Do not release metadata lock if we have failed to open table as this lock might have been acquired by one of previous statements in transaction, and therefore should not be released. open_system_tables_for_read()/close_system_tables()/ open_performance_schema_table(): Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. close_performance_schema_table(): Got rid of duplicated code. sql/sql_class.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. Also releasing metadata lock on system table is now responsibility of THD::restore_backup_open_tables_state(). Adjusted assert in THD::cleanup() to take into account fact that now we also use MDL sentinel for global read lock. sql/sql_class.h: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. As result: - 'mdl_context' member was moved out of Open_tables_state to THD class. enter_locked_tables_mode()/leave_locked_tables_mode() had to follow. - Methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. Changed Open_table_context class to store MDL_request object for global intention exclusive lock acquired when opening tables. sql/sql_delete.cc: MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object exclusive metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. sql/sql_help.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sql_parse.cc: Adjusted assert reload_acl_and_cache() to the fact that global read lock now takes full-blown metadata lock. sql/sql_plist.h: Added support for element counting to I_P_List list template. One can use policy classes to specify if such counting is needed or not needed for particular list. sql/sql_show.cc: Instead of using separate MDL_context for opening tables for I_S purposes we now create MDL savepoint in the main context before opening tables and rollback to this savepoint after closing them. To support this and similar change for system tables methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing tables for I_S purposes was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sql_table.cc: mysql_rm_tables_part2(): Since now global intention exclusive metadata lock is ordinary metadata lock we no longer can rely that by releasing MDL locks on all tables we will release all locks acquired by this routine. So in non-LOCK-TABLES mode we have to release all locks acquired explicitly. prepare_for_repair(), mysql_alter_table(): MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object exclusive metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. sql/tztime.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. Also changed code not to use special mechanism for open system tables when it is not really necessary.
2010-01-21 23:43:03 +03:00
handler t0 open;
select * from t0;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
handler t1 open;
commit;
handler t1 close;
--echo # --> connection con2
connection con2;
Implementation of simple deadlock detection for metadata locks. This change is supposed to reduce number of ER_LOCK_DEADLOCK errors which occur when multi-statement transaction encounters conflicting metadata lock in cases when waiting is possible. The idea is not to fail ER_LOCK_DEADLOCK error immediately when we encounter conflicting metadata lock. Instead we release all metadata locks acquired by current statement and start to wait until conflicting lock go away. To avoid deadlocks we use simple empiric which aborts waiting with ER_LOCK_DEADLOCK error if it turns out that somebody is waiting for metadata locks owned by this transaction. This patch also fixes bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". The bug was that concurrent execution of UPDATE or MULTI-UPDATE statement as a part of multi-statement transaction that already has used table being updated and ALTER TABLE statement might have resulted of loss of isolation between this transaction and ALTER TABLE statement, which manifested itself as changes performed by ALTER TABLE becoming visible in transaction and wrong binary log order as a consequence. This problem occurred when UPDATE or MULTI-UPDATE's wait in mysql_lock_tables() call was aborted due to metadata lock upgrade performed by concurrent ALTER TABLE. After such abort all metadata locks held by transaction were released but transaction silently continued to be executed as if nothing has happened. We solve this problem by changing our code not to release all locks in such case. Instead we release only locks which were acquired by current statement and then try to reacquire them by restarting open/lock tables process. We piggyback on simple deadlock detector implementation since this change has to be done anyway for it. mysql-test/include/handler.inc: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/handler_innodb.result: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/handler_myisam.result: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/mdl_sync.result: Added test coverage for basic deadlock detection in metadata locking subsystem and for bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". mysql-test/r/sp-lock.result: Adjusted test coverage for metadata locking for stored routines since after introduction of basic deadlock detector for metadata locks number of scenarios in which ER_LOCK_DEADLOCK error in absence of deadlock has decreased. mysql-test/t/mdl_sync.test: Added test coverage for basic deadlock detection in metadata locking subsystem and for bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". mysql-test/t/sp-lock.test: Adjusted test coverage for metadata locking for stored routines since after introduction of basic deadlock detector for metadata locks number of scenarios in which ER_LOCK_DEADLOCK error in absence of deadlock has decreased. sql/log_event_old.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/mdl.cc: Changed metadata locking subsystem to support basic deadlock detection with a help of the following simple empiric -- we assume that there is a deadlock if there is a connection which has to wait for a metadata lock which is currently acquired by some connection which is itself waiting to be able to acquire some shared metadata lock. To implement this change: - Added MDL_context::can_wait_lead_to_deadlock()/_impl() methods which allow to find out if there is someone waiting for metadata lock which is held by the connection and therefore deadlocks are possible if this connection is going to wait for some metadata lock. To do this added version of MDL_ticket::has_pending_conflicting_lock() method which assumes that its caller already owns LOCK_mdl mutex. - Changed MDL_context::wait_for_locks() to use one of the above methods to check if somebody is waiting for metadata lock owned by this context (and therefore deadlock is possible) and emit ER_LOCK_DEADLOCK error in this case. Also now we mark context of connections waiting inside of this method by setting MDL_context::m_is_waiting_in_mdl member. Thanks to this such connection could be waken up if some other connection starts waiting for one of its metadata locks and so a deadlock can occur. - Adjusted notify_shared_lock() to wake up connections which wait inside MDL_context::wait_for_locks() while holding shared metadata lock. - Changed MDL_ticket::upgrade_shared_lock_to_exclusive() to add temporary ticket for exclusive lock to MDL_lock::waiting queue, so request for metadata lock upgrade can be properly detected by our empiric. Also now this method invokes a callback which forces transactions holding shared metadata lock on the table to call MDL_context:: can_wait_lead_to_deadlock() method even if they don't need any new metadata locks. Thanks to this such transactions can detect deadlocks/ livelocks between MDL and table-level locks. Also reduced timeouts between calls to notify_shared_lock() in MDL_ticket::upgrade_shared_lock_to_exclusive() and MDL_context::acquire_exclusive_locks(). This was necessary to get rid of call to mysql_lock_abort() in wait_while_table_is_used(). (Now we instead rely on notify_shared_lock() timely calling mysql_lock_abort_for_thread() for the table on which lock is being upgraded/acquired). sql/mdl.h: - Added a version of MDL_ticket::has_pending_conflicting_lock() method to be used in situations when caller already has acquired LOCK_mdl mutex. - Added MDL_context::can_wait_lead_to_deadlock()/_impl() methods which allow to find out if there is someone waiting for metadata lock which is held by this connection and thus deadlocks are possible if this connections will start waiting for some metadata lock. - Added MDL_context::m_is_waiting_in_mdl member to mark connections waiting in MDL_context::wait_for_locks() method of metadata locking subsystem. Added getter method for this private member to make it accessible in notify_shared_lock() auxiliary so we can wake-up such connections if they hold shared metadata locks. - Finally, added mysql_abort_transactions_with_shared_lock() callback to be able force transactions which don't need any new metadata locks still call MDL_context::can_wait_lead_to_deadlock() and detect some of deadlocks between metadata locks and table-level locks. sql/mysql_priv.h: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_base.cc: Changed approach to metadata locking for multi-statement transactions. We no longer fail ER_LOCK_DEADLOCK error immediately when we encounter conflicting metadata lock. Instead we release all metadata locks acquired by current statement and start to wait until conflicting locks to go away by calling MDL_context::wait_for_locks() method. To avoid deadlocks the latter implements simple empiric which aborts waiting with ER_LOCK_DEADLOCK error if it turns out that somebody is waiting for metadata locks owned by this transaction. To implement the change described above: - Introduced Open_table_context::m_start_of_statement_svp member to store state of metadata locks at the start of the statement. - Changed Open_table_context::request_backoff_action() not to fail with ER_LOCK_DEADLOCK immediately if back-off is requested due to conflicting metadata lock. - Added new argument for close_tables_for_reopen() procedure which allows to specify subset of metadata locks to be released. - Changed open_tables() not to release all metadata locks acquired by current transaction when metadata lock conflict is discovered. Instead we release only locks acquired by current statement. - Changed open_ltable() and open_and_lock_tables_derived() not to emit ER_LOCK_DEADLOCK error when mysql_lock_tables() is aborted in multi-statement transaction when somebody tries to acquire exclusive metadata lock on the table. Instead we release metadata locks acquired by current statement and try to wait until they can be re-acquired. - Adjusted tdc_wait_for_old_versions() to check if there is someone waiting for one of metadata locks held by this connection and run deadlock detection in order to avoid deadlocks in some situations. - Added mysql_abort_transactions_with_shared_lock() callback which allows to force transactions holding shared metadata lock on the table to call MDL_context::can_wait_lead_to_deadlock() even if they don't need any new metadata locks so they can detect potential deadlocks between metadata locking subsystem and table-level locks. - Adjusted wait_while_table_is_used() not to set TABLE::version to 0 as it is now done only when necessary by the above-mentioned callback. Also removed unnecessary call to mysql_lock_abort(). Instead we rely on code performing metadata lock upgrade aborting waits on the table-level lock for this table by calling mysql_lock_abort_for_thread() (invoked by mysql_notify_thread_having_shared_lock()). In future this should allow to reduce number of scenarios in which we produce ER_LOCK_DEADLOCK error even though no real deadlock exists. sql/sql_class.h: Introduced Open_table_context::m_start_of_statement_svp member to store state of metadata locks at the start of the statement. Replaced Open_table_context::m_can_deadlock member with m_has_locks member to reflect the fact that we no longer unconditionally emit ER_LOCK_DEADLOCK error for transaction having some metadata locks when conflicting metadata lock is discovered. sql/sql_insert.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_plist.h: Made I_P_List_iterator<T, B> usable with const lists. sql/sql_show.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_update.cc: Changed UPDATE and MULTI-UPDATE code not to release all metadata locks when calls to mysql_lock_tables() are aborted. Instead we release only locks which are acquired by this statement and then try to reacquire them by calling open_tables(). This solves bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER".
2009-12-30 20:53:30 +03:00
--echo # Reaping 'rename table ...'...
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--reap
--echo # --> connection default
connection default;
handler t1 open;
handler t1 read a prev;
handler t1 close;
Patch that changes metadata locking subsystem to use mutex per lock and condition variable per context instead of one mutex and one conditional variable for the whole subsystem. This should increase concurrency in this subsystem. It also opens the way for further changes which are necessary to solve such bugs as bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock" and bug #37346 "innodb does not detect deadlock between update and alter table". Two other notable changes done by this patch: - MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. - Instead of using separate MDL_context for opening system tables/tables for purposes of I_S we now create MDL savepoint in the main context before opening tables and rollback to this savepoint after closing them. This means that it is now possible to get ER_LOCK_DEADLOCK error even not inside a transaction. This might happen in unlikely case when one runs DDL on one of system tables while also running DDL on some other tables. Cases when this ER_LOCK_DEADLOCK error is not justified will be addressed by advanced deadlock detector for MDL subsystem which we plan to implement. mysql-test/include/handler.inc: Adjusted handler_myisam.test and handler_innodb.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/r/handler_innodb.result: Adjusted handler_myisam.test and handler_innodb.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/r/handler_myisam.result: Adjusted handler_myisam.test and handler_innodb.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/r/mdl_sync.result: Adjusted mdl_sync.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. mysql-test/t/mdl_sync.test: Adjusted mdl_sync.test to the fact that exclusive metadata locks on tables are now acquired according to alphabetical order of fully qualified table names instead of order in which tables are mentioned in statement. sql/events.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/ha_ndbcluster.cc: Since manipulations with open table state no longer install proxy MDL_context it does not make sense to perform them in order to satisfy assert in mysql_rm_tables_part2(). Removed them per agreement with Cluster team. This has not broken test suite since scenario in which deadlock can occur and assertion fails is not covered by tests. sql/lock.cc: MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object exclusive metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. sql/log.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/mdl.cc: Changed metadata locking subsystem to use mutex per lock and condition variable per context instead of one mutex and one conditional variable for the whole subsystem. Changed approach to handling of global metadata locks. Instead of implicitly acquiring intention exclusive locks when user requests per-object upgradeable or exclusive locks now we require them to be acquired explicitly in the same way as ordinary metadata locks. In fact global lock are now ordinary metadata locks in new GLOBAL namespace. To implement these changes: - Removed LOCK_mdl mutex and COND_mdl condition variable. - Introduced MDL_lock::m_mutex mutexes which protect individual lock objects. - Replaced mdl_locks hash with MDL_map class, which has hash for MDL_lock objects as a member and separate mutex which protects this hash. Methods of this class allow to find(), find_or_create() or remove() MDL_lock objects in concurrency-friendly fashion (i.e. for most common operation, find_or_create(), we don't acquire MDL_lock::m_mutex while holding MDL_map::m_mutex. Thanks to MikaelR for this idea and benchmarks!). Added three auxiliary members to MDL_lock class (m_is_destroyed, m_ref_usage, m_ref_release) to support this concurrency-friendly behavior. - Introduced MDL_context::m_ctx_wakeup_cond condition variable to be used for waiting until this context's pending request can be satisfied or its thread has to perform actions to resolve potential deadlock. Context which want to wait add ticket corresponding to the request to an appropriate queue of waiters in MDL_lock object so they can be noticed when other contexts change state of lock and be awaken by them by signalling on MDL_context::m_ctx_wakeup_cond. As consequence MDL_ticket objects has to be used for any waiting in metadata locking subsystem including one which happens in MDL_context::wait_for_locks() method. Another consequence is that MDL_context is no longer copyable and can't be saved/restored when working with system tables. - Made MDL_lock an abstract class, which delegates specifying exact compatibility matrix to its descendants. Added MDL_global_lock child class for global lock (The old is_lock_type_compatible() method became can_grant_lock() method of this class). Added MDL_object_lock class to represent per-object lock (The old MDL_lock::can_grant_lock() became its method). Choice between two classes happens based on MDL namespace in MDL_lock::create() method. - Got rid of MDL_lock::type member as its meaning became ambigous for global locks. - To simplify waking up of contexts waiting for lock split waiting queue in MDL_lock class in two queues. One for pending requests for exclusive (including intention exclusive) locks and another for requests for shared locks. - Added virtual wake_up_waiters() method to MDL_lock, MDL_global_lock and MDL_object_lock classes which allows to wake up waiting contexts after state of lock changes. Replaced old duplicated code with calls to this method. - Adjusted MDL_context::try_acquire_shared_lock()/exclusive_lock()/ global_shared_lock(), MDL_ticket::upgrade_shared_lock_to_exclusive_lock() and MDL_context::release_ticket() methods to use MDL_map and MDL_lock::m_mutex instead of single LOCK_mdl mutex and wake up waiters according to the approach described above. The latter method also was renamed to MDL_context::release_lock(). - Changed MDL_context::try_acquire_shared_lock()/exclusive_lock() and release_lock() not to handle global locks. They are now supposed to be taken explicitly like ordinary metadata locks. - Added helper MDL_context::try_acquire_global_intention_exclusive_lock() and acquire_global_intention_exclusive_lock() methods. - Moved common code from MDL_context::acquire_global_shared_lock() and acquire_global_intention_exclusive_lock() to new method - MDL_context::acquire_lock_impl(). - Moved common code from MDL_context::try_acquire_shared_lock(), try_acquire_global_intention_exclusive_lock()/exclusive_lock() to MDL_context::try_acquire_lock_impl(). - Since acquiring of several exclusive locks can no longer happen under single LOCK_mdl mutex the approach to it had to be changed. Now we do it in one by one fashion. This is done in alphabetical order to avoid deadlocks. Changed MDL_context::acquire_exclusive_locks() accordingly (as part of this change moved code responsible for acquiring single exclusive lock to new MDL_context::acquire_exclusive_lock_impl() method). - Since we no longer have single LOCK_mdl mutex which protects all MDL_context::m_is_waiting_in_mdl members using these members to determine if we have really awaken context holding conflicting shared lock became inconvinient. Got rid of this member and changed notify_shared_lock() helper function and process of acquiring of/upgrading to exclusive lock not to rely on such information. Now in MDL_context::acquire_exclusive_lock_impl() and MDL_ticket::upgrade_shared_lock_to_exclusive_lock() we simply re-try to wake up threads holding conflicting shared locks after small time out. - Adjusted MDL_context::can_wait_lead_to_deadlock() and MDL_ticket::has_pending_conflicting_lock() to use per-lock mutexes instead of LOCK_mdl. To do this introduced MDL_lock::has_pending_exclusive_lock() method. sql/mdl.h: Changed metadata locking subsystem to use mutex per lock and condition variable per context instead of one mutex and one conditional variable for the whole subsystem. In order to implement this change: - Added MDL_key::cmp() method to be able to sort MDL_key objects alphabetically. Changed length fields in MDL_key class to uint16 as 16-bit is enough for length of any key. - Changed MDL_ticket::get_ctx() to return pointer to non-const object in order to be able to use MDL_context::awake() method for such contexts. - Got rid of unlocked versions of can_wait_lead_to_deadlock()/ has_pending_conflicting_lock() methods in MDL_context and MDL_ticket. We no longer has single mutex which protects all locks. Thus one always has to use versions of these methods which acquire per-lock mutexes. - MDL_request_list type of list now counts its elements. - Added MDL_context::m_ctx_wakeup_cond condition variable to be used for waiting until this context's pending request can be satisfied or its thread has to perform actions to resolve potential deadlock. Added awake() method to wake up context from such wait. Addition of condition variable made MDL_context uncopyable. As result we no longer can save/restore MDL_context when working with system tables. Instead we create MDL savepoint before opening those tables and rollback to it once they are closed. - MDL_context::release_ticket() became release_lock() method. - Added auxiliary MDL_context::acquire_exclusive_lock_impl() method which does all necessary work to acquire exclusive lock on one object but should not be used directly as it does not enforce any asserts ensuring that no deadlocks are possible. - Since we no longer need to know if thread trying to acquire exclusive lock managed to wake up any threads having conflicting shared locks (as, anyway, we will try to wake up such threads again shortly) - MDL_context::m_is_waiting_in_mdl member became unnecessary and notify_shared_lock() no longer needs to be friend of MDL_context. Changed approach to handling of global metadata locks. Instead of implicitly acquiring intention exclusive locks when user requests per-object upgradeable or exclusive locks now we require them to be acquired explicitly in the same way as ordinary metadata locks. - Added new GLOBAL namespace for such locks. - Added new type of lock to be requested MDL_INTENTION_EXCLISIVE. - Added MDL_context::try_acquire_global_intention_exclusive_lock() and acquire_global_intention_exclusive_lock() methods. - Moved common code from MDL_context::acquire_global_shared_lock() and acquire_global_intention_exclusive_lock() to new method - MDL_context::acquire_lock_impl(). - Moved common code from MDL_context::try_acquire_shared_lock(), try_acquire_global_intention_exclusive_lock()/exclusive_lock() to MDL_context::try_acquire_lock_impl(). - Added helper MDL_context::is_global_lock_owner() method to be able easily to find what kind of global lock this context holds. - MDL_context::m_has_global_shared_lock became unnecessary as global read lock is now represented by ordinary ticket. - Removed assert in MDL_context::set_lt_or_ha_sentinel() which became false for cases when we execute LOCK TABLES under global read lock mode. sql/mysql_priv.h: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result calls opening/closing system tables were changed to use Open_tables_backup instead of Open_table_state class as well. sql/sp.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sp.h: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sql_base.cc: close_thread_tables(): Since we no longer use separate MDL_context for opening system tables we need to avoid releasing all transaction locks when closing system table. Releasing metadata lock on system table is now responsibility of THD::restore_backup_open_tables_state(). open_table_get_mdl_lock(), Open_table_context::recover_from_failed_open(): MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object upgradable or exclusive metadata lock is acquired. So this have to be done explicitly from these calls. Changed Open_table_context class to store MDL_request object for global intention exclusive lock acquired when opening tables. open_table(): Do not release metadata lock if we have failed to open table as this lock might have been acquired by one of previous statements in transaction, and therefore should not be released. open_system_tables_for_read()/close_system_tables()/ open_performance_schema_table(): Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. close_performance_schema_table(): Got rid of duplicated code. sql/sql_class.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. Also releasing metadata lock on system table is now responsibility of THD::restore_backup_open_tables_state(). Adjusted assert in THD::cleanup() to take into account fact that now we also use MDL sentinel for global read lock. sql/sql_class.h: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. As result: - 'mdl_context' member was moved out of Open_tables_state to THD class. enter_locked_tables_mode()/leave_locked_tables_mode() had to follow. - Methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. Changed Open_table_context class to store MDL_request object for global intention exclusive lock acquired when opening tables. sql/sql_delete.cc: MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object exclusive metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. sql/sql_help.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sql_parse.cc: Adjusted assert reload_acl_and_cache() to the fact that global read lock now takes full-blown metadata lock. sql/sql_plist.h: Added support for element counting to I_P_List list template. One can use policy classes to specify if such counting is needed or not needed for particular list. sql/sql_show.cc: Instead of using separate MDL_context for opening tables for I_S purposes we now create MDL savepoint in the main context before opening tables and rollback to this savepoint after closing them. To support this and similar change for system tables methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing tables for I_S purposes was changed to use Open_tables_backup instead of Open_table_state class as well. sql/sql_table.cc: mysql_rm_tables_part2(): Since now global intention exclusive metadata lock is ordinary metadata lock we no longer can rely that by releasing MDL locks on all tables we will release all locks acquired by this routine. So in non-LOCK-TABLES mode we have to release all locks acquired explicitly. prepare_for_repair(), mysql_alter_table(): MDL subsystem no longer implicitly acquires global intention exclusive metadata lock when per-object exclusive metadata lock is acquired. Now this has to be done by explicit calls outside of MDL subsystem. sql/tztime.cc: Instead of using separate MDL_context for opening system tables we now create MDL savepoint in the main context before opening such tables and rollback to this savepoint after closing them. To support this change methods of THD responsible for saving/restoring open table state were changed to use Open_tables_backup class which in addition to Open_table_state has a member for this savepoint. As result code opening/closing system tables was changed to use Open_tables_backup instead of Open_table_state class as well. Also changed code not to use special mechanism for open system tables when it is not really necessary.
2010-01-21 23:43:03 +03:00
drop table t0;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo #
Implementation of simple deadlock detection for metadata locks. This change is supposed to reduce number of ER_LOCK_DEADLOCK errors which occur when multi-statement transaction encounters conflicting metadata lock in cases when waiting is possible. The idea is not to fail ER_LOCK_DEADLOCK error immediately when we encounter conflicting metadata lock. Instead we release all metadata locks acquired by current statement and start to wait until conflicting lock go away. To avoid deadlocks we use simple empiric which aborts waiting with ER_LOCK_DEADLOCK error if it turns out that somebody is waiting for metadata locks owned by this transaction. This patch also fixes bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". The bug was that concurrent execution of UPDATE or MULTI-UPDATE statement as a part of multi-statement transaction that already has used table being updated and ALTER TABLE statement might have resulted of loss of isolation between this transaction and ALTER TABLE statement, which manifested itself as changes performed by ALTER TABLE becoming visible in transaction and wrong binary log order as a consequence. This problem occurred when UPDATE or MULTI-UPDATE's wait in mysql_lock_tables() call was aborted due to metadata lock upgrade performed by concurrent ALTER TABLE. After such abort all metadata locks held by transaction were released but transaction silently continued to be executed as if nothing has happened. We solve this problem by changing our code not to release all locks in such case. Instead we release only locks which were acquired by current statement and then try to reacquire them by restarting open/lock tables process. We piggyback on simple deadlock detector implementation since this change has to be done anyway for it. mysql-test/include/handler.inc: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/handler_innodb.result: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/handler_myisam.result: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/mdl_sync.result: Added test coverage for basic deadlock detection in metadata locking subsystem and for bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". mysql-test/r/sp-lock.result: Adjusted test coverage for metadata locking for stored routines since after introduction of basic deadlock detector for metadata locks number of scenarios in which ER_LOCK_DEADLOCK error in absence of deadlock has decreased. mysql-test/t/mdl_sync.test: Added test coverage for basic deadlock detection in metadata locking subsystem and for bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". mysql-test/t/sp-lock.test: Adjusted test coverage for metadata locking for stored routines since after introduction of basic deadlock detector for metadata locks number of scenarios in which ER_LOCK_DEADLOCK error in absence of deadlock has decreased. sql/log_event_old.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/mdl.cc: Changed metadata locking subsystem to support basic deadlock detection with a help of the following simple empiric -- we assume that there is a deadlock if there is a connection which has to wait for a metadata lock which is currently acquired by some connection which is itself waiting to be able to acquire some shared metadata lock. To implement this change: - Added MDL_context::can_wait_lead_to_deadlock()/_impl() methods which allow to find out if there is someone waiting for metadata lock which is held by the connection and therefore deadlocks are possible if this connection is going to wait for some metadata lock. To do this added version of MDL_ticket::has_pending_conflicting_lock() method which assumes that its caller already owns LOCK_mdl mutex. - Changed MDL_context::wait_for_locks() to use one of the above methods to check if somebody is waiting for metadata lock owned by this context (and therefore deadlock is possible) and emit ER_LOCK_DEADLOCK error in this case. Also now we mark context of connections waiting inside of this method by setting MDL_context::m_is_waiting_in_mdl member. Thanks to this such connection could be waken up if some other connection starts waiting for one of its metadata locks and so a deadlock can occur. - Adjusted notify_shared_lock() to wake up connections which wait inside MDL_context::wait_for_locks() while holding shared metadata lock. - Changed MDL_ticket::upgrade_shared_lock_to_exclusive() to add temporary ticket for exclusive lock to MDL_lock::waiting queue, so request for metadata lock upgrade can be properly detected by our empiric. Also now this method invokes a callback which forces transactions holding shared metadata lock on the table to call MDL_context:: can_wait_lead_to_deadlock() method even if they don't need any new metadata locks. Thanks to this such transactions can detect deadlocks/ livelocks between MDL and table-level locks. Also reduced timeouts between calls to notify_shared_lock() in MDL_ticket::upgrade_shared_lock_to_exclusive() and MDL_context::acquire_exclusive_locks(). This was necessary to get rid of call to mysql_lock_abort() in wait_while_table_is_used(). (Now we instead rely on notify_shared_lock() timely calling mysql_lock_abort_for_thread() for the table on which lock is being upgraded/acquired). sql/mdl.h: - Added a version of MDL_ticket::has_pending_conflicting_lock() method to be used in situations when caller already has acquired LOCK_mdl mutex. - Added MDL_context::can_wait_lead_to_deadlock()/_impl() methods which allow to find out if there is someone waiting for metadata lock which is held by this connection and thus deadlocks are possible if this connections will start waiting for some metadata lock. - Added MDL_context::m_is_waiting_in_mdl member to mark connections waiting in MDL_context::wait_for_locks() method of metadata locking subsystem. Added getter method for this private member to make it accessible in notify_shared_lock() auxiliary so we can wake-up such connections if they hold shared metadata locks. - Finally, added mysql_abort_transactions_with_shared_lock() callback to be able force transactions which don't need any new metadata locks still call MDL_context::can_wait_lead_to_deadlock() and detect some of deadlocks between metadata locks and table-level locks. sql/mysql_priv.h: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_base.cc: Changed approach to metadata locking for multi-statement transactions. We no longer fail ER_LOCK_DEADLOCK error immediately when we encounter conflicting metadata lock. Instead we release all metadata locks acquired by current statement and start to wait until conflicting locks to go away by calling MDL_context::wait_for_locks() method. To avoid deadlocks the latter implements simple empiric which aborts waiting with ER_LOCK_DEADLOCK error if it turns out that somebody is waiting for metadata locks owned by this transaction. To implement the change described above: - Introduced Open_table_context::m_start_of_statement_svp member to store state of metadata locks at the start of the statement. - Changed Open_table_context::request_backoff_action() not to fail with ER_LOCK_DEADLOCK immediately if back-off is requested due to conflicting metadata lock. - Added new argument for close_tables_for_reopen() procedure which allows to specify subset of metadata locks to be released. - Changed open_tables() not to release all metadata locks acquired by current transaction when metadata lock conflict is discovered. Instead we release only locks acquired by current statement. - Changed open_ltable() and open_and_lock_tables_derived() not to emit ER_LOCK_DEADLOCK error when mysql_lock_tables() is aborted in multi-statement transaction when somebody tries to acquire exclusive metadata lock on the table. Instead we release metadata locks acquired by current statement and try to wait until they can be re-acquired. - Adjusted tdc_wait_for_old_versions() to check if there is someone waiting for one of metadata locks held by this connection and run deadlock detection in order to avoid deadlocks in some situations. - Added mysql_abort_transactions_with_shared_lock() callback which allows to force transactions holding shared metadata lock on the table to call MDL_context::can_wait_lead_to_deadlock() even if they don't need any new metadata locks so they can detect potential deadlocks between metadata locking subsystem and table-level locks. - Adjusted wait_while_table_is_used() not to set TABLE::version to 0 as it is now done only when necessary by the above-mentioned callback. Also removed unnecessary call to mysql_lock_abort(). Instead we rely on code performing metadata lock upgrade aborting waits on the table-level lock for this table by calling mysql_lock_abort_for_thread() (invoked by mysql_notify_thread_having_shared_lock()). In future this should allow to reduce number of scenarios in which we produce ER_LOCK_DEADLOCK error even though no real deadlock exists. sql/sql_class.h: Introduced Open_table_context::m_start_of_statement_svp member to store state of metadata locks at the start of the statement. Replaced Open_table_context::m_can_deadlock member with m_has_locks member to reflect the fact that we no longer unconditionally emit ER_LOCK_DEADLOCK error for transaction having some metadata locks when conflicting metadata lock is discovered. sql/sql_insert.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_plist.h: Made I_P_List_iterator<T, B> usable with const lists. sql/sql_show.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_update.cc: Changed UPDATE and MULTI-UPDATE code not to release all metadata locks when calls to mysql_lock_tables() are aborted. Instead we release only locks which are acquired by this statement and then try to reacquire them by calling open_tables(). This solves bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER".
2009-12-30 20:53:30 +03:00
--echo # Originally there was a deadlock error in this test.
--echo # With implementation of deadlock detector
--echo # we no longer deadlock, but block and wait on a lock.
--echo # The HANDLER is auto-closed as soon as the connection
--echo # sees a pending conflicting lock against it.
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo #
create table t2 (a int, key a (a));
handler t1 open;
--echo # --> connection con1
connection con1;
lock tables t2 read;
--echo # --> connection con2
connection con2;
--echo # Sending 'drop table t2'...
--send drop table t2
--echo # --> connection con1
connection con1;
--echo # Waiting for 'drop table t2' to get blocked...
Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompatible" to be pushed as separate patch. Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. Also replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it more consistent with other thread state names. Updated test cases and their results according to these changes. Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. mysql-test/r/query_cache.result: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/t/query_cache.test: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysys/thr_lock.c: Replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it consistent with thread state names which are used while waiting for metadata locks and table flush. sql/mdl.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/mdl.h: To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/sql_base.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for table flush, with a more elaborate "Waiting for table flush".
2010-08-06 15:29:37 +04:00
let $wait_condition=select count(*)=1 from information_schema.processlist
where state='Waiting for table metadata lock' and
info='drop table t2';
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--source include/wait_condition.inc
--echo # --> connection default
connection default;
Implementation of simple deadlock detection for metadata locks. This change is supposed to reduce number of ER_LOCK_DEADLOCK errors which occur when multi-statement transaction encounters conflicting metadata lock in cases when waiting is possible. The idea is not to fail ER_LOCK_DEADLOCK error immediately when we encounter conflicting metadata lock. Instead we release all metadata locks acquired by current statement and start to wait until conflicting lock go away. To avoid deadlocks we use simple empiric which aborts waiting with ER_LOCK_DEADLOCK error if it turns out that somebody is waiting for metadata locks owned by this transaction. This patch also fixes bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". The bug was that concurrent execution of UPDATE or MULTI-UPDATE statement as a part of multi-statement transaction that already has used table being updated and ALTER TABLE statement might have resulted of loss of isolation between this transaction and ALTER TABLE statement, which manifested itself as changes performed by ALTER TABLE becoming visible in transaction and wrong binary log order as a consequence. This problem occurred when UPDATE or MULTI-UPDATE's wait in mysql_lock_tables() call was aborted due to metadata lock upgrade performed by concurrent ALTER TABLE. After such abort all metadata locks held by transaction were released but transaction silently continued to be executed as if nothing has happened. We solve this problem by changing our code not to release all locks in such case. Instead we release only locks which were acquired by current statement and then try to reacquire them by restarting open/lock tables process. We piggyback on simple deadlock detector implementation since this change has to be done anyway for it. mysql-test/include/handler.inc: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/handler_innodb.result: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/handler_myisam.result: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/mdl_sync.result: Added test coverage for basic deadlock detection in metadata locking subsystem and for bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". mysql-test/r/sp-lock.result: Adjusted test coverage for metadata locking for stored routines since after introduction of basic deadlock detector for metadata locks number of scenarios in which ER_LOCK_DEADLOCK error in absence of deadlock has decreased. mysql-test/t/mdl_sync.test: Added test coverage for basic deadlock detection in metadata locking subsystem and for bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". mysql-test/t/sp-lock.test: Adjusted test coverage for metadata locking for stored routines since after introduction of basic deadlock detector for metadata locks number of scenarios in which ER_LOCK_DEADLOCK error in absence of deadlock has decreased. sql/log_event_old.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/mdl.cc: Changed metadata locking subsystem to support basic deadlock detection with a help of the following simple empiric -- we assume that there is a deadlock if there is a connection which has to wait for a metadata lock which is currently acquired by some connection which is itself waiting to be able to acquire some shared metadata lock. To implement this change: - Added MDL_context::can_wait_lead_to_deadlock()/_impl() methods which allow to find out if there is someone waiting for metadata lock which is held by the connection and therefore deadlocks are possible if this connection is going to wait for some metadata lock. To do this added version of MDL_ticket::has_pending_conflicting_lock() method which assumes that its caller already owns LOCK_mdl mutex. - Changed MDL_context::wait_for_locks() to use one of the above methods to check if somebody is waiting for metadata lock owned by this context (and therefore deadlock is possible) and emit ER_LOCK_DEADLOCK error in this case. Also now we mark context of connections waiting inside of this method by setting MDL_context::m_is_waiting_in_mdl member. Thanks to this such connection could be waken up if some other connection starts waiting for one of its metadata locks and so a deadlock can occur. - Adjusted notify_shared_lock() to wake up connections which wait inside MDL_context::wait_for_locks() while holding shared metadata lock. - Changed MDL_ticket::upgrade_shared_lock_to_exclusive() to add temporary ticket for exclusive lock to MDL_lock::waiting queue, so request for metadata lock upgrade can be properly detected by our empiric. Also now this method invokes a callback which forces transactions holding shared metadata lock on the table to call MDL_context:: can_wait_lead_to_deadlock() method even if they don't need any new metadata locks. Thanks to this such transactions can detect deadlocks/ livelocks between MDL and table-level locks. Also reduced timeouts between calls to notify_shared_lock() in MDL_ticket::upgrade_shared_lock_to_exclusive() and MDL_context::acquire_exclusive_locks(). This was necessary to get rid of call to mysql_lock_abort() in wait_while_table_is_used(). (Now we instead rely on notify_shared_lock() timely calling mysql_lock_abort_for_thread() for the table on which lock is being upgraded/acquired). sql/mdl.h: - Added a version of MDL_ticket::has_pending_conflicting_lock() method to be used in situations when caller already has acquired LOCK_mdl mutex. - Added MDL_context::can_wait_lead_to_deadlock()/_impl() methods which allow to find out if there is someone waiting for metadata lock which is held by this connection and thus deadlocks are possible if this connections will start waiting for some metadata lock. - Added MDL_context::m_is_waiting_in_mdl member to mark connections waiting in MDL_context::wait_for_locks() method of metadata locking subsystem. Added getter method for this private member to make it accessible in notify_shared_lock() auxiliary so we can wake-up such connections if they hold shared metadata locks. - Finally, added mysql_abort_transactions_with_shared_lock() callback to be able force transactions which don't need any new metadata locks still call MDL_context::can_wait_lead_to_deadlock() and detect some of deadlocks between metadata locks and table-level locks. sql/mysql_priv.h: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_base.cc: Changed approach to metadata locking for multi-statement transactions. We no longer fail ER_LOCK_DEADLOCK error immediately when we encounter conflicting metadata lock. Instead we release all metadata locks acquired by current statement and start to wait until conflicting locks to go away by calling MDL_context::wait_for_locks() method. To avoid deadlocks the latter implements simple empiric which aborts waiting with ER_LOCK_DEADLOCK error if it turns out that somebody is waiting for metadata locks owned by this transaction. To implement the change described above: - Introduced Open_table_context::m_start_of_statement_svp member to store state of metadata locks at the start of the statement. - Changed Open_table_context::request_backoff_action() not to fail with ER_LOCK_DEADLOCK immediately if back-off is requested due to conflicting metadata lock. - Added new argument for close_tables_for_reopen() procedure which allows to specify subset of metadata locks to be released. - Changed open_tables() not to release all metadata locks acquired by current transaction when metadata lock conflict is discovered. Instead we release only locks acquired by current statement. - Changed open_ltable() and open_and_lock_tables_derived() not to emit ER_LOCK_DEADLOCK error when mysql_lock_tables() is aborted in multi-statement transaction when somebody tries to acquire exclusive metadata lock on the table. Instead we release metadata locks acquired by current statement and try to wait until they can be re-acquired. - Adjusted tdc_wait_for_old_versions() to check if there is someone waiting for one of metadata locks held by this connection and run deadlock detection in order to avoid deadlocks in some situations. - Added mysql_abort_transactions_with_shared_lock() callback which allows to force transactions holding shared metadata lock on the table to call MDL_context::can_wait_lead_to_deadlock() even if they don't need any new metadata locks so they can detect potential deadlocks between metadata locking subsystem and table-level locks. - Adjusted wait_while_table_is_used() not to set TABLE::version to 0 as it is now done only when necessary by the above-mentioned callback. Also removed unnecessary call to mysql_lock_abort(). Instead we rely on code performing metadata lock upgrade aborting waits on the table-level lock for this table by calling mysql_lock_abort_for_thread() (invoked by mysql_notify_thread_having_shared_lock()). In future this should allow to reduce number of scenarios in which we produce ER_LOCK_DEADLOCK error even though no real deadlock exists. sql/sql_class.h: Introduced Open_table_context::m_start_of_statement_svp member to store state of metadata locks at the start of the statement. Replaced Open_table_context::m_can_deadlock member with m_has_locks member to reflect the fact that we no longer unconditionally emit ER_LOCK_DEADLOCK error for transaction having some metadata locks when conflicting metadata lock is discovered. sql/sql_insert.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_plist.h: Made I_P_List_iterator<T, B> usable with const lists. sql/sql_show.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_update.cc: Changed UPDATE and MULTI-UPDATE code not to release all metadata locks when calls to mysql_lock_tables() are aborted. Instead we release only locks which are acquired by this statement and then try to reacquire them by calling open_tables(). This solves bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER".
2009-12-30 20:53:30 +03:00
--echo # Sending 'select * from t2'
send select * from t2;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo # --> connection con1
connection con1;
Implementation of simple deadlock detection for metadata locks. This change is supposed to reduce number of ER_LOCK_DEADLOCK errors which occur when multi-statement transaction encounters conflicting metadata lock in cases when waiting is possible. The idea is not to fail ER_LOCK_DEADLOCK error immediately when we encounter conflicting metadata lock. Instead we release all metadata locks acquired by current statement and start to wait until conflicting lock go away. To avoid deadlocks we use simple empiric which aborts waiting with ER_LOCK_DEADLOCK error if it turns out that somebody is waiting for metadata locks owned by this transaction. This patch also fixes bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". The bug was that concurrent execution of UPDATE or MULTI-UPDATE statement as a part of multi-statement transaction that already has used table being updated and ALTER TABLE statement might have resulted of loss of isolation between this transaction and ALTER TABLE statement, which manifested itself as changes performed by ALTER TABLE becoming visible in transaction and wrong binary log order as a consequence. This problem occurred when UPDATE or MULTI-UPDATE's wait in mysql_lock_tables() call was aborted due to metadata lock upgrade performed by concurrent ALTER TABLE. After such abort all metadata locks held by transaction were released but transaction silently continued to be executed as if nothing has happened. We solve this problem by changing our code not to release all locks in such case. Instead we release only locks which were acquired by current statement and then try to reacquire them by restarting open/lock tables process. We piggyback on simple deadlock detector implementation since this change has to be done anyway for it. mysql-test/include/handler.inc: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/handler_innodb.result: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/handler_myisam.result: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/mdl_sync.result: Added test coverage for basic deadlock detection in metadata locking subsystem and for bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". mysql-test/r/sp-lock.result: Adjusted test coverage for metadata locking for stored routines since after introduction of basic deadlock detector for metadata locks number of scenarios in which ER_LOCK_DEADLOCK error in absence of deadlock has decreased. mysql-test/t/mdl_sync.test: Added test coverage for basic deadlock detection in metadata locking subsystem and for bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". mysql-test/t/sp-lock.test: Adjusted test coverage for metadata locking for stored routines since after introduction of basic deadlock detector for metadata locks number of scenarios in which ER_LOCK_DEADLOCK error in absence of deadlock has decreased. sql/log_event_old.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/mdl.cc: Changed metadata locking subsystem to support basic deadlock detection with a help of the following simple empiric -- we assume that there is a deadlock if there is a connection which has to wait for a metadata lock which is currently acquired by some connection which is itself waiting to be able to acquire some shared metadata lock. To implement this change: - Added MDL_context::can_wait_lead_to_deadlock()/_impl() methods which allow to find out if there is someone waiting for metadata lock which is held by the connection and therefore deadlocks are possible if this connection is going to wait for some metadata lock. To do this added version of MDL_ticket::has_pending_conflicting_lock() method which assumes that its caller already owns LOCK_mdl mutex. - Changed MDL_context::wait_for_locks() to use one of the above methods to check if somebody is waiting for metadata lock owned by this context (and therefore deadlock is possible) and emit ER_LOCK_DEADLOCK error in this case. Also now we mark context of connections waiting inside of this method by setting MDL_context::m_is_waiting_in_mdl member. Thanks to this such connection could be waken up if some other connection starts waiting for one of its metadata locks and so a deadlock can occur. - Adjusted notify_shared_lock() to wake up connections which wait inside MDL_context::wait_for_locks() while holding shared metadata lock. - Changed MDL_ticket::upgrade_shared_lock_to_exclusive() to add temporary ticket for exclusive lock to MDL_lock::waiting queue, so request for metadata lock upgrade can be properly detected by our empiric. Also now this method invokes a callback which forces transactions holding shared metadata lock on the table to call MDL_context:: can_wait_lead_to_deadlock() method even if they don't need any new metadata locks. Thanks to this such transactions can detect deadlocks/ livelocks between MDL and table-level locks. Also reduced timeouts between calls to notify_shared_lock() in MDL_ticket::upgrade_shared_lock_to_exclusive() and MDL_context::acquire_exclusive_locks(). This was necessary to get rid of call to mysql_lock_abort() in wait_while_table_is_used(). (Now we instead rely on notify_shared_lock() timely calling mysql_lock_abort_for_thread() for the table on which lock is being upgraded/acquired). sql/mdl.h: - Added a version of MDL_ticket::has_pending_conflicting_lock() method to be used in situations when caller already has acquired LOCK_mdl mutex. - Added MDL_context::can_wait_lead_to_deadlock()/_impl() methods which allow to find out if there is someone waiting for metadata lock which is held by this connection and thus deadlocks are possible if this connections will start waiting for some metadata lock. - Added MDL_context::m_is_waiting_in_mdl member to mark connections waiting in MDL_context::wait_for_locks() method of metadata locking subsystem. Added getter method for this private member to make it accessible in notify_shared_lock() auxiliary so we can wake-up such connections if they hold shared metadata locks. - Finally, added mysql_abort_transactions_with_shared_lock() callback to be able force transactions which don't need any new metadata locks still call MDL_context::can_wait_lead_to_deadlock() and detect some of deadlocks between metadata locks and table-level locks. sql/mysql_priv.h: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_base.cc: Changed approach to metadata locking for multi-statement transactions. We no longer fail ER_LOCK_DEADLOCK error immediately when we encounter conflicting metadata lock. Instead we release all metadata locks acquired by current statement and start to wait until conflicting locks to go away by calling MDL_context::wait_for_locks() method. To avoid deadlocks the latter implements simple empiric which aborts waiting with ER_LOCK_DEADLOCK error if it turns out that somebody is waiting for metadata locks owned by this transaction. To implement the change described above: - Introduced Open_table_context::m_start_of_statement_svp member to store state of metadata locks at the start of the statement. - Changed Open_table_context::request_backoff_action() not to fail with ER_LOCK_DEADLOCK immediately if back-off is requested due to conflicting metadata lock. - Added new argument for close_tables_for_reopen() procedure which allows to specify subset of metadata locks to be released. - Changed open_tables() not to release all metadata locks acquired by current transaction when metadata lock conflict is discovered. Instead we release only locks acquired by current statement. - Changed open_ltable() and open_and_lock_tables_derived() not to emit ER_LOCK_DEADLOCK error when mysql_lock_tables() is aborted in multi-statement transaction when somebody tries to acquire exclusive metadata lock on the table. Instead we release metadata locks acquired by current statement and try to wait until they can be re-acquired. - Adjusted tdc_wait_for_old_versions() to check if there is someone waiting for one of metadata locks held by this connection and run deadlock detection in order to avoid deadlocks in some situations. - Added mysql_abort_transactions_with_shared_lock() callback which allows to force transactions holding shared metadata lock on the table to call MDL_context::can_wait_lead_to_deadlock() even if they don't need any new metadata locks so they can detect potential deadlocks between metadata locking subsystem and table-level locks. - Adjusted wait_while_table_is_used() not to set TABLE::version to 0 as it is now done only when necessary by the above-mentioned callback. Also removed unnecessary call to mysql_lock_abort(). Instead we rely on code performing metadata lock upgrade aborting waits on the table-level lock for this table by calling mysql_lock_abort_for_thread() (invoked by mysql_notify_thread_having_shared_lock()). In future this should allow to reduce number of scenarios in which we produce ER_LOCK_DEADLOCK error even though no real deadlock exists. sql/sql_class.h: Introduced Open_table_context::m_start_of_statement_svp member to store state of metadata locks at the start of the statement. Replaced Open_table_context::m_can_deadlock member with m_has_locks member to reflect the fact that we no longer unconditionally emit ER_LOCK_DEADLOCK error for transaction having some metadata locks when conflicting metadata lock is discovered. sql/sql_insert.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_plist.h: Made I_P_List_iterator<T, B> usable with const lists. sql/sql_show.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_update.cc: Changed UPDATE and MULTI-UPDATE code not to release all metadata locks when calls to mysql_lock_tables() are aborted. Instead we release only locks which are acquired by this statement and then try to reacquire them by calling open_tables(). This solves bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER".
2009-12-30 20:53:30 +03:00
--echo # Waiting for 'select * from t2' to get blocked...
Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompatible" to be pushed as separate patch. Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. Also replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it more consistent with other thread state names. Updated test cases and their results according to these changes. Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. mysql-test/r/query_cache.result: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/t/query_cache.test: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysys/thr_lock.c: Replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it consistent with thread state names which are used while waiting for metadata locks and table flush. sql/mdl.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/mdl.h: To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/sql_base.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for table flush, with a more elaborate "Waiting for table flush".
2010-08-06 15:29:37 +04:00
let $wait_condition=select count(*)=1 from information_schema.processlist
where state='Waiting for table metadata lock' and
info='select * from t2';
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
unlock tables;
--echo # --> connection con2
connection con2;
--echo # Reaping 'drop table t2'...
--reap
--echo # --> connection default
connection default;
Implementation of simple deadlock detection for metadata locks. This change is supposed to reduce number of ER_LOCK_DEADLOCK errors which occur when multi-statement transaction encounters conflicting metadata lock in cases when waiting is possible. The idea is not to fail ER_LOCK_DEADLOCK error immediately when we encounter conflicting metadata lock. Instead we release all metadata locks acquired by current statement and start to wait until conflicting lock go away. To avoid deadlocks we use simple empiric which aborts waiting with ER_LOCK_DEADLOCK error if it turns out that somebody is waiting for metadata locks owned by this transaction. This patch also fixes bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". The bug was that concurrent execution of UPDATE or MULTI-UPDATE statement as a part of multi-statement transaction that already has used table being updated and ALTER TABLE statement might have resulted of loss of isolation between this transaction and ALTER TABLE statement, which manifested itself as changes performed by ALTER TABLE becoming visible in transaction and wrong binary log order as a consequence. This problem occurred when UPDATE or MULTI-UPDATE's wait in mysql_lock_tables() call was aborted due to metadata lock upgrade performed by concurrent ALTER TABLE. After such abort all metadata locks held by transaction were released but transaction silently continued to be executed as if nothing has happened. We solve this problem by changing our code not to release all locks in such case. Instead we release only locks which were acquired by current statement and then try to reacquire them by restarting open/lock tables process. We piggyback on simple deadlock detector implementation since this change has to be done anyway for it. mysql-test/include/handler.inc: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/handler_innodb.result: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/handler_myisam.result: After introduction of basic deadlock detector for metadata locks it became necessary to change parts of test for HANDLER statements which covered some of scenarios in which ER_LOCK_DEADLOCK error was detected in absence of real deadlock (with new deadlock detector this no longer happens). Also adjusted test to the fact that HANDLER READ for the table no longer will be blocked by ALTER TABLE for the same table which awaits for metadata lock upgrade (this is due to removal of mysql_lock_abort() from wait_while_table_is_used()). mysql-test/r/mdl_sync.result: Added test coverage for basic deadlock detection in metadata locking subsystem and for bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". mysql-test/r/sp-lock.result: Adjusted test coverage for metadata locking for stored routines since after introduction of basic deadlock detector for metadata locks number of scenarios in which ER_LOCK_DEADLOCK error in absence of deadlock has decreased. mysql-test/t/mdl_sync.test: Added test coverage for basic deadlock detection in metadata locking subsystem and for bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER". mysql-test/t/sp-lock.test: Adjusted test coverage for metadata locking for stored routines since after introduction of basic deadlock detector for metadata locks number of scenarios in which ER_LOCK_DEADLOCK error in absence of deadlock has decreased. sql/log_event_old.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/mdl.cc: Changed metadata locking subsystem to support basic deadlock detection with a help of the following simple empiric -- we assume that there is a deadlock if there is a connection which has to wait for a metadata lock which is currently acquired by some connection which is itself waiting to be able to acquire some shared metadata lock. To implement this change: - Added MDL_context::can_wait_lead_to_deadlock()/_impl() methods which allow to find out if there is someone waiting for metadata lock which is held by the connection and therefore deadlocks are possible if this connection is going to wait for some metadata lock. To do this added version of MDL_ticket::has_pending_conflicting_lock() method which assumes that its caller already owns LOCK_mdl mutex. - Changed MDL_context::wait_for_locks() to use one of the above methods to check if somebody is waiting for metadata lock owned by this context (and therefore deadlock is possible) and emit ER_LOCK_DEADLOCK error in this case. Also now we mark context of connections waiting inside of this method by setting MDL_context::m_is_waiting_in_mdl member. Thanks to this such connection could be waken up if some other connection starts waiting for one of its metadata locks and so a deadlock can occur. - Adjusted notify_shared_lock() to wake up connections which wait inside MDL_context::wait_for_locks() while holding shared metadata lock. - Changed MDL_ticket::upgrade_shared_lock_to_exclusive() to add temporary ticket for exclusive lock to MDL_lock::waiting queue, so request for metadata lock upgrade can be properly detected by our empiric. Also now this method invokes a callback which forces transactions holding shared metadata lock on the table to call MDL_context:: can_wait_lead_to_deadlock() method even if they don't need any new metadata locks. Thanks to this such transactions can detect deadlocks/ livelocks between MDL and table-level locks. Also reduced timeouts between calls to notify_shared_lock() in MDL_ticket::upgrade_shared_lock_to_exclusive() and MDL_context::acquire_exclusive_locks(). This was necessary to get rid of call to mysql_lock_abort() in wait_while_table_is_used(). (Now we instead rely on notify_shared_lock() timely calling mysql_lock_abort_for_thread() for the table on which lock is being upgraded/acquired). sql/mdl.h: - Added a version of MDL_ticket::has_pending_conflicting_lock() method to be used in situations when caller already has acquired LOCK_mdl mutex. - Added MDL_context::can_wait_lead_to_deadlock()/_impl() methods which allow to find out if there is someone waiting for metadata lock which is held by this connection and thus deadlocks are possible if this connections will start waiting for some metadata lock. - Added MDL_context::m_is_waiting_in_mdl member to mark connections waiting in MDL_context::wait_for_locks() method of metadata locking subsystem. Added getter method for this private member to make it accessible in notify_shared_lock() auxiliary so we can wake-up such connections if they hold shared metadata locks. - Finally, added mysql_abort_transactions_with_shared_lock() callback to be able force transactions which don't need any new metadata locks still call MDL_context::can_wait_lead_to_deadlock() and detect some of deadlocks between metadata locks and table-level locks. sql/mysql_priv.h: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_base.cc: Changed approach to metadata locking for multi-statement transactions. We no longer fail ER_LOCK_DEADLOCK error immediately when we encounter conflicting metadata lock. Instead we release all metadata locks acquired by current statement and start to wait until conflicting locks to go away by calling MDL_context::wait_for_locks() method. To avoid deadlocks the latter implements simple empiric which aborts waiting with ER_LOCK_DEADLOCK error if it turns out that somebody is waiting for metadata locks owned by this transaction. To implement the change described above: - Introduced Open_table_context::m_start_of_statement_svp member to store state of metadata locks at the start of the statement. - Changed Open_table_context::request_backoff_action() not to fail with ER_LOCK_DEADLOCK immediately if back-off is requested due to conflicting metadata lock. - Added new argument for close_tables_for_reopen() procedure which allows to specify subset of metadata locks to be released. - Changed open_tables() not to release all metadata locks acquired by current transaction when metadata lock conflict is discovered. Instead we release only locks acquired by current statement. - Changed open_ltable() and open_and_lock_tables_derived() not to emit ER_LOCK_DEADLOCK error when mysql_lock_tables() is aborted in multi-statement transaction when somebody tries to acquire exclusive metadata lock on the table. Instead we release metadata locks acquired by current statement and try to wait until they can be re-acquired. - Adjusted tdc_wait_for_old_versions() to check if there is someone waiting for one of metadata locks held by this connection and run deadlock detection in order to avoid deadlocks in some situations. - Added mysql_abort_transactions_with_shared_lock() callback which allows to force transactions holding shared metadata lock on the table to call MDL_context::can_wait_lead_to_deadlock() even if they don't need any new metadata locks so they can detect potential deadlocks between metadata locking subsystem and table-level locks. - Adjusted wait_while_table_is_used() not to set TABLE::version to 0 as it is now done only when necessary by the above-mentioned callback. Also removed unnecessary call to mysql_lock_abort(). Instead we rely on code performing metadata lock upgrade aborting waits on the table-level lock for this table by calling mysql_lock_abort_for_thread() (invoked by mysql_notify_thread_having_shared_lock()). In future this should allow to reduce number of scenarios in which we produce ER_LOCK_DEADLOCK error even though no real deadlock exists. sql/sql_class.h: Introduced Open_table_context::m_start_of_statement_svp member to store state of metadata locks at the start of the statement. Replaced Open_table_context::m_can_deadlock member with m_has_locks member to reflect the fact that we no longer unconditionally emit ER_LOCK_DEADLOCK error for transaction having some metadata locks when conflicting metadata lock is discovered. sql/sql_insert.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_plist.h: Made I_P_List_iterator<T, B> usable with const lists. sql/sql_show.cc: close_tables_for_reopen() now takes one more argument which specifies at which point it should stop releasing metadata locks acquired by this connection. sql/sql_update.cc: Changed UPDATE and MULTI-UPDATE code not to release all metadata locks when calls to mysql_lock_tables() are aborted. Instead we release only locks which are acquired by this statement and then try to reacquire them by calling open_tables(). This solves bug #46273 "MySQL 5.4.4 new MDL: Bug#989 is not fully fixed in case of ALTER".
2009-12-30 20:53:30 +03:00
--echo # Reaping 'select * from t2'
--error ER_NO_SUCH_TABLE
reap;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
handler t1 close;
--echo #
--echo # ROLLBACK TO SAVEPOINT releases transactional locks,
--echo # but has no effect on open HANDLERs
--echo #
create table t2 like t1;
create table t3 like t1;
begin;
--echo # Have something before the savepoint
select * from t3;
savepoint sv;
handler t1 open;
handler t1 read a first;
handler t1 read a next;
select * from t2;
--echo # --> connection con1
connection con1;
--echo # Sending:
--send drop table t1
--echo # --> connection con2
connection con2;
--echo # Sending:
--send drop table t2
--echo # --> connection default
connection default;
--echo # Let DROP TABLE statements sync in. We must use
--echo # a separate connection for that, because otherwise SELECT
--echo # will auto-close the HANDLERs, becaues there are pending
--echo # exclusive locks against them.
--echo # --> connection con3
connection con3;
--echo # Waiting for 'drop table t1' to get blocked...
Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompatible" to be pushed as separate patch. Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. Also replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it more consistent with other thread state names. Updated test cases and their results according to these changes. Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. mysql-test/r/query_cache.result: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/t/query_cache.test: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysys/thr_lock.c: Replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it consistent with thread state names which are used while waiting for metadata locks and table flush. sql/mdl.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/mdl.h: To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/sql_base.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for table flush, with a more elaborate "Waiting for table flush".
2010-08-06 15:29:37 +04:00
let $wait_condition=select count(*)=1 from information_schema.processlist
where state='Waiting for table metadata lock' and
info='drop table t1';
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--source include/wait_condition.inc
--echo # Waiting for 'drop table t2' to get blocked...
Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompatible" to be pushed as separate patch. Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. Also replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it more consistent with other thread state names. Updated test cases and their results according to these changes. Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. mysql-test/r/query_cache.result: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/t/query_cache.test: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysys/thr_lock.c: Replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it consistent with thread state names which are used while waiting for metadata locks and table flush. sql/mdl.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/mdl.h: To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/sql_base.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for table flush, with a more elaborate "Waiting for table flush".
2010-08-06 15:29:37 +04:00
let $wait_condition=select count(*)=1 from information_schema.processlist
where state='Waiting for table metadata lock' and
info='drop table t2';
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--source include/wait_condition.inc
--echo # Demonstrate that t2 lock was released and t2 was dropped
--echo # after ROLLBACK TO SAVEPOINT
--echo # --> connection default
connection default;
rollback to savepoint sv;
--echo # --> connection con2
connection con2;
--echo # Reaping 'drop table t2'...
--reap
--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
--echo # lock.
--echo # --> connection default
connection default;
handler t1 read a next;
handler t1 read a next;
--echo # Demonstrate that the drop will go through as soon as we close the
--echo # HANDLER
handler t1 close;
--echo # connection con1
connection con1;
--echo # Reaping 'drop table t1'...
--reap
--echo # --> connection default
connection default;
commit;
drop table t3;
--echo #
--echo # A few special cases when using SAVEPOINT/ROLLBACK TO
--echo # SAVEPOINT and HANDLER.
--echo #
--echo # Show that rollback to the savepoint taken in the beginning
--echo # of the transaction doesn't release mdl lock on
--echo # the HANDLER that was opened later.
--echo #
create table t1 (a int, key using btree (a));
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
insert into t1 (a) values (1), (2), (3), (4), (5);
create table t2 like t1;
begin;
savepoint sv;
handler t1 open;
handler t1 read a first;
handler t1 read a next;
select * from t2;
--echo # --> connection con1
connection con1;
--echo # Sending:
--send drop table t1
--echo # --> connection con2
connection con2;
--echo # Sending:
--send drop table t2
--echo # --> connection default
connection default;
--echo # Let DROP TABLE statements sync in. We must use
--echo # a separate connection for that, because otherwise SELECT
--echo # will auto-close the HANDLERs, becaues there are pending
--echo # exclusive locks against them.
--echo # --> connection con3
connection con3;
--echo # Waiting for 'drop table t1' to get blocked...
Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompatible" to be pushed as separate patch. Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. Also replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it more consistent with other thread state names. Updated test cases and their results according to these changes. Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. mysql-test/r/query_cache.result: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/t/query_cache.test: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysys/thr_lock.c: Replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it consistent with thread state names which are used while waiting for metadata locks and table flush. sql/mdl.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/mdl.h: To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/sql_base.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for table flush, with a more elaborate "Waiting for table flush".
2010-08-06 15:29:37 +04:00
let $wait_condition=select count(*)=1 from information_schema.processlist
where state='Waiting for table metadata lock' and
info='drop table t1';
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--source include/wait_condition.inc
--echo # Waiting for 'drop table t2' to get blocked...
Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompatible" to be pushed as separate patch. Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. Also replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it more consistent with other thread state names. Updated test cases and their results according to these changes. Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. mysql-test/r/query_cache.result: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/t/query_cache.test: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysys/thr_lock.c: Replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it consistent with thread state names which are used while waiting for metadata locks and table flush. sql/mdl.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/mdl.h: To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/sql_base.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for table flush, with a more elaborate "Waiting for table flush".
2010-08-06 15:29:37 +04:00
let $wait_condition=select count(*)=1 from information_schema.processlist
where state='Waiting for table metadata lock' and
info='drop table t2';
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--source include/wait_condition.inc
--echo # Demonstrate that t2 lock was released and t2 was dropped
--echo # after ROLLBACK TO SAVEPOINT
--echo # --> connection default
connection default;
rollback to savepoint sv;
--echo # --> connection con2
connection con2;
--echo # Reaping 'drop table t2'...
--reap
--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
--echo # lock.
--echo # --> connection default
connection default;
handler t1 read a next;
handler t1 read a next;
--echo # Demonstrate that the drop will go through as soon as we close the
--echo # HANDLER
handler t1 close;
--echo # connection con1
connection con1;
--echo # Reaping 'drop table t1'...
--reap
--echo # --> connection default
connection default;
commit;
--echo #
--echo # Show that rollback to the savepoint taken in the beginning
--echo # of the transaction works properly (no valgrind warnins, etc),
--echo # even though it's done after the HANDLER mdl lock that was there
--echo # at the beginning is released and added again.
--echo #
create table t1 (a int, key using btree (a));
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
insert into t1 (a) values (1), (2), (3), (4), (5);
create table t2 like t1;
create table t3 like t1;
insert into t3 (a) select a from t1;
begin;
handler t1 open;
savepoint sv;
handler t1 read a first;
select * from t2;
handler t1 close;
handler t3 open;
handler t3 read a first;
rollback to savepoint sv;
--echo # --> connection con1
connection con1;
drop table t1, t2;
--echo # Sending:
--send drop table t3
--echo # Let DROP TABLE statement sync in.
--echo # --> connection con2
connection con2;
--echo # Waiting for 'drop table t3' to get blocked...
Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompatible" to be pushed as separate patch. Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. Also replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it more consistent with other thread state names. Updated test cases and their results according to these changes. Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. mysql-test/r/query_cache.result: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/t/query_cache.test: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysys/thr_lock.c: Replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it consistent with thread state names which are used while waiting for metadata locks and table flush. sql/mdl.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/mdl.h: To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/sql_base.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for table flush, with a more elaborate "Waiting for table flush".
2010-08-06 15:29:37 +04:00
let $wait_condition=select count(*)=1 from information_schema.processlist
where state='Waiting for table metadata lock' and
info='drop table t3';
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--source include/wait_condition.inc
--echo # Demonstrate that ROLLBACK TO SAVEPOINT didn't release the handler
--echo # lock.
--echo # --> connection default
connection default;
handler t3 read a next;
--echo # Demonstrate that the drop will go through as soon as we close the
--echo # HANDLER
handler t3 close;
--echo # connection con1
connection con1;
--echo # Reaping 'drop table t3'...
--reap
--echo # --> connection default
connection default;
commit;
--echo #
--echo # If we have to wait on an exclusive locks while having
--echo # an open HANDLER, ER_LOCK_DEADLOCK is reported.
--echo #
create table t1 (a int, key a(a));
create table t2 like t1;
handler t1 open;
--echo # --> connection con1
connection con1;
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. mysql-test/include/handler.inc: Adjusted test case to trigger an execution path on which bug 41110 "crash with handler command when used concurrently with alter table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data with alter table" were originally discovered. Left old test case which no longer triggers this execution path for the sake of coverage. Added test coverage for HANDLER SQL statements and type-aware metadata locks. Added a test for the global shared lock and HANDLER SQL. Updated tests to take into account that the old simple deadlock detection heuristics was replaced with a graph-based deadlock detector. mysql-test/r/debug_sync.result: Updated results (see debug_sync.test). mysql-test/r/handler_innodb.result: Updated results (see handler.inc test). mysql-test/r/handler_myisam.result: Updated results (see handler.inc test). mysql-test/r/innodb-lock.result: Updated results (see innodb-lock.test). mysql-test/r/innodb_mysql_lock.result: Updated results (see innodb_mysql_lock.test). mysql-test/r/lock.result: Updated results (see lock.test). mysql-test/r/lock_multi.result: Updated results (see lock_multi.test). mysql-test/r/lock_sync.result: Updated results (see lock_sync.test). mysql-test/r/mdl_sync.result: Updated results (see mdl_sync.test). mysql-test/r/sp-threads.result: SHOW PROCESSLIST output has changed due to the fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/r/truncate_coverage.result: Updated results (see truncate_coverage.test). mysql-test/suite/funcs_1/datadict/processlist_val.inc: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/rpl/t/rpl_sp.test: Updated to a new SHOW PROCESSLIST state name. mysql-test/t/debug_sync.test: Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter no longer allows to trigger execution path involving waiting on thr_lock.c lock and therefore reaching debug sync-point covered by this test. mysql-test/t/innodb-lock.test: Adjusted test case to the fact that innodb_table_locks=0 option is no longer supported, since LOCK TABLES WRITE handles all its conflicts within MDL subsystem. mysql-test/t/innodb_mysql_lock.test: Added test for bug #37346 "innodb does not detect deadlock between update and alter table". mysql-test/t/lock.test: Added test coverage which checks the fact that we no longer support DDL under LOCK TABLES on tables which were locked implicitly. Adjusted existing test cases accordingly. mysql-test/t/lock_multi.test: Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock". Adjusted other test cases to take into account the fact that waiting for LOCK TABLES ... WRITE now happens within MDL subsystem. mysql-test/t/lock_sync.test: Since LOCK TABLES ... WRITE now takes SNRW metadata lock for tables locked explicitly we have to implicitly lock InnoDB tables (through view) to trigger the table-level lock conflict between TL_WRITE and TL_WRITE_ALLOW_WRITE. mysql-test/t/mdl_sync.test: Added basic test coverage for type-of-operation-aware metadata locks. Also covered with tests some use cases involving HANDLER statements in which a deadlock could arise. Adjusted existing tests to take type-of-operation-aware MDL into account. mysql-test/t/multi_update.test: Update to a new SHOW PROCESSLIST state name. mysql-test/t/truncate_coverage.test: Adjusted test case after making LOCK TABLES WRITE to wait until transactions that use the table to be locked are completed. Updated to the changed name of DEBUG_SYNC point. sql/handler.cc: Global read lock functionality has been moved into a class. sql/lock.cc: Global read lock functionality has been moved into a class. Updated code to use the new MDL API. sql/mdl.cc: Introduced new type-of-operation aware metadata locks. To do this: - Changed MDL_lock to use one list for waiting requests and one list for granted requests. For each list, added a bitmap that holds information what lock types a list contains. Added a helper class MDL_lock::List to manipulate with granted and waited lists while keeping the bitmaps in sync with list contents. - Changed lock-compatibility functions to use bitmaps that define compatibility. - Introduced a graph based deadlock detector inspired by waiting_threads.c from Maria implementation. - Now that we have a deadlock detector, and no longer have a global lock to protect individual lock objects, but rather use an rw lock per object, removed redundant code for upgrade, and the global read lock. Changed the MDL API to no longer require the caller to acquire the global intention exclusive lock by means of a separate method. Removed a few more methods that became redundant. - Removed deadlock detection heuristic, it has been made obsolete by the deadlock detector. - With operation-type-aware metadata locks, MDL subsystem has become aware of potential conflicts between DDL and open transactions. This made it possible to remove calls to mysql_abort_transactions_with_shared_lock() from acquisition paths for exclusive lock and lock upgrade. Now we can simply wait for these transactions to complete without fear of deadlock. Function mysql_lock_abort() has also become unnecessary for all conflicting cases except when a DDL conflicts with a connection that has an open HANDLER. sql/mdl.h: Introduced new type-of-operation aware metadata locks. Introduced a graph based deadlock detector and supporting methods. Added comments. God rid of redundant API calls. Renamed m_lt_or_ha_sentinel to m_trans_sentinel, since now it guards the global read lock as well as LOCK TABLES and HANDLER locks. sql/mysql_priv.h: Moved the global read lock functionality into a class. Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces open_tables() to take MDL_SHARED on tables instead of metadata locks specified in the parser. We use this to allow PREPARE run concurrently in presence of LOCK TABLES ... WRITE. Added signature for find_table_for_mdl_ugprade(). sql/set_var.cc: Global read lock functionality has been moved into a class. sql/sp_head.cc: When creating TABLE_LIST elements for prelocking or system tables set the type of request for metadata lock according to the operation that will be performed on the table. sql/sql_base.cc: - Updated code to use the new MDL API. - In order to avoid locks starvation we take upgradable locks all at once. As result implicitly locked tables no longer get an upgradable lock. Consequently DDL and FLUSH TABLES for such tables is prohibited. find_write_locked_table() was replaced by find_table_for_mdl_upgrade() function. open_table() was adjusted to return TABLE instance with upgradable ticket when necessary. - We no longer wait for all locks on OT_WAIT back off action -- only on the lock that caused the wait conflict. Moreover, now we distinguish cases when we have to wait due to conflict in MDL and old version of table in TDC. - Upate mysql_notify_threads_having_share_locks() to only abort thr_lock.c waits of threads that have open HANDLERs, since lock conflicts with only these threads now can lead to deadlocks not detectable by the MDL deadlock detector. - Remove mysql_abort_transactions_with_shared_locks() which is no longer needed. sql/sql_class.cc: Global read lock functionality has been moved into a class. Re-arranged code in THD::cleanup() to simplify assert. sql/sql_class.h: Introduced class to incapsulate global read lock functionality. Now sentinel in MDL subsystem guards the global read lock as well as LOCK TABLES and HANDLER locks. Adjusted code accordingly. sql/sql_db.cc: Global read lock functionality has been moved into a class. sql/sql_delete.cc: We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result TRUNCATE TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_handler.cc: Inform MDL_context about presence of open HANDLERs. Since HANLDERs break MDL protocol by acquiring table-level lock while holding only S metadata lock on a table MDL subsystem should take special care about such contexts (Now this is the only case when mysql_lock_abort() is used). sql/sql_parse.cc: Global read lock functionality has been moved into a class. Do not take upgradable metadata locks when opening tables for CREATE TABLE SELECT as it is not necessary and limits concurrency. When initializing TABLE_LIST objects before adding them to the table list set the type of request for metadata lock according to the operation that will be performed on the table. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result FLUSH TABLES is no longer allowed for such tables. sql/sql_prepare.cc: Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening tables during PREPARE. This allows PREPARE to run concurrently in presence of LOCK TABLES ... WRITE. sql/sql_rename.cc: Global read lock functionality has been moved into a class. sql/sql_show.cc: Updated code to use the new MDL API. sql/sql_table.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result DROP TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_trigger.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result CREATE/DROP TRIGGER is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_view.cc: Global read lock functionality has been moved into a class. Fixed results of wrong merge that led to misuse of GLR API. CREATE VIEW statement is not a commit statement. sql/table.cc: When resetting TABLE_LIST objects for PS or SP re-execution set the type of request for metadata lock according to the operation that will be performed on the table. Do the same in auxiliary function initializing metadata lock requests in a table list. sql/table.h: When initializing TABLE_LIST objects set the type of request for metadata lock according to the operation that will be performed on the table. sql/transaction.cc: Global read lock functionality has been moved into a class.
2010-02-01 14:43:06 +03:00
lock table t1 write, t2 write;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo # --> connection default
connection default;
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. mysql-test/include/handler.inc: Adjusted test case to trigger an execution path on which bug 41110 "crash with handler command when used concurrently with alter table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data with alter table" were originally discovered. Left old test case which no longer triggers this execution path for the sake of coverage. Added test coverage for HANDLER SQL statements and type-aware metadata locks. Added a test for the global shared lock and HANDLER SQL. Updated tests to take into account that the old simple deadlock detection heuristics was replaced with a graph-based deadlock detector. mysql-test/r/debug_sync.result: Updated results (see debug_sync.test). mysql-test/r/handler_innodb.result: Updated results (see handler.inc test). mysql-test/r/handler_myisam.result: Updated results (see handler.inc test). mysql-test/r/innodb-lock.result: Updated results (see innodb-lock.test). mysql-test/r/innodb_mysql_lock.result: Updated results (see innodb_mysql_lock.test). mysql-test/r/lock.result: Updated results (see lock.test). mysql-test/r/lock_multi.result: Updated results (see lock_multi.test). mysql-test/r/lock_sync.result: Updated results (see lock_sync.test). mysql-test/r/mdl_sync.result: Updated results (see mdl_sync.test). mysql-test/r/sp-threads.result: SHOW PROCESSLIST output has changed due to the fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/r/truncate_coverage.result: Updated results (see truncate_coverage.test). mysql-test/suite/funcs_1/datadict/processlist_val.inc: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/rpl/t/rpl_sp.test: Updated to a new SHOW PROCESSLIST state name. mysql-test/t/debug_sync.test: Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter no longer allows to trigger execution path involving waiting on thr_lock.c lock and therefore reaching debug sync-point covered by this test. mysql-test/t/innodb-lock.test: Adjusted test case to the fact that innodb_table_locks=0 option is no longer supported, since LOCK TABLES WRITE handles all its conflicts within MDL subsystem. mysql-test/t/innodb_mysql_lock.test: Added test for bug #37346 "innodb does not detect deadlock between update and alter table". mysql-test/t/lock.test: Added test coverage which checks the fact that we no longer support DDL under LOCK TABLES on tables which were locked implicitly. Adjusted existing test cases accordingly. mysql-test/t/lock_multi.test: Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock". Adjusted other test cases to take into account the fact that waiting for LOCK TABLES ... WRITE now happens within MDL subsystem. mysql-test/t/lock_sync.test: Since LOCK TABLES ... WRITE now takes SNRW metadata lock for tables locked explicitly we have to implicitly lock InnoDB tables (through view) to trigger the table-level lock conflict between TL_WRITE and TL_WRITE_ALLOW_WRITE. mysql-test/t/mdl_sync.test: Added basic test coverage for type-of-operation-aware metadata locks. Also covered with tests some use cases involving HANDLER statements in which a deadlock could arise. Adjusted existing tests to take type-of-operation-aware MDL into account. mysql-test/t/multi_update.test: Update to a new SHOW PROCESSLIST state name. mysql-test/t/truncate_coverage.test: Adjusted test case after making LOCK TABLES WRITE to wait until transactions that use the table to be locked are completed. Updated to the changed name of DEBUG_SYNC point. sql/handler.cc: Global read lock functionality has been moved into a class. sql/lock.cc: Global read lock functionality has been moved into a class. Updated code to use the new MDL API. sql/mdl.cc: Introduced new type-of-operation aware metadata locks. To do this: - Changed MDL_lock to use one list for waiting requests and one list for granted requests. For each list, added a bitmap that holds information what lock types a list contains. Added a helper class MDL_lock::List to manipulate with granted and waited lists while keeping the bitmaps in sync with list contents. - Changed lock-compatibility functions to use bitmaps that define compatibility. - Introduced a graph based deadlock detector inspired by waiting_threads.c from Maria implementation. - Now that we have a deadlock detector, and no longer have a global lock to protect individual lock objects, but rather use an rw lock per object, removed redundant code for upgrade, and the global read lock. Changed the MDL API to no longer require the caller to acquire the global intention exclusive lock by means of a separate method. Removed a few more methods that became redundant. - Removed deadlock detection heuristic, it has been made obsolete by the deadlock detector. - With operation-type-aware metadata locks, MDL subsystem has become aware of potential conflicts between DDL and open transactions. This made it possible to remove calls to mysql_abort_transactions_with_shared_lock() from acquisition paths for exclusive lock and lock upgrade. Now we can simply wait for these transactions to complete without fear of deadlock. Function mysql_lock_abort() has also become unnecessary for all conflicting cases except when a DDL conflicts with a connection that has an open HANDLER. sql/mdl.h: Introduced new type-of-operation aware metadata locks. Introduced a graph based deadlock detector and supporting methods. Added comments. God rid of redundant API calls. Renamed m_lt_or_ha_sentinel to m_trans_sentinel, since now it guards the global read lock as well as LOCK TABLES and HANDLER locks. sql/mysql_priv.h: Moved the global read lock functionality into a class. Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces open_tables() to take MDL_SHARED on tables instead of metadata locks specified in the parser. We use this to allow PREPARE run concurrently in presence of LOCK TABLES ... WRITE. Added signature for find_table_for_mdl_ugprade(). sql/set_var.cc: Global read lock functionality has been moved into a class. sql/sp_head.cc: When creating TABLE_LIST elements for prelocking or system tables set the type of request for metadata lock according to the operation that will be performed on the table. sql/sql_base.cc: - Updated code to use the new MDL API. - In order to avoid locks starvation we take upgradable locks all at once. As result implicitly locked tables no longer get an upgradable lock. Consequently DDL and FLUSH TABLES for such tables is prohibited. find_write_locked_table() was replaced by find_table_for_mdl_upgrade() function. open_table() was adjusted to return TABLE instance with upgradable ticket when necessary. - We no longer wait for all locks on OT_WAIT back off action -- only on the lock that caused the wait conflict. Moreover, now we distinguish cases when we have to wait due to conflict in MDL and old version of table in TDC. - Upate mysql_notify_threads_having_share_locks() to only abort thr_lock.c waits of threads that have open HANDLERs, since lock conflicts with only these threads now can lead to deadlocks not detectable by the MDL deadlock detector. - Remove mysql_abort_transactions_with_shared_locks() which is no longer needed. sql/sql_class.cc: Global read lock functionality has been moved into a class. Re-arranged code in THD::cleanup() to simplify assert. sql/sql_class.h: Introduced class to incapsulate global read lock functionality. Now sentinel in MDL subsystem guards the global read lock as well as LOCK TABLES and HANDLER locks. Adjusted code accordingly. sql/sql_db.cc: Global read lock functionality has been moved into a class. sql/sql_delete.cc: We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result TRUNCATE TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_handler.cc: Inform MDL_context about presence of open HANDLERs. Since HANLDERs break MDL protocol by acquiring table-level lock while holding only S metadata lock on a table MDL subsystem should take special care about such contexts (Now this is the only case when mysql_lock_abort() is used). sql/sql_parse.cc: Global read lock functionality has been moved into a class. Do not take upgradable metadata locks when opening tables for CREATE TABLE SELECT as it is not necessary and limits concurrency. When initializing TABLE_LIST objects before adding them to the table list set the type of request for metadata lock according to the operation that will be performed on the table. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result FLUSH TABLES is no longer allowed for such tables. sql/sql_prepare.cc: Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening tables during PREPARE. This allows PREPARE to run concurrently in presence of LOCK TABLES ... WRITE. sql/sql_rename.cc: Global read lock functionality has been moved into a class. sql/sql_show.cc: Updated code to use the new MDL API. sql/sql_table.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result DROP TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_trigger.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result CREATE/DROP TRIGGER is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_view.cc: Global read lock functionality has been moved into a class. Fixed results of wrong merge that led to misuse of GLR API. CREATE VIEW statement is not a commit statement. sql/table.cc: When resetting TABLE_LIST objects for PS or SP re-execution set the type of request for metadata lock according to the operation that will be performed on the table. Do the same in auxiliary function initializing metadata lock requests in a table list. sql/table.h: When initializing TABLE_LIST objects set the type of request for metadata lock according to the operation that will be performed on the table. sql/transaction.cc: Global read lock functionality has been moved into a class.
2010-02-01 14:43:06 +03:00
send drop table t2;
--echo # --> connection con2
connection con2;
--echo # Waiting for 'drop table t2' to get blocked...
Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompatible" to be pushed as separate patch. Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. Also replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it more consistent with other thread state names. Updated test cases and their results according to these changes. Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. mysql-test/r/query_cache.result: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/t/query_cache.test: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysys/thr_lock.c: Replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it consistent with thread state names which are used while waiting for metadata locks and table flush. sql/mdl.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/mdl.h: To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/sql_base.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for table flush, with a more elaborate "Waiting for table flush".
2010-08-06 15:29:37 +04:00
let $wait_condition=select count(*)=1 from information_schema.processlist
where state='Waiting for table metadata lock' and
info='drop table t2';
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. mysql-test/include/handler.inc: Adjusted test case to trigger an execution path on which bug 41110 "crash with handler command when used concurrently with alter table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data with alter table" were originally discovered. Left old test case which no longer triggers this execution path for the sake of coverage. Added test coverage for HANDLER SQL statements and type-aware metadata locks. Added a test for the global shared lock and HANDLER SQL. Updated tests to take into account that the old simple deadlock detection heuristics was replaced with a graph-based deadlock detector. mysql-test/r/debug_sync.result: Updated results (see debug_sync.test). mysql-test/r/handler_innodb.result: Updated results (see handler.inc test). mysql-test/r/handler_myisam.result: Updated results (see handler.inc test). mysql-test/r/innodb-lock.result: Updated results (see innodb-lock.test). mysql-test/r/innodb_mysql_lock.result: Updated results (see innodb_mysql_lock.test). mysql-test/r/lock.result: Updated results (see lock.test). mysql-test/r/lock_multi.result: Updated results (see lock_multi.test). mysql-test/r/lock_sync.result: Updated results (see lock_sync.test). mysql-test/r/mdl_sync.result: Updated results (see mdl_sync.test). mysql-test/r/sp-threads.result: SHOW PROCESSLIST output has changed due to the fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/r/truncate_coverage.result: Updated results (see truncate_coverage.test). mysql-test/suite/funcs_1/datadict/processlist_val.inc: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/rpl/t/rpl_sp.test: Updated to a new SHOW PROCESSLIST state name. mysql-test/t/debug_sync.test: Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter no longer allows to trigger execution path involving waiting on thr_lock.c lock and therefore reaching debug sync-point covered by this test. mysql-test/t/innodb-lock.test: Adjusted test case to the fact that innodb_table_locks=0 option is no longer supported, since LOCK TABLES WRITE handles all its conflicts within MDL subsystem. mysql-test/t/innodb_mysql_lock.test: Added test for bug #37346 "innodb does not detect deadlock between update and alter table". mysql-test/t/lock.test: Added test coverage which checks the fact that we no longer support DDL under LOCK TABLES on tables which were locked implicitly. Adjusted existing test cases accordingly. mysql-test/t/lock_multi.test: Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock". Adjusted other test cases to take into account the fact that waiting for LOCK TABLES ... WRITE now happens within MDL subsystem. mysql-test/t/lock_sync.test: Since LOCK TABLES ... WRITE now takes SNRW metadata lock for tables locked explicitly we have to implicitly lock InnoDB tables (through view) to trigger the table-level lock conflict between TL_WRITE and TL_WRITE_ALLOW_WRITE. mysql-test/t/mdl_sync.test: Added basic test coverage for type-of-operation-aware metadata locks. Also covered with tests some use cases involving HANDLER statements in which a deadlock could arise. Adjusted existing tests to take type-of-operation-aware MDL into account. mysql-test/t/multi_update.test: Update to a new SHOW PROCESSLIST state name. mysql-test/t/truncate_coverage.test: Adjusted test case after making LOCK TABLES WRITE to wait until transactions that use the table to be locked are completed. Updated to the changed name of DEBUG_SYNC point. sql/handler.cc: Global read lock functionality has been moved into a class. sql/lock.cc: Global read lock functionality has been moved into a class. Updated code to use the new MDL API. sql/mdl.cc: Introduced new type-of-operation aware metadata locks. To do this: - Changed MDL_lock to use one list for waiting requests and one list for granted requests. For each list, added a bitmap that holds information what lock types a list contains. Added a helper class MDL_lock::List to manipulate with granted and waited lists while keeping the bitmaps in sync with list contents. - Changed lock-compatibility functions to use bitmaps that define compatibility. - Introduced a graph based deadlock detector inspired by waiting_threads.c from Maria implementation. - Now that we have a deadlock detector, and no longer have a global lock to protect individual lock objects, but rather use an rw lock per object, removed redundant code for upgrade, and the global read lock. Changed the MDL API to no longer require the caller to acquire the global intention exclusive lock by means of a separate method. Removed a few more methods that became redundant. - Removed deadlock detection heuristic, it has been made obsolete by the deadlock detector. - With operation-type-aware metadata locks, MDL subsystem has become aware of potential conflicts between DDL and open transactions. This made it possible to remove calls to mysql_abort_transactions_with_shared_lock() from acquisition paths for exclusive lock and lock upgrade. Now we can simply wait for these transactions to complete without fear of deadlock. Function mysql_lock_abort() has also become unnecessary for all conflicting cases except when a DDL conflicts with a connection that has an open HANDLER. sql/mdl.h: Introduced new type-of-operation aware metadata locks. Introduced a graph based deadlock detector and supporting methods. Added comments. God rid of redundant API calls. Renamed m_lt_or_ha_sentinel to m_trans_sentinel, since now it guards the global read lock as well as LOCK TABLES and HANDLER locks. sql/mysql_priv.h: Moved the global read lock functionality into a class. Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces open_tables() to take MDL_SHARED on tables instead of metadata locks specified in the parser. We use this to allow PREPARE run concurrently in presence of LOCK TABLES ... WRITE. Added signature for find_table_for_mdl_ugprade(). sql/set_var.cc: Global read lock functionality has been moved into a class. sql/sp_head.cc: When creating TABLE_LIST elements for prelocking or system tables set the type of request for metadata lock according to the operation that will be performed on the table. sql/sql_base.cc: - Updated code to use the new MDL API. - In order to avoid locks starvation we take upgradable locks all at once. As result implicitly locked tables no longer get an upgradable lock. Consequently DDL and FLUSH TABLES for such tables is prohibited. find_write_locked_table() was replaced by find_table_for_mdl_upgrade() function. open_table() was adjusted to return TABLE instance with upgradable ticket when necessary. - We no longer wait for all locks on OT_WAIT back off action -- only on the lock that caused the wait conflict. Moreover, now we distinguish cases when we have to wait due to conflict in MDL and old version of table in TDC. - Upate mysql_notify_threads_having_share_locks() to only abort thr_lock.c waits of threads that have open HANDLERs, since lock conflicts with only these threads now can lead to deadlocks not detectable by the MDL deadlock detector. - Remove mysql_abort_transactions_with_shared_locks() which is no longer needed. sql/sql_class.cc: Global read lock functionality has been moved into a class. Re-arranged code in THD::cleanup() to simplify assert. sql/sql_class.h: Introduced class to incapsulate global read lock functionality. Now sentinel in MDL subsystem guards the global read lock as well as LOCK TABLES and HANDLER locks. Adjusted code accordingly. sql/sql_db.cc: Global read lock functionality has been moved into a class. sql/sql_delete.cc: We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result TRUNCATE TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_handler.cc: Inform MDL_context about presence of open HANDLERs. Since HANLDERs break MDL protocol by acquiring table-level lock while holding only S metadata lock on a table MDL subsystem should take special care about such contexts (Now this is the only case when mysql_lock_abort() is used). sql/sql_parse.cc: Global read lock functionality has been moved into a class. Do not take upgradable metadata locks when opening tables for CREATE TABLE SELECT as it is not necessary and limits concurrency. When initializing TABLE_LIST objects before adding them to the table list set the type of request for metadata lock according to the operation that will be performed on the table. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result FLUSH TABLES is no longer allowed for such tables. sql/sql_prepare.cc: Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening tables during PREPARE. This allows PREPARE to run concurrently in presence of LOCK TABLES ... WRITE. sql/sql_rename.cc: Global read lock functionality has been moved into a class. sql/sql_show.cc: Updated code to use the new MDL API. sql/sql_table.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result DROP TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_trigger.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result CREATE/DROP TRIGGER is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_view.cc: Global read lock functionality has been moved into a class. Fixed results of wrong merge that led to misuse of GLR API. CREATE VIEW statement is not a commit statement. sql/table.cc: When resetting TABLE_LIST objects for PS or SP re-execution set the type of request for metadata lock according to the operation that will be performed on the table. Do the same in auxiliary function initializing metadata lock requests in a table list. sql/table.h: When initializing TABLE_LIST objects set the type of request for metadata lock according to the operation that will be performed on the table. sql/transaction.cc: Global read lock functionality has been moved into a class.
2010-02-01 14:43:06 +03:00
--source include/wait_condition.inc
--echo # --> connection con1
connection con1;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--error ER_LOCK_DEADLOCK
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. mysql-test/include/handler.inc: Adjusted test case to trigger an execution path on which bug 41110 "crash with handler command when used concurrently with alter table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data with alter table" were originally discovered. Left old test case which no longer triggers this execution path for the sake of coverage. Added test coverage for HANDLER SQL statements and type-aware metadata locks. Added a test for the global shared lock and HANDLER SQL. Updated tests to take into account that the old simple deadlock detection heuristics was replaced with a graph-based deadlock detector. mysql-test/r/debug_sync.result: Updated results (see debug_sync.test). mysql-test/r/handler_innodb.result: Updated results (see handler.inc test). mysql-test/r/handler_myisam.result: Updated results (see handler.inc test). mysql-test/r/innodb-lock.result: Updated results (see innodb-lock.test). mysql-test/r/innodb_mysql_lock.result: Updated results (see innodb_mysql_lock.test). mysql-test/r/lock.result: Updated results (see lock.test). mysql-test/r/lock_multi.result: Updated results (see lock_multi.test). mysql-test/r/lock_sync.result: Updated results (see lock_sync.test). mysql-test/r/mdl_sync.result: Updated results (see mdl_sync.test). mysql-test/r/sp-threads.result: SHOW PROCESSLIST output has changed due to the fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/r/truncate_coverage.result: Updated results (see truncate_coverage.test). mysql-test/suite/funcs_1/datadict/processlist_val.inc: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/rpl/t/rpl_sp.test: Updated to a new SHOW PROCESSLIST state name. mysql-test/t/debug_sync.test: Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter no longer allows to trigger execution path involving waiting on thr_lock.c lock and therefore reaching debug sync-point covered by this test. mysql-test/t/innodb-lock.test: Adjusted test case to the fact that innodb_table_locks=0 option is no longer supported, since LOCK TABLES WRITE handles all its conflicts within MDL subsystem. mysql-test/t/innodb_mysql_lock.test: Added test for bug #37346 "innodb does not detect deadlock between update and alter table". mysql-test/t/lock.test: Added test coverage which checks the fact that we no longer support DDL under LOCK TABLES on tables which were locked implicitly. Adjusted existing test cases accordingly. mysql-test/t/lock_multi.test: Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock". Adjusted other test cases to take into account the fact that waiting for LOCK TABLES ... WRITE now happens within MDL subsystem. mysql-test/t/lock_sync.test: Since LOCK TABLES ... WRITE now takes SNRW metadata lock for tables locked explicitly we have to implicitly lock InnoDB tables (through view) to trigger the table-level lock conflict between TL_WRITE and TL_WRITE_ALLOW_WRITE. mysql-test/t/mdl_sync.test: Added basic test coverage for type-of-operation-aware metadata locks. Also covered with tests some use cases involving HANDLER statements in which a deadlock could arise. Adjusted existing tests to take type-of-operation-aware MDL into account. mysql-test/t/multi_update.test: Update to a new SHOW PROCESSLIST state name. mysql-test/t/truncate_coverage.test: Adjusted test case after making LOCK TABLES WRITE to wait until transactions that use the table to be locked are completed. Updated to the changed name of DEBUG_SYNC point. sql/handler.cc: Global read lock functionality has been moved into a class. sql/lock.cc: Global read lock functionality has been moved into a class. Updated code to use the new MDL API. sql/mdl.cc: Introduced new type-of-operation aware metadata locks. To do this: - Changed MDL_lock to use one list for waiting requests and one list for granted requests. For each list, added a bitmap that holds information what lock types a list contains. Added a helper class MDL_lock::List to manipulate with granted and waited lists while keeping the bitmaps in sync with list contents. - Changed lock-compatibility functions to use bitmaps that define compatibility. - Introduced a graph based deadlock detector inspired by waiting_threads.c from Maria implementation. - Now that we have a deadlock detector, and no longer have a global lock to protect individual lock objects, but rather use an rw lock per object, removed redundant code for upgrade, and the global read lock. Changed the MDL API to no longer require the caller to acquire the global intention exclusive lock by means of a separate method. Removed a few more methods that became redundant. - Removed deadlock detection heuristic, it has been made obsolete by the deadlock detector. - With operation-type-aware metadata locks, MDL subsystem has become aware of potential conflicts between DDL and open transactions. This made it possible to remove calls to mysql_abort_transactions_with_shared_lock() from acquisition paths for exclusive lock and lock upgrade. Now we can simply wait for these transactions to complete without fear of deadlock. Function mysql_lock_abort() has also become unnecessary for all conflicting cases except when a DDL conflicts with a connection that has an open HANDLER. sql/mdl.h: Introduced new type-of-operation aware metadata locks. Introduced a graph based deadlock detector and supporting methods. Added comments. God rid of redundant API calls. Renamed m_lt_or_ha_sentinel to m_trans_sentinel, since now it guards the global read lock as well as LOCK TABLES and HANDLER locks. sql/mysql_priv.h: Moved the global read lock functionality into a class. Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces open_tables() to take MDL_SHARED on tables instead of metadata locks specified in the parser. We use this to allow PREPARE run concurrently in presence of LOCK TABLES ... WRITE. Added signature for find_table_for_mdl_ugprade(). sql/set_var.cc: Global read lock functionality has been moved into a class. sql/sp_head.cc: When creating TABLE_LIST elements for prelocking or system tables set the type of request for metadata lock according to the operation that will be performed on the table. sql/sql_base.cc: - Updated code to use the new MDL API. - In order to avoid locks starvation we take upgradable locks all at once. As result implicitly locked tables no longer get an upgradable lock. Consequently DDL and FLUSH TABLES for such tables is prohibited. find_write_locked_table() was replaced by find_table_for_mdl_upgrade() function. open_table() was adjusted to return TABLE instance with upgradable ticket when necessary. - We no longer wait for all locks on OT_WAIT back off action -- only on the lock that caused the wait conflict. Moreover, now we distinguish cases when we have to wait due to conflict in MDL and old version of table in TDC. - Upate mysql_notify_threads_having_share_locks() to only abort thr_lock.c waits of threads that have open HANDLERs, since lock conflicts with only these threads now can lead to deadlocks not detectable by the MDL deadlock detector. - Remove mysql_abort_transactions_with_shared_locks() which is no longer needed. sql/sql_class.cc: Global read lock functionality has been moved into a class. Re-arranged code in THD::cleanup() to simplify assert. sql/sql_class.h: Introduced class to incapsulate global read lock functionality. Now sentinel in MDL subsystem guards the global read lock as well as LOCK TABLES and HANDLER locks. Adjusted code accordingly. sql/sql_db.cc: Global read lock functionality has been moved into a class. sql/sql_delete.cc: We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result TRUNCATE TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_handler.cc: Inform MDL_context about presence of open HANDLERs. Since HANLDERs break MDL protocol by acquiring table-level lock while holding only S metadata lock on a table MDL subsystem should take special care about such contexts (Now this is the only case when mysql_lock_abort() is used). sql/sql_parse.cc: Global read lock functionality has been moved into a class. Do not take upgradable metadata locks when opening tables for CREATE TABLE SELECT as it is not necessary and limits concurrency. When initializing TABLE_LIST objects before adding them to the table list set the type of request for metadata lock according to the operation that will be performed on the table. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result FLUSH TABLES is no longer allowed for such tables. sql/sql_prepare.cc: Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening tables during PREPARE. This allows PREPARE to run concurrently in presence of LOCK TABLES ... WRITE. sql/sql_rename.cc: Global read lock functionality has been moved into a class. sql/sql_show.cc: Updated code to use the new MDL API. sql/sql_table.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result DROP TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_trigger.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result CREATE/DROP TRIGGER is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_view.cc: Global read lock functionality has been moved into a class. Fixed results of wrong merge that led to misuse of GLR API. CREATE VIEW statement is not a commit statement. sql/table.cc: When resetting TABLE_LIST objects for PS or SP re-execution set the type of request for metadata lock according to the operation that will be performed on the table. Do the same in auxiliary function initializing metadata lock requests in a table list. sql/table.h: When initializing TABLE_LIST objects set the type of request for metadata lock according to the operation that will be performed on the table. sql/transaction.cc: Global read lock functionality has been moved into a class.
2010-02-01 14:43:06 +03:00
drop table t1;
unlock tables;
--echo # --> connection default
connection default;
reap;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo # Demonstrate that there is no deadlock with FLUSH TABLE,
--echo # even though it is waiting for the other table to go away
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. mysql-test/include/handler.inc: Adjusted test case to trigger an execution path on which bug 41110 "crash with handler command when used concurrently with alter table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data with alter table" were originally discovered. Left old test case which no longer triggers this execution path for the sake of coverage. Added test coverage for HANDLER SQL statements and type-aware metadata locks. Added a test for the global shared lock and HANDLER SQL. Updated tests to take into account that the old simple deadlock detection heuristics was replaced with a graph-based deadlock detector. mysql-test/r/debug_sync.result: Updated results (see debug_sync.test). mysql-test/r/handler_innodb.result: Updated results (see handler.inc test). mysql-test/r/handler_myisam.result: Updated results (see handler.inc test). mysql-test/r/innodb-lock.result: Updated results (see innodb-lock.test). mysql-test/r/innodb_mysql_lock.result: Updated results (see innodb_mysql_lock.test). mysql-test/r/lock.result: Updated results (see lock.test). mysql-test/r/lock_multi.result: Updated results (see lock_multi.test). mysql-test/r/lock_sync.result: Updated results (see lock_sync.test). mysql-test/r/mdl_sync.result: Updated results (see mdl_sync.test). mysql-test/r/sp-threads.result: SHOW PROCESSLIST output has changed due to the fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/r/truncate_coverage.result: Updated results (see truncate_coverage.test). mysql-test/suite/funcs_1/datadict/processlist_val.inc: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/rpl/t/rpl_sp.test: Updated to a new SHOW PROCESSLIST state name. mysql-test/t/debug_sync.test: Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter no longer allows to trigger execution path involving waiting on thr_lock.c lock and therefore reaching debug sync-point covered by this test. mysql-test/t/innodb-lock.test: Adjusted test case to the fact that innodb_table_locks=0 option is no longer supported, since LOCK TABLES WRITE handles all its conflicts within MDL subsystem. mysql-test/t/innodb_mysql_lock.test: Added test for bug #37346 "innodb does not detect deadlock between update and alter table". mysql-test/t/lock.test: Added test coverage which checks the fact that we no longer support DDL under LOCK TABLES on tables which were locked implicitly. Adjusted existing test cases accordingly. mysql-test/t/lock_multi.test: Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock". Adjusted other test cases to take into account the fact that waiting for LOCK TABLES ... WRITE now happens within MDL subsystem. mysql-test/t/lock_sync.test: Since LOCK TABLES ... WRITE now takes SNRW metadata lock for tables locked explicitly we have to implicitly lock InnoDB tables (through view) to trigger the table-level lock conflict between TL_WRITE and TL_WRITE_ALLOW_WRITE. mysql-test/t/mdl_sync.test: Added basic test coverage for type-of-operation-aware metadata locks. Also covered with tests some use cases involving HANDLER statements in which a deadlock could arise. Adjusted existing tests to take type-of-operation-aware MDL into account. mysql-test/t/multi_update.test: Update to a new SHOW PROCESSLIST state name. mysql-test/t/truncate_coverage.test: Adjusted test case after making LOCK TABLES WRITE to wait until transactions that use the table to be locked are completed. Updated to the changed name of DEBUG_SYNC point. sql/handler.cc: Global read lock functionality has been moved into a class. sql/lock.cc: Global read lock functionality has been moved into a class. Updated code to use the new MDL API. sql/mdl.cc: Introduced new type-of-operation aware metadata locks. To do this: - Changed MDL_lock to use one list for waiting requests and one list for granted requests. For each list, added a bitmap that holds information what lock types a list contains. Added a helper class MDL_lock::List to manipulate with granted and waited lists while keeping the bitmaps in sync with list contents. - Changed lock-compatibility functions to use bitmaps that define compatibility. - Introduced a graph based deadlock detector inspired by waiting_threads.c from Maria implementation. - Now that we have a deadlock detector, and no longer have a global lock to protect individual lock objects, but rather use an rw lock per object, removed redundant code for upgrade, and the global read lock. Changed the MDL API to no longer require the caller to acquire the global intention exclusive lock by means of a separate method. Removed a few more methods that became redundant. - Removed deadlock detection heuristic, it has been made obsolete by the deadlock detector. - With operation-type-aware metadata locks, MDL subsystem has become aware of potential conflicts between DDL and open transactions. This made it possible to remove calls to mysql_abort_transactions_with_shared_lock() from acquisition paths for exclusive lock and lock upgrade. Now we can simply wait for these transactions to complete without fear of deadlock. Function mysql_lock_abort() has also become unnecessary for all conflicting cases except when a DDL conflicts with a connection that has an open HANDLER. sql/mdl.h: Introduced new type-of-operation aware metadata locks. Introduced a graph based deadlock detector and supporting methods. Added comments. God rid of redundant API calls. Renamed m_lt_or_ha_sentinel to m_trans_sentinel, since now it guards the global read lock as well as LOCK TABLES and HANDLER locks. sql/mysql_priv.h: Moved the global read lock functionality into a class. Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces open_tables() to take MDL_SHARED on tables instead of metadata locks specified in the parser. We use this to allow PREPARE run concurrently in presence of LOCK TABLES ... WRITE. Added signature for find_table_for_mdl_ugprade(). sql/set_var.cc: Global read lock functionality has been moved into a class. sql/sp_head.cc: When creating TABLE_LIST elements for prelocking or system tables set the type of request for metadata lock according to the operation that will be performed on the table. sql/sql_base.cc: - Updated code to use the new MDL API. - In order to avoid locks starvation we take upgradable locks all at once. As result implicitly locked tables no longer get an upgradable lock. Consequently DDL and FLUSH TABLES for such tables is prohibited. find_write_locked_table() was replaced by find_table_for_mdl_upgrade() function. open_table() was adjusted to return TABLE instance with upgradable ticket when necessary. - We no longer wait for all locks on OT_WAIT back off action -- only on the lock that caused the wait conflict. Moreover, now we distinguish cases when we have to wait due to conflict in MDL and old version of table in TDC. - Upate mysql_notify_threads_having_share_locks() to only abort thr_lock.c waits of threads that have open HANDLERs, since lock conflicts with only these threads now can lead to deadlocks not detectable by the MDL deadlock detector. - Remove mysql_abort_transactions_with_shared_locks() which is no longer needed. sql/sql_class.cc: Global read lock functionality has been moved into a class. Re-arranged code in THD::cleanup() to simplify assert. sql/sql_class.h: Introduced class to incapsulate global read lock functionality. Now sentinel in MDL subsystem guards the global read lock as well as LOCK TABLES and HANDLER locks. Adjusted code accordingly. sql/sql_db.cc: Global read lock functionality has been moved into a class. sql/sql_delete.cc: We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result TRUNCATE TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_handler.cc: Inform MDL_context about presence of open HANDLERs. Since HANLDERs break MDL protocol by acquiring table-level lock while holding only S metadata lock on a table MDL subsystem should take special care about such contexts (Now this is the only case when mysql_lock_abort() is used). sql/sql_parse.cc: Global read lock functionality has been moved into a class. Do not take upgradable metadata locks when opening tables for CREATE TABLE SELECT as it is not necessary and limits concurrency. When initializing TABLE_LIST objects before adding them to the table list set the type of request for metadata lock according to the operation that will be performed on the table. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result FLUSH TABLES is no longer allowed for such tables. sql/sql_prepare.cc: Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening tables during PREPARE. This allows PREPARE to run concurrently in presence of LOCK TABLES ... WRITE. sql/sql_rename.cc: Global read lock functionality has been moved into a class. sql/sql_show.cc: Updated code to use the new MDL API. sql/sql_table.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result DROP TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_trigger.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result CREATE/DROP TRIGGER is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_view.cc: Global read lock functionality has been moved into a class. Fixed results of wrong merge that led to misuse of GLR API. CREATE VIEW statement is not a commit statement. sql/table.cc: When resetting TABLE_LIST objects for PS or SP re-execution set the type of request for metadata lock according to the operation that will be performed on the table. Do the same in auxiliary function initializing metadata lock requests in a table list. sql/table.h: When initializing TABLE_LIST objects set the type of request for metadata lock according to the operation that will be performed on the table. sql/transaction.cc: Global read lock functionality has been moved into a class.
2010-02-01 14:43:06 +03:00
create table t2 like t1;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo # Sending:
--send flush table t2
--echo # --> connection con2
connection con2;
drop table t1;
--echo # --> connection con1
connection con1;
unlock tables;
--echo # --> connection default
connection default;
--echo # Reaping 'flush table t2'...
--reap
drop table t2;
--echo #
--echo # Bug #46224 HANDLER statements within a transaction might
--echo # lead to deadlocks
--echo #
create table t1 (a int, key using btree (a));
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. mysql-test/include/handler.inc: Adjusted test case to trigger an execution path on which bug 41110 "crash with handler command when used concurrently with alter table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data with alter table" were originally discovered. Left old test case which no longer triggers this execution path for the sake of coverage. Added test coverage for HANDLER SQL statements and type-aware metadata locks. Added a test for the global shared lock and HANDLER SQL. Updated tests to take into account that the old simple deadlock detection heuristics was replaced with a graph-based deadlock detector. mysql-test/r/debug_sync.result: Updated results (see debug_sync.test). mysql-test/r/handler_innodb.result: Updated results (see handler.inc test). mysql-test/r/handler_myisam.result: Updated results (see handler.inc test). mysql-test/r/innodb-lock.result: Updated results (see innodb-lock.test). mysql-test/r/innodb_mysql_lock.result: Updated results (see innodb_mysql_lock.test). mysql-test/r/lock.result: Updated results (see lock.test). mysql-test/r/lock_multi.result: Updated results (see lock_multi.test). mysql-test/r/lock_sync.result: Updated results (see lock_sync.test). mysql-test/r/mdl_sync.result: Updated results (see mdl_sync.test). mysql-test/r/sp-threads.result: SHOW PROCESSLIST output has changed due to the fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/r/truncate_coverage.result: Updated results (see truncate_coverage.test). mysql-test/suite/funcs_1/datadict/processlist_val.inc: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/rpl/t/rpl_sp.test: Updated to a new SHOW PROCESSLIST state name. mysql-test/t/debug_sync.test: Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter no longer allows to trigger execution path involving waiting on thr_lock.c lock and therefore reaching debug sync-point covered by this test. mysql-test/t/innodb-lock.test: Adjusted test case to the fact that innodb_table_locks=0 option is no longer supported, since LOCK TABLES WRITE handles all its conflicts within MDL subsystem. mysql-test/t/innodb_mysql_lock.test: Added test for bug #37346 "innodb does not detect deadlock between update and alter table". mysql-test/t/lock.test: Added test coverage which checks the fact that we no longer support DDL under LOCK TABLES on tables which were locked implicitly. Adjusted existing test cases accordingly. mysql-test/t/lock_multi.test: Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock". Adjusted other test cases to take into account the fact that waiting for LOCK TABLES ... WRITE now happens within MDL subsystem. mysql-test/t/lock_sync.test: Since LOCK TABLES ... WRITE now takes SNRW metadata lock for tables locked explicitly we have to implicitly lock InnoDB tables (through view) to trigger the table-level lock conflict between TL_WRITE and TL_WRITE_ALLOW_WRITE. mysql-test/t/mdl_sync.test: Added basic test coverage for type-of-operation-aware metadata locks. Also covered with tests some use cases involving HANDLER statements in which a deadlock could arise. Adjusted existing tests to take type-of-operation-aware MDL into account. mysql-test/t/multi_update.test: Update to a new SHOW PROCESSLIST state name. mysql-test/t/truncate_coverage.test: Adjusted test case after making LOCK TABLES WRITE to wait until transactions that use the table to be locked are completed. Updated to the changed name of DEBUG_SYNC point. sql/handler.cc: Global read lock functionality has been moved into a class. sql/lock.cc: Global read lock functionality has been moved into a class. Updated code to use the new MDL API. sql/mdl.cc: Introduced new type-of-operation aware metadata locks. To do this: - Changed MDL_lock to use one list for waiting requests and one list for granted requests. For each list, added a bitmap that holds information what lock types a list contains. Added a helper class MDL_lock::List to manipulate with granted and waited lists while keeping the bitmaps in sync with list contents. - Changed lock-compatibility functions to use bitmaps that define compatibility. - Introduced a graph based deadlock detector inspired by waiting_threads.c from Maria implementation. - Now that we have a deadlock detector, and no longer have a global lock to protect individual lock objects, but rather use an rw lock per object, removed redundant code for upgrade, and the global read lock. Changed the MDL API to no longer require the caller to acquire the global intention exclusive lock by means of a separate method. Removed a few more methods that became redundant. - Removed deadlock detection heuristic, it has been made obsolete by the deadlock detector. - With operation-type-aware metadata locks, MDL subsystem has become aware of potential conflicts between DDL and open transactions. This made it possible to remove calls to mysql_abort_transactions_with_shared_lock() from acquisition paths for exclusive lock and lock upgrade. Now we can simply wait for these transactions to complete without fear of deadlock. Function mysql_lock_abort() has also become unnecessary for all conflicting cases except when a DDL conflicts with a connection that has an open HANDLER. sql/mdl.h: Introduced new type-of-operation aware metadata locks. Introduced a graph based deadlock detector and supporting methods. Added comments. God rid of redundant API calls. Renamed m_lt_or_ha_sentinel to m_trans_sentinel, since now it guards the global read lock as well as LOCK TABLES and HANDLER locks. sql/mysql_priv.h: Moved the global read lock functionality into a class. Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces open_tables() to take MDL_SHARED on tables instead of metadata locks specified in the parser. We use this to allow PREPARE run concurrently in presence of LOCK TABLES ... WRITE. Added signature for find_table_for_mdl_ugprade(). sql/set_var.cc: Global read lock functionality has been moved into a class. sql/sp_head.cc: When creating TABLE_LIST elements for prelocking or system tables set the type of request for metadata lock according to the operation that will be performed on the table. sql/sql_base.cc: - Updated code to use the new MDL API. - In order to avoid locks starvation we take upgradable locks all at once. As result implicitly locked tables no longer get an upgradable lock. Consequently DDL and FLUSH TABLES for such tables is prohibited. find_write_locked_table() was replaced by find_table_for_mdl_upgrade() function. open_table() was adjusted to return TABLE instance with upgradable ticket when necessary. - We no longer wait for all locks on OT_WAIT back off action -- only on the lock that caused the wait conflict. Moreover, now we distinguish cases when we have to wait due to conflict in MDL and old version of table in TDC. - Upate mysql_notify_threads_having_share_locks() to only abort thr_lock.c waits of threads that have open HANDLERs, since lock conflicts with only these threads now can lead to deadlocks not detectable by the MDL deadlock detector. - Remove mysql_abort_transactions_with_shared_locks() which is no longer needed. sql/sql_class.cc: Global read lock functionality has been moved into a class. Re-arranged code in THD::cleanup() to simplify assert. sql/sql_class.h: Introduced class to incapsulate global read lock functionality. Now sentinel in MDL subsystem guards the global read lock as well as LOCK TABLES and HANDLER locks. Adjusted code accordingly. sql/sql_db.cc: Global read lock functionality has been moved into a class. sql/sql_delete.cc: We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result TRUNCATE TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_handler.cc: Inform MDL_context about presence of open HANDLERs. Since HANLDERs break MDL protocol by acquiring table-level lock while holding only S metadata lock on a table MDL subsystem should take special care about such contexts (Now this is the only case when mysql_lock_abort() is used). sql/sql_parse.cc: Global read lock functionality has been moved into a class. Do not take upgradable metadata locks when opening tables for CREATE TABLE SELECT as it is not necessary and limits concurrency. When initializing TABLE_LIST objects before adding them to the table list set the type of request for metadata lock according to the operation that will be performed on the table. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result FLUSH TABLES is no longer allowed for such tables. sql/sql_prepare.cc: Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening tables during PREPARE. This allows PREPARE to run concurrently in presence of LOCK TABLES ... WRITE. sql/sql_rename.cc: Global read lock functionality has been moved into a class. sql/sql_show.cc: Updated code to use the new MDL API. sql/sql_table.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result DROP TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_trigger.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result CREATE/DROP TRIGGER is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_view.cc: Global read lock functionality has been moved into a class. Fixed results of wrong merge that led to misuse of GLR API. CREATE VIEW statement is not a commit statement. sql/table.cc: When resetting TABLE_LIST objects for PS or SP re-execution set the type of request for metadata lock according to the operation that will be performed on the table. Do the same in auxiliary function initializing metadata lock requests in a table list. sql/table.h: When initializing TABLE_LIST objects set the type of request for metadata lock according to the operation that will be performed on the table. sql/transaction.cc: Global read lock functionality has been moved into a class.
2010-02-01 14:43:06 +03:00
insert into t1 values (1), (2);
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo # --> connection default
connection default;
begin;
select * from t1;
handler t1 open;
--echo # --> connection con1
connection con1;
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. mysql-test/include/handler.inc: Adjusted test case to trigger an execution path on which bug 41110 "crash with handler command when used concurrently with alter table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data with alter table" were originally discovered. Left old test case which no longer triggers this execution path for the sake of coverage. Added test coverage for HANDLER SQL statements and type-aware metadata locks. Added a test for the global shared lock and HANDLER SQL. Updated tests to take into account that the old simple deadlock detection heuristics was replaced with a graph-based deadlock detector. mysql-test/r/debug_sync.result: Updated results (see debug_sync.test). mysql-test/r/handler_innodb.result: Updated results (see handler.inc test). mysql-test/r/handler_myisam.result: Updated results (see handler.inc test). mysql-test/r/innodb-lock.result: Updated results (see innodb-lock.test). mysql-test/r/innodb_mysql_lock.result: Updated results (see innodb_mysql_lock.test). mysql-test/r/lock.result: Updated results (see lock.test). mysql-test/r/lock_multi.result: Updated results (see lock_multi.test). mysql-test/r/lock_sync.result: Updated results (see lock_sync.test). mysql-test/r/mdl_sync.result: Updated results (see mdl_sync.test). mysql-test/r/sp-threads.result: SHOW PROCESSLIST output has changed due to the fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/r/truncate_coverage.result: Updated results (see truncate_coverage.test). mysql-test/suite/funcs_1/datadict/processlist_val.inc: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/rpl/t/rpl_sp.test: Updated to a new SHOW PROCESSLIST state name. mysql-test/t/debug_sync.test: Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter no longer allows to trigger execution path involving waiting on thr_lock.c lock and therefore reaching debug sync-point covered by this test. mysql-test/t/innodb-lock.test: Adjusted test case to the fact that innodb_table_locks=0 option is no longer supported, since LOCK TABLES WRITE handles all its conflicts within MDL subsystem. mysql-test/t/innodb_mysql_lock.test: Added test for bug #37346 "innodb does not detect deadlock between update and alter table". mysql-test/t/lock.test: Added test coverage which checks the fact that we no longer support DDL under LOCK TABLES on tables which were locked implicitly. Adjusted existing test cases accordingly. mysql-test/t/lock_multi.test: Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock". Adjusted other test cases to take into account the fact that waiting for LOCK TABLES ... WRITE now happens within MDL subsystem. mysql-test/t/lock_sync.test: Since LOCK TABLES ... WRITE now takes SNRW metadata lock for tables locked explicitly we have to implicitly lock InnoDB tables (through view) to trigger the table-level lock conflict between TL_WRITE and TL_WRITE_ALLOW_WRITE. mysql-test/t/mdl_sync.test: Added basic test coverage for type-of-operation-aware metadata locks. Also covered with tests some use cases involving HANDLER statements in which a deadlock could arise. Adjusted existing tests to take type-of-operation-aware MDL into account. mysql-test/t/multi_update.test: Update to a new SHOW PROCESSLIST state name. mysql-test/t/truncate_coverage.test: Adjusted test case after making LOCK TABLES WRITE to wait until transactions that use the table to be locked are completed. Updated to the changed name of DEBUG_SYNC point. sql/handler.cc: Global read lock functionality has been moved into a class. sql/lock.cc: Global read lock functionality has been moved into a class. Updated code to use the new MDL API. sql/mdl.cc: Introduced new type-of-operation aware metadata locks. To do this: - Changed MDL_lock to use one list for waiting requests and one list for granted requests. For each list, added a bitmap that holds information what lock types a list contains. Added a helper class MDL_lock::List to manipulate with granted and waited lists while keeping the bitmaps in sync with list contents. - Changed lock-compatibility functions to use bitmaps that define compatibility. - Introduced a graph based deadlock detector inspired by waiting_threads.c from Maria implementation. - Now that we have a deadlock detector, and no longer have a global lock to protect individual lock objects, but rather use an rw lock per object, removed redundant code for upgrade, and the global read lock. Changed the MDL API to no longer require the caller to acquire the global intention exclusive lock by means of a separate method. Removed a few more methods that became redundant. - Removed deadlock detection heuristic, it has been made obsolete by the deadlock detector. - With operation-type-aware metadata locks, MDL subsystem has become aware of potential conflicts between DDL and open transactions. This made it possible to remove calls to mysql_abort_transactions_with_shared_lock() from acquisition paths for exclusive lock and lock upgrade. Now we can simply wait for these transactions to complete without fear of deadlock. Function mysql_lock_abort() has also become unnecessary for all conflicting cases except when a DDL conflicts with a connection that has an open HANDLER. sql/mdl.h: Introduced new type-of-operation aware metadata locks. Introduced a graph based deadlock detector and supporting methods. Added comments. God rid of redundant API calls. Renamed m_lt_or_ha_sentinel to m_trans_sentinel, since now it guards the global read lock as well as LOCK TABLES and HANDLER locks. sql/mysql_priv.h: Moved the global read lock functionality into a class. Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces open_tables() to take MDL_SHARED on tables instead of metadata locks specified in the parser. We use this to allow PREPARE run concurrently in presence of LOCK TABLES ... WRITE. Added signature for find_table_for_mdl_ugprade(). sql/set_var.cc: Global read lock functionality has been moved into a class. sql/sp_head.cc: When creating TABLE_LIST elements for prelocking or system tables set the type of request for metadata lock according to the operation that will be performed on the table. sql/sql_base.cc: - Updated code to use the new MDL API. - In order to avoid locks starvation we take upgradable locks all at once. As result implicitly locked tables no longer get an upgradable lock. Consequently DDL and FLUSH TABLES for such tables is prohibited. find_write_locked_table() was replaced by find_table_for_mdl_upgrade() function. open_table() was adjusted to return TABLE instance with upgradable ticket when necessary. - We no longer wait for all locks on OT_WAIT back off action -- only on the lock that caused the wait conflict. Moreover, now we distinguish cases when we have to wait due to conflict in MDL and old version of table in TDC. - Upate mysql_notify_threads_having_share_locks() to only abort thr_lock.c waits of threads that have open HANDLERs, since lock conflicts with only these threads now can lead to deadlocks not detectable by the MDL deadlock detector. - Remove mysql_abort_transactions_with_shared_locks() which is no longer needed. sql/sql_class.cc: Global read lock functionality has been moved into a class. Re-arranged code in THD::cleanup() to simplify assert. sql/sql_class.h: Introduced class to incapsulate global read lock functionality. Now sentinel in MDL subsystem guards the global read lock as well as LOCK TABLES and HANDLER locks. Adjusted code accordingly. sql/sql_db.cc: Global read lock functionality has been moved into a class. sql/sql_delete.cc: We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result TRUNCATE TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_handler.cc: Inform MDL_context about presence of open HANDLERs. Since HANLDERs break MDL protocol by acquiring table-level lock while holding only S metadata lock on a table MDL subsystem should take special care about such contexts (Now this is the only case when mysql_lock_abort() is used). sql/sql_parse.cc: Global read lock functionality has been moved into a class. Do not take upgradable metadata locks when opening tables for CREATE TABLE SELECT as it is not necessary and limits concurrency. When initializing TABLE_LIST objects before adding them to the table list set the type of request for metadata lock according to the operation that will be performed on the table. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result FLUSH TABLES is no longer allowed for such tables. sql/sql_prepare.cc: Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening tables during PREPARE. This allows PREPARE to run concurrently in presence of LOCK TABLES ... WRITE. sql/sql_rename.cc: Global read lock functionality has been moved into a class. sql/sql_show.cc: Updated code to use the new MDL API. sql/sql_table.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result DROP TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_trigger.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result CREATE/DROP TRIGGER is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_view.cc: Global read lock functionality has been moved into a class. Fixed results of wrong merge that led to misuse of GLR API. CREATE VIEW statement is not a commit statement. sql/table.cc: When resetting TABLE_LIST objects for PS or SP re-execution set the type of request for metadata lock according to the operation that will be performed on the table. Do the same in auxiliary function initializing metadata lock requests in a table list. sql/table.h: When initializing TABLE_LIST objects set the type of request for metadata lock according to the operation that will be performed on the table. sql/transaction.cc: Global read lock functionality has been moved into a class.
2010-02-01 14:43:06 +03:00
--echo # Sending:
--send lock tables t1 write
--echo # --> connection con2
connection con2;
--echo # Check that 'lock tables t1 write' waits until transaction which
--echo # has read from the table commits.
let $wait_condition=
select count(*) = 1 from information_schema.processlist
Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompatible" to be pushed as separate patch. Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. Also replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it more consistent with other thread state names. Updated test cases and their results according to these changes. Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. mysql-test/r/query_cache.result: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/t/query_cache.test: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysys/thr_lock.c: Replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it consistent with thread state names which are used while waiting for metadata locks and table flush. sql/mdl.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/mdl.h: To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/sql_base.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for table flush, with a more elaborate "Waiting for table flush".
2010-08-06 15:29:37 +04:00
where state = "Waiting for table metadata lock" and
info = "lock tables t1 write";
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. mysql-test/include/handler.inc: Adjusted test case to trigger an execution path on which bug 41110 "crash with handler command when used concurrently with alter table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data with alter table" were originally discovered. Left old test case which no longer triggers this execution path for the sake of coverage. Added test coverage for HANDLER SQL statements and type-aware metadata locks. Added a test for the global shared lock and HANDLER SQL. Updated tests to take into account that the old simple deadlock detection heuristics was replaced with a graph-based deadlock detector. mysql-test/r/debug_sync.result: Updated results (see debug_sync.test). mysql-test/r/handler_innodb.result: Updated results (see handler.inc test). mysql-test/r/handler_myisam.result: Updated results (see handler.inc test). mysql-test/r/innodb-lock.result: Updated results (see innodb-lock.test). mysql-test/r/innodb_mysql_lock.result: Updated results (see innodb_mysql_lock.test). mysql-test/r/lock.result: Updated results (see lock.test). mysql-test/r/lock_multi.result: Updated results (see lock_multi.test). mysql-test/r/lock_sync.result: Updated results (see lock_sync.test). mysql-test/r/mdl_sync.result: Updated results (see mdl_sync.test). mysql-test/r/sp-threads.result: SHOW PROCESSLIST output has changed due to the fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/r/truncate_coverage.result: Updated results (see truncate_coverage.test). mysql-test/suite/funcs_1/datadict/processlist_val.inc: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/rpl/t/rpl_sp.test: Updated to a new SHOW PROCESSLIST state name. mysql-test/t/debug_sync.test: Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter no longer allows to trigger execution path involving waiting on thr_lock.c lock and therefore reaching debug sync-point covered by this test. mysql-test/t/innodb-lock.test: Adjusted test case to the fact that innodb_table_locks=0 option is no longer supported, since LOCK TABLES WRITE handles all its conflicts within MDL subsystem. mysql-test/t/innodb_mysql_lock.test: Added test for bug #37346 "innodb does not detect deadlock between update and alter table". mysql-test/t/lock.test: Added test coverage which checks the fact that we no longer support DDL under LOCK TABLES on tables which were locked implicitly. Adjusted existing test cases accordingly. mysql-test/t/lock_multi.test: Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock". Adjusted other test cases to take into account the fact that waiting for LOCK TABLES ... WRITE now happens within MDL subsystem. mysql-test/t/lock_sync.test: Since LOCK TABLES ... WRITE now takes SNRW metadata lock for tables locked explicitly we have to implicitly lock InnoDB tables (through view) to trigger the table-level lock conflict between TL_WRITE and TL_WRITE_ALLOW_WRITE. mysql-test/t/mdl_sync.test: Added basic test coverage for type-of-operation-aware metadata locks. Also covered with tests some use cases involving HANDLER statements in which a deadlock could arise. Adjusted existing tests to take type-of-operation-aware MDL into account. mysql-test/t/multi_update.test: Update to a new SHOW PROCESSLIST state name. mysql-test/t/truncate_coverage.test: Adjusted test case after making LOCK TABLES WRITE to wait until transactions that use the table to be locked are completed. Updated to the changed name of DEBUG_SYNC point. sql/handler.cc: Global read lock functionality has been moved into a class. sql/lock.cc: Global read lock functionality has been moved into a class. Updated code to use the new MDL API. sql/mdl.cc: Introduced new type-of-operation aware metadata locks. To do this: - Changed MDL_lock to use one list for waiting requests and one list for granted requests. For each list, added a bitmap that holds information what lock types a list contains. Added a helper class MDL_lock::List to manipulate with granted and waited lists while keeping the bitmaps in sync with list contents. - Changed lock-compatibility functions to use bitmaps that define compatibility. - Introduced a graph based deadlock detector inspired by waiting_threads.c from Maria implementation. - Now that we have a deadlock detector, and no longer have a global lock to protect individual lock objects, but rather use an rw lock per object, removed redundant code for upgrade, and the global read lock. Changed the MDL API to no longer require the caller to acquire the global intention exclusive lock by means of a separate method. Removed a few more methods that became redundant. - Removed deadlock detection heuristic, it has been made obsolete by the deadlock detector. - With operation-type-aware metadata locks, MDL subsystem has become aware of potential conflicts between DDL and open transactions. This made it possible to remove calls to mysql_abort_transactions_with_shared_lock() from acquisition paths for exclusive lock and lock upgrade. Now we can simply wait for these transactions to complete without fear of deadlock. Function mysql_lock_abort() has also become unnecessary for all conflicting cases except when a DDL conflicts with a connection that has an open HANDLER. sql/mdl.h: Introduced new type-of-operation aware metadata locks. Introduced a graph based deadlock detector and supporting methods. Added comments. God rid of redundant API calls. Renamed m_lt_or_ha_sentinel to m_trans_sentinel, since now it guards the global read lock as well as LOCK TABLES and HANDLER locks. sql/mysql_priv.h: Moved the global read lock functionality into a class. Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces open_tables() to take MDL_SHARED on tables instead of metadata locks specified in the parser. We use this to allow PREPARE run concurrently in presence of LOCK TABLES ... WRITE. Added signature for find_table_for_mdl_ugprade(). sql/set_var.cc: Global read lock functionality has been moved into a class. sql/sp_head.cc: When creating TABLE_LIST elements for prelocking or system tables set the type of request for metadata lock according to the operation that will be performed on the table. sql/sql_base.cc: - Updated code to use the new MDL API. - In order to avoid locks starvation we take upgradable locks all at once. As result implicitly locked tables no longer get an upgradable lock. Consequently DDL and FLUSH TABLES for such tables is prohibited. find_write_locked_table() was replaced by find_table_for_mdl_upgrade() function. open_table() was adjusted to return TABLE instance with upgradable ticket when necessary. - We no longer wait for all locks on OT_WAIT back off action -- only on the lock that caused the wait conflict. Moreover, now we distinguish cases when we have to wait due to conflict in MDL and old version of table in TDC. - Upate mysql_notify_threads_having_share_locks() to only abort thr_lock.c waits of threads that have open HANDLERs, since lock conflicts with only these threads now can lead to deadlocks not detectable by the MDL deadlock detector. - Remove mysql_abort_transactions_with_shared_locks() which is no longer needed. sql/sql_class.cc: Global read lock functionality has been moved into a class. Re-arranged code in THD::cleanup() to simplify assert. sql/sql_class.h: Introduced class to incapsulate global read lock functionality. Now sentinel in MDL subsystem guards the global read lock as well as LOCK TABLES and HANDLER locks. Adjusted code accordingly. sql/sql_db.cc: Global read lock functionality has been moved into a class. sql/sql_delete.cc: We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result TRUNCATE TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_handler.cc: Inform MDL_context about presence of open HANDLERs. Since HANLDERs break MDL protocol by acquiring table-level lock while holding only S metadata lock on a table MDL subsystem should take special care about such contexts (Now this is the only case when mysql_lock_abort() is used). sql/sql_parse.cc: Global read lock functionality has been moved into a class. Do not take upgradable metadata locks when opening tables for CREATE TABLE SELECT as it is not necessary and limits concurrency. When initializing TABLE_LIST objects before adding them to the table list set the type of request for metadata lock according to the operation that will be performed on the table. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result FLUSH TABLES is no longer allowed for such tables. sql/sql_prepare.cc: Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening tables during PREPARE. This allows PREPARE to run concurrently in presence of LOCK TABLES ... WRITE. sql/sql_rename.cc: Global read lock functionality has been moved into a class. sql/sql_show.cc: Updated code to use the new MDL API. sql/sql_table.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result DROP TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_trigger.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result CREATE/DROP TRIGGER is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_view.cc: Global read lock functionality has been moved into a class. Fixed results of wrong merge that led to misuse of GLR API. CREATE VIEW statement is not a commit statement. sql/table.cc: When resetting TABLE_LIST objects for PS or SP re-execution set the type of request for metadata lock according to the operation that will be performed on the table. Do the same in auxiliary function initializing metadata lock requests in a table list. sql/table.h: When initializing TABLE_LIST objects set the type of request for metadata lock according to the operation that will be performed on the table. sql/transaction.cc: Global read lock functionality has been moved into a class.
2010-02-01 14:43:06 +03:00
--source include/wait_condition.inc
--echo # --> connection default
connection default;
--echo # The below 'handler t1 read ...' should not be blocked as
--echo # 'lock tables t1 write' has not succeeded yet.
handler t1 read a next;
--echo # Unblock 'lock tables t1 write'.
commit;
--echo # --> connection con1
connection con1;
--echo # Reap 'lock tables t1 write'.
--reap
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo # --> connection default
connection default;
--echo # Sending:
--send handler t1 read a next
--echo # --> connection con1
connection con1;
--echo # Waiting for 'handler t1 read a next' to get blocked...
let $wait_condition=
select count(*) = 1 from information_schema.processlist
Part of fix for bug#52044 "FLUSH TABLES WITH READ LOCK and FLUSH TABLES <list> WITH READ LOCK are incompatible" to be pushed as separate patch. Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. Also replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it more consistent with other thread state names. Updated test cases and their results according to these changes. Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. mysql-test/r/query_cache.result: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysql-test/suite/sys_vars/r/query_cache_wlock_invalidate_func.result: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/suite/sys_vars/t/query_cache_wlock_invalidate_func.test: Fixed sys_vars.query_cache_wlock_invalidate_func test to not to wait for timeout of wait_condition.inc script. Reverted changes to test which introduced timeout and replaced waiting condition with a more appropriate one. Test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables was added to query_cache.test. mysql-test/t/query_cache.test: Added test coverage for query_cache_wlock_invalidate behavior for implicitly locked tables. mysys/thr_lock.c: Replaced "Table lock" thread state name, which was used by threads waiting on thr_lock.c table level lock, with more elaborate "Waiting for table level lock", to make it consistent with thread state names which are used while waiting for metadata locks and table flush. sql/mdl.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for a metadata lock or table flush, with a set of names which better reflect types of resources being waited for. To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/mdl.h: To implement this: - Adjusted MDL_wait::timed_wait() to take thread state name as parameter. - Introduced method of MDL_key class which allows to get thread state name to be used while waiting for resource corresponding to the key and changed code to use it. Added array translating namespaces to thread state names as part of this change. sql/sql_base.cc: Replaced thread state name "Waiting for table", which was used by threads waiting for table flush, with a more elaborate "Waiting for table flush".
2010-08-06 15:29:37 +04:00
where state = "Waiting for table level lock" and
info = "handler t1 read a next";
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--source include/wait_condition.inc
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. mysql-test/include/handler.inc: Adjusted test case to trigger an execution path on which bug 41110 "crash with handler command when used concurrently with alter table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data with alter table" were originally discovered. Left old test case which no longer triggers this execution path for the sake of coverage. Added test coverage for HANDLER SQL statements and type-aware metadata locks. Added a test for the global shared lock and HANDLER SQL. Updated tests to take into account that the old simple deadlock detection heuristics was replaced with a graph-based deadlock detector. mysql-test/r/debug_sync.result: Updated results (see debug_sync.test). mysql-test/r/handler_innodb.result: Updated results (see handler.inc test). mysql-test/r/handler_myisam.result: Updated results (see handler.inc test). mysql-test/r/innodb-lock.result: Updated results (see innodb-lock.test). mysql-test/r/innodb_mysql_lock.result: Updated results (see innodb_mysql_lock.test). mysql-test/r/lock.result: Updated results (see lock.test). mysql-test/r/lock_multi.result: Updated results (see lock_multi.test). mysql-test/r/lock_sync.result: Updated results (see lock_sync.test). mysql-test/r/mdl_sync.result: Updated results (see mdl_sync.test). mysql-test/r/sp-threads.result: SHOW PROCESSLIST output has changed due to the fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/r/truncate_coverage.result: Updated results (see truncate_coverage.test). mysql-test/suite/funcs_1/datadict/processlist_val.inc: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/rpl/t/rpl_sp.test: Updated to a new SHOW PROCESSLIST state name. mysql-test/t/debug_sync.test: Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter no longer allows to trigger execution path involving waiting on thr_lock.c lock and therefore reaching debug sync-point covered by this test. mysql-test/t/innodb-lock.test: Adjusted test case to the fact that innodb_table_locks=0 option is no longer supported, since LOCK TABLES WRITE handles all its conflicts within MDL subsystem. mysql-test/t/innodb_mysql_lock.test: Added test for bug #37346 "innodb does not detect deadlock between update and alter table". mysql-test/t/lock.test: Added test coverage which checks the fact that we no longer support DDL under LOCK TABLES on tables which were locked implicitly. Adjusted existing test cases accordingly. mysql-test/t/lock_multi.test: Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock". Adjusted other test cases to take into account the fact that waiting for LOCK TABLES ... WRITE now happens within MDL subsystem. mysql-test/t/lock_sync.test: Since LOCK TABLES ... WRITE now takes SNRW metadata lock for tables locked explicitly we have to implicitly lock InnoDB tables (through view) to trigger the table-level lock conflict between TL_WRITE and TL_WRITE_ALLOW_WRITE. mysql-test/t/mdl_sync.test: Added basic test coverage for type-of-operation-aware metadata locks. Also covered with tests some use cases involving HANDLER statements in which a deadlock could arise. Adjusted existing tests to take type-of-operation-aware MDL into account. mysql-test/t/multi_update.test: Update to a new SHOW PROCESSLIST state name. mysql-test/t/truncate_coverage.test: Adjusted test case after making LOCK TABLES WRITE to wait until transactions that use the table to be locked are completed. Updated to the changed name of DEBUG_SYNC point. sql/handler.cc: Global read lock functionality has been moved into a class. sql/lock.cc: Global read lock functionality has been moved into a class. Updated code to use the new MDL API. sql/mdl.cc: Introduced new type-of-operation aware metadata locks. To do this: - Changed MDL_lock to use one list for waiting requests and one list for granted requests. For each list, added a bitmap that holds information what lock types a list contains. Added a helper class MDL_lock::List to manipulate with granted and waited lists while keeping the bitmaps in sync with list contents. - Changed lock-compatibility functions to use bitmaps that define compatibility. - Introduced a graph based deadlock detector inspired by waiting_threads.c from Maria implementation. - Now that we have a deadlock detector, and no longer have a global lock to protect individual lock objects, but rather use an rw lock per object, removed redundant code for upgrade, and the global read lock. Changed the MDL API to no longer require the caller to acquire the global intention exclusive lock by means of a separate method. Removed a few more methods that became redundant. - Removed deadlock detection heuristic, it has been made obsolete by the deadlock detector. - With operation-type-aware metadata locks, MDL subsystem has become aware of potential conflicts between DDL and open transactions. This made it possible to remove calls to mysql_abort_transactions_with_shared_lock() from acquisition paths for exclusive lock and lock upgrade. Now we can simply wait for these transactions to complete without fear of deadlock. Function mysql_lock_abort() has also become unnecessary for all conflicting cases except when a DDL conflicts with a connection that has an open HANDLER. sql/mdl.h: Introduced new type-of-operation aware metadata locks. Introduced a graph based deadlock detector and supporting methods. Added comments. God rid of redundant API calls. Renamed m_lt_or_ha_sentinel to m_trans_sentinel, since now it guards the global read lock as well as LOCK TABLES and HANDLER locks. sql/mysql_priv.h: Moved the global read lock functionality into a class. Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces open_tables() to take MDL_SHARED on tables instead of metadata locks specified in the parser. We use this to allow PREPARE run concurrently in presence of LOCK TABLES ... WRITE. Added signature for find_table_for_mdl_ugprade(). sql/set_var.cc: Global read lock functionality has been moved into a class. sql/sp_head.cc: When creating TABLE_LIST elements for prelocking or system tables set the type of request for metadata lock according to the operation that will be performed on the table. sql/sql_base.cc: - Updated code to use the new MDL API. - In order to avoid locks starvation we take upgradable locks all at once. As result implicitly locked tables no longer get an upgradable lock. Consequently DDL and FLUSH TABLES for such tables is prohibited. find_write_locked_table() was replaced by find_table_for_mdl_upgrade() function. open_table() was adjusted to return TABLE instance with upgradable ticket when necessary. - We no longer wait for all locks on OT_WAIT back off action -- only on the lock that caused the wait conflict. Moreover, now we distinguish cases when we have to wait due to conflict in MDL and old version of table in TDC. - Upate mysql_notify_threads_having_share_locks() to only abort thr_lock.c waits of threads that have open HANDLERs, since lock conflicts with only these threads now can lead to deadlocks not detectable by the MDL deadlock detector. - Remove mysql_abort_transactions_with_shared_locks() which is no longer needed. sql/sql_class.cc: Global read lock functionality has been moved into a class. Re-arranged code in THD::cleanup() to simplify assert. sql/sql_class.h: Introduced class to incapsulate global read lock functionality. Now sentinel in MDL subsystem guards the global read lock as well as LOCK TABLES and HANDLER locks. Adjusted code accordingly. sql/sql_db.cc: Global read lock functionality has been moved into a class. sql/sql_delete.cc: We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result TRUNCATE TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_handler.cc: Inform MDL_context about presence of open HANDLERs. Since HANLDERs break MDL protocol by acquiring table-level lock while holding only S metadata lock on a table MDL subsystem should take special care about such contexts (Now this is the only case when mysql_lock_abort() is used). sql/sql_parse.cc: Global read lock functionality has been moved into a class. Do not take upgradable metadata locks when opening tables for CREATE TABLE SELECT as it is not necessary and limits concurrency. When initializing TABLE_LIST objects before adding them to the table list set the type of request for metadata lock according to the operation that will be performed on the table. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result FLUSH TABLES is no longer allowed for such tables. sql/sql_prepare.cc: Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening tables during PREPARE. This allows PREPARE to run concurrently in presence of LOCK TABLES ... WRITE. sql/sql_rename.cc: Global read lock functionality has been moved into a class. sql/sql_show.cc: Updated code to use the new MDL API. sql/sql_table.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result DROP TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_trigger.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result CREATE/DROP TRIGGER is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_view.cc: Global read lock functionality has been moved into a class. Fixed results of wrong merge that led to misuse of GLR API. CREATE VIEW statement is not a commit statement. sql/table.cc: When resetting TABLE_LIST objects for PS or SP re-execution set the type of request for metadata lock according to the operation that will be performed on the table. Do the same in auxiliary function initializing metadata lock requests in a table list. sql/table.h: When initializing TABLE_LIST objects set the type of request for metadata lock according to the operation that will be performed on the table. sql/transaction.cc: Global read lock functionality has been moved into a class.
2010-02-01 14:43:06 +03:00
--echo # The below 'drop table t1' should be able to proceed without
--echo # waiting as it will force HANDLER to be closed.
drop table t1;
unlock tables;
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--echo # --> connection default
connection default;
--echo # Reaping 'handler t1 read a next'...
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. mysql-test/include/handler.inc: Adjusted test case to trigger an execution path on which bug 41110 "crash with handler command when used concurrently with alter table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data with alter table" were originally discovered. Left old test case which no longer triggers this execution path for the sake of coverage. Added test coverage for HANDLER SQL statements and type-aware metadata locks. Added a test for the global shared lock and HANDLER SQL. Updated tests to take into account that the old simple deadlock detection heuristics was replaced with a graph-based deadlock detector. mysql-test/r/debug_sync.result: Updated results (see debug_sync.test). mysql-test/r/handler_innodb.result: Updated results (see handler.inc test). mysql-test/r/handler_myisam.result: Updated results (see handler.inc test). mysql-test/r/innodb-lock.result: Updated results (see innodb-lock.test). mysql-test/r/innodb_mysql_lock.result: Updated results (see innodb_mysql_lock.test). mysql-test/r/lock.result: Updated results (see lock.test). mysql-test/r/lock_multi.result: Updated results (see lock_multi.test). mysql-test/r/lock_sync.result: Updated results (see lock_sync.test). mysql-test/r/mdl_sync.result: Updated results (see mdl_sync.test). mysql-test/r/sp-threads.result: SHOW PROCESSLIST output has changed due to the fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/r/truncate_coverage.result: Updated results (see truncate_coverage.test). mysql-test/suite/funcs_1/datadict/processlist_val.inc: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/rpl/t/rpl_sp.test: Updated to a new SHOW PROCESSLIST state name. mysql-test/t/debug_sync.test: Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter no longer allows to trigger execution path involving waiting on thr_lock.c lock and therefore reaching debug sync-point covered by this test. mysql-test/t/innodb-lock.test: Adjusted test case to the fact that innodb_table_locks=0 option is no longer supported, since LOCK TABLES WRITE handles all its conflicts within MDL subsystem. mysql-test/t/innodb_mysql_lock.test: Added test for bug #37346 "innodb does not detect deadlock between update and alter table". mysql-test/t/lock.test: Added test coverage which checks the fact that we no longer support DDL under LOCK TABLES on tables which were locked implicitly. Adjusted existing test cases accordingly. mysql-test/t/lock_multi.test: Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock". Adjusted other test cases to take into account the fact that waiting for LOCK TABLES ... WRITE now happens within MDL subsystem. mysql-test/t/lock_sync.test: Since LOCK TABLES ... WRITE now takes SNRW metadata lock for tables locked explicitly we have to implicitly lock InnoDB tables (through view) to trigger the table-level lock conflict between TL_WRITE and TL_WRITE_ALLOW_WRITE. mysql-test/t/mdl_sync.test: Added basic test coverage for type-of-operation-aware metadata locks. Also covered with tests some use cases involving HANDLER statements in which a deadlock could arise. Adjusted existing tests to take type-of-operation-aware MDL into account. mysql-test/t/multi_update.test: Update to a new SHOW PROCESSLIST state name. mysql-test/t/truncate_coverage.test: Adjusted test case after making LOCK TABLES WRITE to wait until transactions that use the table to be locked are completed. Updated to the changed name of DEBUG_SYNC point. sql/handler.cc: Global read lock functionality has been moved into a class. sql/lock.cc: Global read lock functionality has been moved into a class. Updated code to use the new MDL API. sql/mdl.cc: Introduced new type-of-operation aware metadata locks. To do this: - Changed MDL_lock to use one list for waiting requests and one list for granted requests. For each list, added a bitmap that holds information what lock types a list contains. Added a helper class MDL_lock::List to manipulate with granted and waited lists while keeping the bitmaps in sync with list contents. - Changed lock-compatibility functions to use bitmaps that define compatibility. - Introduced a graph based deadlock detector inspired by waiting_threads.c from Maria implementation. - Now that we have a deadlock detector, and no longer have a global lock to protect individual lock objects, but rather use an rw lock per object, removed redundant code for upgrade, and the global read lock. Changed the MDL API to no longer require the caller to acquire the global intention exclusive lock by means of a separate method. Removed a few more methods that became redundant. - Removed deadlock detection heuristic, it has been made obsolete by the deadlock detector. - With operation-type-aware metadata locks, MDL subsystem has become aware of potential conflicts between DDL and open transactions. This made it possible to remove calls to mysql_abort_transactions_with_shared_lock() from acquisition paths for exclusive lock and lock upgrade. Now we can simply wait for these transactions to complete without fear of deadlock. Function mysql_lock_abort() has also become unnecessary for all conflicting cases except when a DDL conflicts with a connection that has an open HANDLER. sql/mdl.h: Introduced new type-of-operation aware metadata locks. Introduced a graph based deadlock detector and supporting methods. Added comments. God rid of redundant API calls. Renamed m_lt_or_ha_sentinel to m_trans_sentinel, since now it guards the global read lock as well as LOCK TABLES and HANDLER locks. sql/mysql_priv.h: Moved the global read lock functionality into a class. Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces open_tables() to take MDL_SHARED on tables instead of metadata locks specified in the parser. We use this to allow PREPARE run concurrently in presence of LOCK TABLES ... WRITE. Added signature for find_table_for_mdl_ugprade(). sql/set_var.cc: Global read lock functionality has been moved into a class. sql/sp_head.cc: When creating TABLE_LIST elements for prelocking or system tables set the type of request for metadata lock according to the operation that will be performed on the table. sql/sql_base.cc: - Updated code to use the new MDL API. - In order to avoid locks starvation we take upgradable locks all at once. As result implicitly locked tables no longer get an upgradable lock. Consequently DDL and FLUSH TABLES for such tables is prohibited. find_write_locked_table() was replaced by find_table_for_mdl_upgrade() function. open_table() was adjusted to return TABLE instance with upgradable ticket when necessary. - We no longer wait for all locks on OT_WAIT back off action -- only on the lock that caused the wait conflict. Moreover, now we distinguish cases when we have to wait due to conflict in MDL and old version of table in TDC. - Upate mysql_notify_threads_having_share_locks() to only abort thr_lock.c waits of threads that have open HANDLERs, since lock conflicts with only these threads now can lead to deadlocks not detectable by the MDL deadlock detector. - Remove mysql_abort_transactions_with_shared_locks() which is no longer needed. sql/sql_class.cc: Global read lock functionality has been moved into a class. Re-arranged code in THD::cleanup() to simplify assert. sql/sql_class.h: Introduced class to incapsulate global read lock functionality. Now sentinel in MDL subsystem guards the global read lock as well as LOCK TABLES and HANDLER locks. Adjusted code accordingly. sql/sql_db.cc: Global read lock functionality has been moved into a class. sql/sql_delete.cc: We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result TRUNCATE TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_handler.cc: Inform MDL_context about presence of open HANDLERs. Since HANLDERs break MDL protocol by acquiring table-level lock while holding only S metadata lock on a table MDL subsystem should take special care about such contexts (Now this is the only case when mysql_lock_abort() is used). sql/sql_parse.cc: Global read lock functionality has been moved into a class. Do not take upgradable metadata locks when opening tables for CREATE TABLE SELECT as it is not necessary and limits concurrency. When initializing TABLE_LIST objects before adding them to the table list set the type of request for metadata lock according to the operation that will be performed on the table. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result FLUSH TABLES is no longer allowed for such tables. sql/sql_prepare.cc: Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening tables during PREPARE. This allows PREPARE to run concurrently in presence of LOCK TABLES ... WRITE. sql/sql_rename.cc: Global read lock functionality has been moved into a class. sql/sql_show.cc: Updated code to use the new MDL API. sql/sql_table.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result DROP TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_trigger.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result CREATE/DROP TRIGGER is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_view.cc: Global read lock functionality has been moved into a class. Fixed results of wrong merge that led to misuse of GLR API. CREATE VIEW statement is not a commit statement. sql/table.cc: When resetting TABLE_LIST objects for PS or SP re-execution set the type of request for metadata lock according to the operation that will be performed on the table. Do the same in auxiliary function initializing metadata lock requests in a table list. sql/table.h: When initializing TABLE_LIST objects set the type of request for metadata lock according to the operation that will be performed on the table. sql/transaction.cc: Global read lock functionality has been moved into a class.
2010-02-01 14:43:06 +03:00
--error ER_NO_SUCH_TABLE
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
--reap
handler t1 close;
--echo # --> connection con1
connection con1;
disconnect con1;
--source include/wait_until_disconnected.inc
--echo # --> connection con2
connection con2;
disconnect con2;
--source include/wait_until_disconnected.inc
--echo # --> connection con3
connection con3;
disconnect con3;
--source include/wait_until_disconnected.inc
connection default;
--echo #
--echo # A temporary table test.
--echo # Check that we don't loose positions of HANDLER opened
--echo # against a temporary table.
--echo #
create table t1 (a int, b int, key using btree (a));
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
insert into t1 (a) values (1), (2), (3), (4), (5);
create temporary table t2 (a int, b int, key using btree (a));
A prerequisite patch for the fix for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Introduce a notion of a sentinel to MDL_context. A sentinel is a ticket that separates all tickets in the context into two groups: before and after it. Currently we can have (and need) only one designated sentinel -- it separates all locks taken by LOCK TABLE or HANDLER statement, which must survive COMMIT and ROLLBACK and all other locks, which must be released at COMMIT or ROLLBACK. The tricky part is maintaining the sentinel up to date when someone release its corresponding ticket. This can happen, e.g. if someone issues DROP TABLE under LOCK TABLES (generally, see all calls to release_all_locks_for_name()). MDL_context::release_ticket() is modified to take care of it. ****** A fix and a test case for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". An attempt to mix HANDLER SQL statements, which are transaction- agnostic, an open multi-statement transaction, and DDL against the involved tables (in a concurrent connection) could lead to a deadlock. The deadlock would occur when HANDLER OPEN or HANDLER READ would have to wait on a conflicting metadata lock. If the connection that issued HANDLER statement also had other metadata locks (say, acquired in scope of a transaction), a classical deadlock situation of mutual wait could occur. Incompatible change: entering LOCK TABLES mode automatically closes all open HANDLERs in the current connection. Incompatible change: previously an attempt to wait on a lock in a connection that has an open HANDLER statement could wait indefinitely/deadlock. After this patch, an error ER_LOCK_DEADLOCK is produced. The idea of the fix is to merge thd->handler_mdl_context with the main mdl_context of the connection, used for transactional locks. This makes deadlock detection possible, since all waits with locks are "visible" and available to analysis in a single MDL context of the connection. Since HANDLER locks and transactional locks have a different life cycle -- HANDLERs are explicitly open and closed, and so are HANDLER locks, explicitly acquired and released, whereas transactional locks "accumulate" till the end of a transaction and are released only with COMMIT, ROLLBACK and ROLLBACK TO SAVEPOINT, a concept of "sentinel" was introduced to MDL_context. All locks, HANDLER and others, reside in the same linked list. However, a selected element of the list separates locks with different life cycle. HANDLER locks always reside at the end of the list, after the sentinel. Transactional locks are prepended to the beginning of the list, before the sentinel. Thus, ROLLBACK, COMMIT or ROLLBACK TO SAVEPOINT, only release those locks that reside before the sentinel. HANDLER locks must be released explicitly as part of HANDLER CLOSE statement, or an implicit close. The same approach with sentinel is also employed for LOCK TABLES locks. Since HANDLER and LOCK TABLES statement has never worked together, the implementation is made simple and only maintains one sentinel, which is used either for HANDLER locks, or for LOCK TABLES locks. mysql-test/include/handler.inc: Add test coverage for Bug#46224 "HANDLER statements within a transaction might lead to deadlocks". Extended HANDLER coverage to cover a mix of HANDLER, transactions and DDL statements. mysql-test/r/handler_innodb.result: Update results (Bug#46224). mysql-test/r/handler_myisam.result: Update results (Bug#46224). sql/lock.cc: Remove thd->some_tables_deleted, it's never used. sql/log_event.cc: No need to check for thd->locked_tables_mode, it's done inside release_transactional_locks(). sql/mdl.cc: Implement the concept of HANDLER and LOCK TABLES "sentinel". Implement a method to clone an acquired ticket. Do not return tickets beyond the sentinel when acquiring locks, create a copy. Remove methods to merge and backup MDL_context, they are now not used (Hurra!). This opens a path to a proper constructor and destructor of class MDL_context (to be done in a separate patch). Modify find_ticket() to provide information about where the ticket position is with regard to the sentinel. sql/mdl.h: Add declarations necessary for the implementation of the concept of "sentinel", a dedicated ticket separating transactional and non-transactional locks. sql/mysql_priv.h: Add mark_tmp_table_for_reuse() declaration, a function to "close" a single session (temporary) table. sql/sql_base.cc: Remove thd->some_tables_deleted. Modify deadlock-prevention asserts and deadlock detection heuristics to take into account that from now on HANDLER locks reside in the same locking context. Add broadcast_refresh() to mysql_notify_thread_having_shared_lock(): this is necessary for the case when a thread having a shared lock is asleep in tdc_wait_for_old_versions(). This situation is only possible with HANDLER t1 OPEN; FLUSH TABLE (since all over code paths that lead to tdc_wait_for_old_versions() always have an empty MDL_context). Previously the server would simply deadlock in this situation. sql/sql_class.cc: Remove now unused member "THD::some_tables_deleted". Move mysql_ha_cleanup() a few lines above in THD::cleanup() to make sure that all handlers are closed when it's time to destroy the MDL_context of this connection. Remove handler_mdl_context and handler_tables. sql/sql_class.h: Remove THD::handler_tables, THD::handler_mdl_context, THD::some_tables_deleted. sql/sql_handler.cc: Remove thd->handler_tables. Remove thd->handler_mdl_context. Rewrite mysql_ha_open() to have no special provision for MERGE tables, now that we don't have to manipulate with thd->handler_tables it's easy to do. Remove dead code. Fix a bug in mysql_ha_flush() when we would always flush a temporary HANDLER when mysql_ha_flush() is called (actually mysql_ha_flush() never needs to flush temporary tables). sql/sql_insert.cc: Update a comment, no more thd->some_tables_deleted. sql/sql_parse.cc: Implement an incompatible change: entering LOCK TABLES closes active HANDLERs, if any. Now that we have a sentinel, we don't need to check for thd->locked_tables_mode when releasing metadata locks in COMMIT/ROLLBACK. sql/sql_plist.h: Add new (now necessary) methods to the list class. sql/sql_prepare.cc: Make sure we don't release HANDLER locks when rollback to a savepoint, set to not keep locks taken at PREPARE. sql/sql_servers.cc: Update to a new signature of MDL_context::release_all_locks(). sql/sql_table.cc: Remove thd->some_tables_deleted. sql/transaction.cc: Add comments. Make sure rollback to (MDL) savepoint works under LOCK TABLES and with HANDLER tables.
2009-12-22 19:09:15 +03:00
insert into t2 (a) select a from t1;
handler t1 open;
handler t1 read a next;
handler t2 open;
handler t2 read a next;
flush table t1;
handler t2 read a next;
--echo # Sic: the position is lost
handler t1 read a next;
select * from t1;
--echo # Sic: the position is not lost
handler t2 read a next;
--error ER_CANT_REOPEN_TABLE
select * from t2;
handler t2 read a next;
drop table t1;
drop temporary table t2;
--echo #
--echo # A test for lock_table_names()/unlock_table_names() function.
--echo # It should work properly in presence of open HANDLER.
--echo #
create table t1 (a int, b int, key a (a));
create table t2 like t1;
create table t3 like t1;
create table t4 like t1;
handler t1 open;
handler t2 open;
rename table t4 to t5, t3 to t4, t5 to t3;
handler t1 read first;
handler t2 read first;
drop table t1, t2, t3, t4;
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. mysql-test/include/handler.inc: Adjusted test case to trigger an execution path on which bug 41110 "crash with handler command when used concurrently with alter table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data with alter table" were originally discovered. Left old test case which no longer triggers this execution path for the sake of coverage. Added test coverage for HANDLER SQL statements and type-aware metadata locks. Added a test for the global shared lock and HANDLER SQL. Updated tests to take into account that the old simple deadlock detection heuristics was replaced with a graph-based deadlock detector. mysql-test/r/debug_sync.result: Updated results (see debug_sync.test). mysql-test/r/handler_innodb.result: Updated results (see handler.inc test). mysql-test/r/handler_myisam.result: Updated results (see handler.inc test). mysql-test/r/innodb-lock.result: Updated results (see innodb-lock.test). mysql-test/r/innodb_mysql_lock.result: Updated results (see innodb_mysql_lock.test). mysql-test/r/lock.result: Updated results (see lock.test). mysql-test/r/lock_multi.result: Updated results (see lock_multi.test). mysql-test/r/lock_sync.result: Updated results (see lock_sync.test). mysql-test/r/mdl_sync.result: Updated results (see mdl_sync.test). mysql-test/r/sp-threads.result: SHOW PROCESSLIST output has changed due to the fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/r/truncate_coverage.result: Updated results (see truncate_coverage.test). mysql-test/suite/funcs_1/datadict/processlist_val.inc: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/rpl/t/rpl_sp.test: Updated to a new SHOW PROCESSLIST state name. mysql-test/t/debug_sync.test: Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter no longer allows to trigger execution path involving waiting on thr_lock.c lock and therefore reaching debug sync-point covered by this test. mysql-test/t/innodb-lock.test: Adjusted test case to the fact that innodb_table_locks=0 option is no longer supported, since LOCK TABLES WRITE handles all its conflicts within MDL subsystem. mysql-test/t/innodb_mysql_lock.test: Added test for bug #37346 "innodb does not detect deadlock between update and alter table". mysql-test/t/lock.test: Added test coverage which checks the fact that we no longer support DDL under LOCK TABLES on tables which were locked implicitly. Adjusted existing test cases accordingly. mysql-test/t/lock_multi.test: Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock". Adjusted other test cases to take into account the fact that waiting for LOCK TABLES ... WRITE now happens within MDL subsystem. mysql-test/t/lock_sync.test: Since LOCK TABLES ... WRITE now takes SNRW metadata lock for tables locked explicitly we have to implicitly lock InnoDB tables (through view) to trigger the table-level lock conflict between TL_WRITE and TL_WRITE_ALLOW_WRITE. mysql-test/t/mdl_sync.test: Added basic test coverage for type-of-operation-aware metadata locks. Also covered with tests some use cases involving HANDLER statements in which a deadlock could arise. Adjusted existing tests to take type-of-operation-aware MDL into account. mysql-test/t/multi_update.test: Update to a new SHOW PROCESSLIST state name. mysql-test/t/truncate_coverage.test: Adjusted test case after making LOCK TABLES WRITE to wait until transactions that use the table to be locked are completed. Updated to the changed name of DEBUG_SYNC point. sql/handler.cc: Global read lock functionality has been moved into a class. sql/lock.cc: Global read lock functionality has been moved into a class. Updated code to use the new MDL API. sql/mdl.cc: Introduced new type-of-operation aware metadata locks. To do this: - Changed MDL_lock to use one list for waiting requests and one list for granted requests. For each list, added a bitmap that holds information what lock types a list contains. Added a helper class MDL_lock::List to manipulate with granted and waited lists while keeping the bitmaps in sync with list contents. - Changed lock-compatibility functions to use bitmaps that define compatibility. - Introduced a graph based deadlock detector inspired by waiting_threads.c from Maria implementation. - Now that we have a deadlock detector, and no longer have a global lock to protect individual lock objects, but rather use an rw lock per object, removed redundant code for upgrade, and the global read lock. Changed the MDL API to no longer require the caller to acquire the global intention exclusive lock by means of a separate method. Removed a few more methods that became redundant. - Removed deadlock detection heuristic, it has been made obsolete by the deadlock detector. - With operation-type-aware metadata locks, MDL subsystem has become aware of potential conflicts between DDL and open transactions. This made it possible to remove calls to mysql_abort_transactions_with_shared_lock() from acquisition paths for exclusive lock and lock upgrade. Now we can simply wait for these transactions to complete without fear of deadlock. Function mysql_lock_abort() has also become unnecessary for all conflicting cases except when a DDL conflicts with a connection that has an open HANDLER. sql/mdl.h: Introduced new type-of-operation aware metadata locks. Introduced a graph based deadlock detector and supporting methods. Added comments. God rid of redundant API calls. Renamed m_lt_or_ha_sentinel to m_trans_sentinel, since now it guards the global read lock as well as LOCK TABLES and HANDLER locks. sql/mysql_priv.h: Moved the global read lock functionality into a class. Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces open_tables() to take MDL_SHARED on tables instead of metadata locks specified in the parser. We use this to allow PREPARE run concurrently in presence of LOCK TABLES ... WRITE. Added signature for find_table_for_mdl_ugprade(). sql/set_var.cc: Global read lock functionality has been moved into a class. sql/sp_head.cc: When creating TABLE_LIST elements for prelocking or system tables set the type of request for metadata lock according to the operation that will be performed on the table. sql/sql_base.cc: - Updated code to use the new MDL API. - In order to avoid locks starvation we take upgradable locks all at once. As result implicitly locked tables no longer get an upgradable lock. Consequently DDL and FLUSH TABLES for such tables is prohibited. find_write_locked_table() was replaced by find_table_for_mdl_upgrade() function. open_table() was adjusted to return TABLE instance with upgradable ticket when necessary. - We no longer wait for all locks on OT_WAIT back off action -- only on the lock that caused the wait conflict. Moreover, now we distinguish cases when we have to wait due to conflict in MDL and old version of table in TDC. - Upate mysql_notify_threads_having_share_locks() to only abort thr_lock.c waits of threads that have open HANDLERs, since lock conflicts with only these threads now can lead to deadlocks not detectable by the MDL deadlock detector. - Remove mysql_abort_transactions_with_shared_locks() which is no longer needed. sql/sql_class.cc: Global read lock functionality has been moved into a class. Re-arranged code in THD::cleanup() to simplify assert. sql/sql_class.h: Introduced class to incapsulate global read lock functionality. Now sentinel in MDL subsystem guards the global read lock as well as LOCK TABLES and HANDLER locks. Adjusted code accordingly. sql/sql_db.cc: Global read lock functionality has been moved into a class. sql/sql_delete.cc: We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result TRUNCATE TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_handler.cc: Inform MDL_context about presence of open HANDLERs. Since HANLDERs break MDL protocol by acquiring table-level lock while holding only S metadata lock on a table MDL subsystem should take special care about such contexts (Now this is the only case when mysql_lock_abort() is used). sql/sql_parse.cc: Global read lock functionality has been moved into a class. Do not take upgradable metadata locks when opening tables for CREATE TABLE SELECT as it is not necessary and limits concurrency. When initializing TABLE_LIST objects before adding them to the table list set the type of request for metadata lock according to the operation that will be performed on the table. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result FLUSH TABLES is no longer allowed for such tables. sql/sql_prepare.cc: Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening tables during PREPARE. This allows PREPARE to run concurrently in presence of LOCK TABLES ... WRITE. sql/sql_rename.cc: Global read lock functionality has been moved into a class. sql/sql_show.cc: Updated code to use the new MDL API. sql/sql_table.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result DROP TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_trigger.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result CREATE/DROP TRIGGER is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_view.cc: Global read lock functionality has been moved into a class. Fixed results of wrong merge that led to misuse of GLR API. CREATE VIEW statement is not a commit statement. sql/table.cc: When resetting TABLE_LIST objects for PS or SP re-execution set the type of request for metadata lock according to the operation that will be performed on the table. Do the same in auxiliary function initializing metadata lock requests in a table list. sql/table.h: When initializing TABLE_LIST objects set the type of request for metadata lock according to the operation that will be performed on the table. sql/transaction.cc: Global read lock functionality has been moved into a class.
2010-02-01 14:43:06 +03:00
--echo #
--echo # A test for FLUSH TABLES WITH READ LOCK and HANDLER statements.
--echo #
set autocommit=0;
create table t1 (a int, b int, key a (a));
insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
create table t2 like t1;
insert into t2 (a, b) select a, b from t1;
create table t3 like t1;
insert into t3 (a, b) select a, b from t1;
commit;
flush tables with read lock;
handler t1 open;
lock table t1 read;
--error ER_LOCK_OR_ACTIVE_TRANSACTION
handler t1 read next;
--echo # This implicitly leaves LOCK TABLES but doesn't drop the GLR
--error ER_NO_SUCH_TABLE
lock table not_exists_write read;
--echo # We still have the read lock.
--error ER_CANT_UPDATE_WITH_READLOCK
drop table t1;
handler t1 open;
select a from t2;
handler t1 read next;
flush tables with read lock;
handler t2 open;
flush tables with read lock;
handler t1 read next;
select a from t3;
handler t2 read next;
handler t1 close;
rollback;
handler t2 close;
--error ER_CANT_UPDATE_WITH_READLOCK
drop table t1;
commit;
flush tables;
--error ER_CANT_UPDATE_WITH_READLOCK
drop table t1;
unlock tables;
drop table t1;
set autocommit=default;
drop table t2, t3;
--echo #
--echo # HANDLER statement and operation-type aware metadata locks.
--echo # Check that when we clone a ticket for HANDLER we downrade
--echo # the lock.
--echo #
--echo # Establish an auxiliary connection con1.
connect (con1,localhost,root,,);
--echo # -> connection default
connection default;
create table t1 (a int, b int, key using btree (a));
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. mysql-test/include/handler.inc: Adjusted test case to trigger an execution path on which bug 41110 "crash with handler command when used concurrently with alter table" and bug 41112 "crash in mysql_ha_close_table/get_lock_data with alter table" were originally discovered. Left old test case which no longer triggers this execution path for the sake of coverage. Added test coverage for HANDLER SQL statements and type-aware metadata locks. Added a test for the global shared lock and HANDLER SQL. Updated tests to take into account that the old simple deadlock detection heuristics was replaced with a graph-based deadlock detector. mysql-test/r/debug_sync.result: Updated results (see debug_sync.test). mysql-test/r/handler_innodb.result: Updated results (see handler.inc test). mysql-test/r/handler_myisam.result: Updated results (see handler.inc test). mysql-test/r/innodb-lock.result: Updated results (see innodb-lock.test). mysql-test/r/innodb_mysql_lock.result: Updated results (see innodb_mysql_lock.test). mysql-test/r/lock.result: Updated results (see lock.test). mysql-test/r/lock_multi.result: Updated results (see lock_multi.test). mysql-test/r/lock_sync.result: Updated results (see lock_sync.test). mysql-test/r/mdl_sync.result: Updated results (see mdl_sync.test). mysql-test/r/sp-threads.result: SHOW PROCESSLIST output has changed due to the fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/r/truncate_coverage.result: Updated results (see truncate_coverage.test). mysql-test/suite/funcs_1/datadict/processlist_val.inc: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/funcs_1/r/processlist_val_no_prot.result: SELECT FROM I_S.PROCESSLIST output has changed due to fact that waiting for LOCK TABLES WRITE now happens within metadata locking subsystem. mysql-test/suite/rpl/t/rpl_sp.test: Updated to a new SHOW PROCESSLIST state name. mysql-test/t/debug_sync.test: Use LOCK TABLES READ instead of LOCK TABLES WRITE as the latter no longer allows to trigger execution path involving waiting on thr_lock.c lock and therefore reaching debug sync-point covered by this test. mysql-test/t/innodb-lock.test: Adjusted test case to the fact that innodb_table_locks=0 option is no longer supported, since LOCK TABLES WRITE handles all its conflicts within MDL subsystem. mysql-test/t/innodb_mysql_lock.test: Added test for bug #37346 "innodb does not detect deadlock between update and alter table". mysql-test/t/lock.test: Added test coverage which checks the fact that we no longer support DDL under LOCK TABLES on tables which were locked implicitly. Adjusted existing test cases accordingly. mysql-test/t/lock_multi.test: Added test for bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock". Adjusted other test cases to take into account the fact that waiting for LOCK TABLES ... WRITE now happens within MDL subsystem. mysql-test/t/lock_sync.test: Since LOCK TABLES ... WRITE now takes SNRW metadata lock for tables locked explicitly we have to implicitly lock InnoDB tables (through view) to trigger the table-level lock conflict between TL_WRITE and TL_WRITE_ALLOW_WRITE. mysql-test/t/mdl_sync.test: Added basic test coverage for type-of-operation-aware metadata locks. Also covered with tests some use cases involving HANDLER statements in which a deadlock could arise. Adjusted existing tests to take type-of-operation-aware MDL into account. mysql-test/t/multi_update.test: Update to a new SHOW PROCESSLIST state name. mysql-test/t/truncate_coverage.test: Adjusted test case after making LOCK TABLES WRITE to wait until transactions that use the table to be locked are completed. Updated to the changed name of DEBUG_SYNC point. sql/handler.cc: Global read lock functionality has been moved into a class. sql/lock.cc: Global read lock functionality has been moved into a class. Updated code to use the new MDL API. sql/mdl.cc: Introduced new type-of-operation aware metadata locks. To do this: - Changed MDL_lock to use one list for waiting requests and one list for granted requests. For each list, added a bitmap that holds information what lock types a list contains. Added a helper class MDL_lock::List to manipulate with granted and waited lists while keeping the bitmaps in sync with list contents. - Changed lock-compatibility functions to use bitmaps that define compatibility. - Introduced a graph based deadlock detector inspired by waiting_threads.c from Maria implementation. - Now that we have a deadlock detector, and no longer have a global lock to protect individual lock objects, but rather use an rw lock per object, removed redundant code for upgrade, and the global read lock. Changed the MDL API to no longer require the caller to acquire the global intention exclusive lock by means of a separate method. Removed a few more methods that became redundant. - Removed deadlock detection heuristic, it has been made obsolete by the deadlock detector. - With operation-type-aware metadata locks, MDL subsystem has become aware of potential conflicts between DDL and open transactions. This made it possible to remove calls to mysql_abort_transactions_with_shared_lock() from acquisition paths for exclusive lock and lock upgrade. Now we can simply wait for these transactions to complete without fear of deadlock. Function mysql_lock_abort() has also become unnecessary for all conflicting cases except when a DDL conflicts with a connection that has an open HANDLER. sql/mdl.h: Introduced new type-of-operation aware metadata locks. Introduced a graph based deadlock detector and supporting methods. Added comments. God rid of redundant API calls. Renamed m_lt_or_ha_sentinel to m_trans_sentinel, since now it guards the global read lock as well as LOCK TABLES and HANDLER locks. sql/mysql_priv.h: Moved the global read lock functionality into a class. Added MYSQL_OPEN_FORCE_SHARED_MDL flag which forces open_tables() to take MDL_SHARED on tables instead of metadata locks specified in the parser. We use this to allow PREPARE run concurrently in presence of LOCK TABLES ... WRITE. Added signature for find_table_for_mdl_ugprade(). sql/set_var.cc: Global read lock functionality has been moved into a class. sql/sp_head.cc: When creating TABLE_LIST elements for prelocking or system tables set the type of request for metadata lock according to the operation that will be performed on the table. sql/sql_base.cc: - Updated code to use the new MDL API. - In order to avoid locks starvation we take upgradable locks all at once. As result implicitly locked tables no longer get an upgradable lock. Consequently DDL and FLUSH TABLES for such tables is prohibited. find_write_locked_table() was replaced by find_table_for_mdl_upgrade() function. open_table() was adjusted to return TABLE instance with upgradable ticket when necessary. - We no longer wait for all locks on OT_WAIT back off action -- only on the lock that caused the wait conflict. Moreover, now we distinguish cases when we have to wait due to conflict in MDL and old version of table in TDC. - Upate mysql_notify_threads_having_share_locks() to only abort thr_lock.c waits of threads that have open HANDLERs, since lock conflicts with only these threads now can lead to deadlocks not detectable by the MDL deadlock detector. - Remove mysql_abort_transactions_with_shared_locks() which is no longer needed. sql/sql_class.cc: Global read lock functionality has been moved into a class. Re-arranged code in THD::cleanup() to simplify assert. sql/sql_class.h: Introduced class to incapsulate global read lock functionality. Now sentinel in MDL subsystem guards the global read lock as well as LOCK TABLES and HANDLER locks. Adjusted code accordingly. sql/sql_db.cc: Global read lock functionality has been moved into a class. sql/sql_delete.cc: We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result TRUNCATE TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_handler.cc: Inform MDL_context about presence of open HANDLERs. Since HANLDERs break MDL protocol by acquiring table-level lock while holding only S metadata lock on a table MDL subsystem should take special care about such contexts (Now this is the only case when mysql_lock_abort() is used). sql/sql_parse.cc: Global read lock functionality has been moved into a class. Do not take upgradable metadata locks when opening tables for CREATE TABLE SELECT as it is not necessary and limits concurrency. When initializing TABLE_LIST objects before adding them to the table list set the type of request for metadata lock according to the operation that will be performed on the table. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result FLUSH TABLES is no longer allowed for such tables. sql/sql_prepare.cc: Use MYSQL_OPEN_FORCE_SHARED_MDL flag when opening tables during PREPARE. This allows PREPARE to run concurrently in presence of LOCK TABLES ... WRITE. sql/sql_rename.cc: Global read lock functionality has been moved into a class. sql/sql_show.cc: Updated code to use the new MDL API. sql/sql_table.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result DROP TABLE is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_trigger.cc: Global read lock functionality has been moved into a class. We no longer acquire upgradable metadata locks on tables which are locked by LOCK TABLES implicitly. As result CREATE/DROP TRIGGER is no longer allowed for such tables. Updated code to use the new MDL API. sql/sql_view.cc: Global read lock functionality has been moved into a class. Fixed results of wrong merge that led to misuse of GLR API. CREATE VIEW statement is not a commit statement. sql/table.cc: When resetting TABLE_LIST objects for PS or SP re-execution set the type of request for metadata lock according to the operation that will be performed on the table. Do the same in auxiliary function initializing metadata lock requests in a table list. sql/table.h: When initializing TABLE_LIST objects set the type of request for metadata lock according to the operation that will be performed on the table. sql/transaction.cc: Global read lock functionality has been moved into a class.
2010-02-01 14:43:06 +03:00
insert into t1 (a, b) values (1, 1), (2, 1), (3, 2), (4, 2), (5, 5);
begin;
insert into t1 (a, b) values (6, 6);
handler t1 open;
handler t1 read a last;
insert into t1 (a, b) values (7, 7);
handler t1 read a last;
commit;
--echo # -> connection con1
connection con1;
--echo # Demonstrate that the HANDLER doesn't hold MDL_SHARED_WRITE.
lock table t1 write;
unlock tables;
--echo # -> connection default
connection default;
handler t1 read a prev;
handler t1 close;
--echo # Cleanup.
drop table t1;
--echo # -> connection con1
connection con1;
disconnect con1;
--source include/wait_until_disconnected.inc
--echo # -> connection default
connection default;
--echo #
--echo # A test for Bug#50555 "handler commands crash server in
--echo # my_hash_first()".
--echo #
--error ER_UNKNOWN_TABLE
handler no_such_table read no_such_index first;
--error ER_UNKNOWN_TABLE
handler no_such_table close;
--echo #
--echo # Bug#50907 Assertion `hash_tables->table->next == __null' on
--echo # HANDLER OPEN
--echo #
--disable_warnings
DROP TABLE IF EXISTS t1, t2;
--enable_warnings
CREATE TEMPORARY TABLE t1 (i INT);
CREATE TEMPORARY TABLE t2 (i INT);
# This used to trigger the assert
HANDLER t2 OPEN;
# This also used to trigger the assert
HANDLER t2 READ FIRST;
HANDLER t2 CLOSE;
DROP TABLE t1, t2;
--echo #
--echo # Bug#50912 Assertion `ticket->m_type >= mdl_request->type'
--echo # failed on HANDLER + I_S
--echo #
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1 (id INT);
HANDLER t1 OPEN;
# This used to trigger the assert.
SELECT table_name, table_comment FROM information_schema.tables
WHERE table_schema= 'test' AND table_name= 't1';
HANDLER t1 CLOSE;
DROP TABLE t1;
Fix for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". Server was aborted due to assertion failure when one tried to execute statement requiring prelocking (i.e. firing triggers or using stored functions) while having open HANDLERs. The problem was that THD::enter_locked_tables_mode() method which was called at the beginning of execution of prelocked statement assumed there are no open HANDLERs. It had to do so because corresponding THD::leave_locked_tables_mode() method was unable to properly restore MDL sentinel when leaving LOCK TABLES/prelocked mode in the presence of open HANDLERs. This patch solves this problem by changing the latter method to properly restore MDL sentinel and thus removing need for this assumption. As a side-effect, it lifts unjustified limitation by allowing to keep HANDLERs open when entering LOCK TABLES mode. mysql-test/include/handler.inc: Adjusted tests after making LOCK TABLES not to close open HANDLERs. Added coverage for bug #50908 "Assertion `handler_tables_hash.records == 0' failed in enter_locked_tables_mode". mysql-test/r/handler_innodb.result: Updated test results (see include/handler.inc). mysql-test/r/handler_myisam.result: Updated test results (see include/handler.inc). sql/mysql_priv.h: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_class.cc: Changed THD::leave_locked_tables_mode() to correctly restore MDL sentinel value in the presence of open HANDLERs. sql/sql_class.h: Removed assert from THD::enter_locked_tables_mode() as we no longer have to close HANDLERs when entering LOCK TABLES or prelocked modes. Instead we keep them open and correctly restore MDL sentinel value after leaving them. Removal of assert also fixes problem from the bug report. sql/sql_handler.cc: Introduced mysql_ha_move_tickets_after_trans_sentinel() routine which allows to move tickets for metadata locks corresponding to open HANDLERs after transaction sentinel. sql/sql_parse.cc: We no longer have to close HANDLERs when entering LOCK TABLES mode. Instead we keep them open and simply correctly restore MDL sentinel value after leaving this mode.
2010-02-12 10:05:43 +03:00
--echo #
--echo # Test for bug #50908 "Assertion `handler_tables_hash.records == 0'
--echo # failed in enter_locked_tables_mode".
--echo #
--disable_warnings
drop tables if exists t1, t2;
drop function if exists f1;
--enable_warnings
create table t1 (i int);
insert into t1 values (1), (2);
create table t2 (j int);
insert into t2 values (1);
create function f1() returns int return (select count(*) from t2);
--echo # Check that open HANDLER survives statement executed in
--echo # prelocked mode.
handler t1 open;
handler t1 read next;
--echo # The below statement were aborted due to an assertion failure.
select f1() from t2;
handler t1 read next;
handler t1 close;
--echo # Check that the same happens under GLOBAL READ LOCK.
flush tables with read lock;
handler t1 open;
handler t1 read next;
select f1() from t2;
handler t1 read next;
unlock tables;
handler t1 close;
--echo # Now, check that the same happens if LOCK TABLES is executed.
handler t1 open;
handler t1 read next;
lock table t2 read;
select * from t2;
unlock tables;
handler t1 read next;
handler t1 close;
--echo # Finally, check scenario with GRL and LOCK TABLES.
flush tables with read lock;
handler t1 open;
handler t1 read next;
lock table t2 read;
select * from t2;
--echo # This unlocks both tables and GRL.
unlock tables;
handler t1 read next;
handler t1 close;
--echo # Clean-up.
drop function f1;
drop tables t1, t2;
Fix for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY + HANDLER + LOCK + SP". Server crashed when one: 1) Opened HANDLER or acquired global read lock 2) Then locked one or several temporary tables with LOCK TABLES statement (but no base tables). 3) Then issued any statement causing commit (explicit or implicit). 4) Issued statement which should have closed HANDLER or released global read lock. The problem was that when entering LOCK TABLES mode in the scenario described above we incorrectly set transactional MDL sentinel to zero. As result during commit all metadata locks were released (including lock for open HANDLER or global metadata shared lock). Indeed, attempt to release metadata lock for the second time which happened during HANLDER CLOSE or during release of GLR caused crash. This patch fixes problem by changing MDL_context's set_trans_sentinel() method to set sentinel to correct value (it should point to the most recent ticket). mysql-test/include/handler.inc: Added test for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY + HANDLER + LOCK + SP". mysql-test/r/flush.result: Updated test results (see flush.test). mysql-test/r/handler_innodb.result: Updated test results (see include/handler.inc). mysql-test/r/handler_myisam.result: Updated test results (see include/handler.inc). mysql-test/t/flush.test: Added additional coverage for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY + HANDLER + LOCK + SP". sql/mdl.h: When setting new value of transactional sentinel use pointer to the most recent ticket instead of value returned by MDL_context::mdl_savepoint(). This allows to handle correctly situation when the new value of sentinel should be the same as its current value (MDL_context::mdl_savepoint() returns NULL in this case).
2010-02-15 14:23:36 +03:00
--echo #
--echo # Test for bug #51136 "Crash in pthread_rwlock_rdlock on TEMPORARY +
--echo # HANDLER + LOCK + SP".
--echo # Also see additional coverage for this bug in flush.test.
--echo #
--disable_warnings
drop tables if exists t1, t2;
--enable_warnings
create table t1 (i int);
create temporary table t2 (j int);
handler t1 open;
lock table t2 read;
--echo # This commit should not release any MDL locks.
commit;
unlock tables;
--echo # The below statement crashed before the bug fix as it
--echo # has attempted to release metadata lock which was
--echo # already released by commit.
handler t1 close;
drop tables t1, t2;
--echo #
--echo # Bug#51355 handler stmt cause assertion in
--echo # bool MDL_context::try_acquire_lock(MDL_request*)
--echo #
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
connect(con51355, localhost, root);
--echo # Connection default
connection default;
CREATE TABLE t1(id INT, KEY id(id));
HANDLER t1 OPEN;
--echo # Connection con51355
connection con51355;
--echo # Sending:
--send DROP TABLE t1
--echo # Connection default
connection default;
--echo # This I_S query will cause the handler table to be closed and
--echo # the metadata lock to be released. This will allow DROP TABLE
--echo # to proceed. Waiting for the table to be removed.
let $wait_condition=
SELECT COUNT(*) = 0 FROM information_schema.tables WHERE table_name = "t1";
--source include/wait_condition.inc
--echo # Connection con51355
connection con51355;
--echo # Reaping: DROP TABLE t1
--reap
--echo # Connection default
connection default;
--error ER_NO_SUCH_TABLE
HANDLER t1 READ id NEXT;
# This caused an assertion
--error ER_NO_SUCH_TABLE
HANDLER t1 READ id NEXT;
HANDLER t1 CLOSE;
--echo # Connection con51355
connection con51355;
disconnect con51355;
--source include/wait_until_disconnected.inc
--echo # Connection default
connection default;
--echo #
--echo # Bug#54401 assert in Diagnostics_area::set_eof_status , HANDLER
--echo #
--disable_warnings
DROP TABLE IF EXISTS t1, t2;
DROP FUNCTION IF EXISTS f1;
--enable_warnings
delimiter |;
CREATE FUNCTION f1() RETURNS INTEGER
BEGIN
SELECT 1 FROM t2 INTO @a;
RETURN 1;
END|
delimiter ;|
# Get f1() parsed and cached
--error ER_NO_SUCH_TABLE
SELECT f1();
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES (1);
HANDLER t1 OPEN;
# This used to cause the assert
--error ER_NOT_SUPPORTED_YET
HANDLER t1 READ FIRST WHERE f1() = 1;
HANDLER t1 CLOSE;
DROP FUNCTION f1;
DROP TABLE t1;
--echo #
--echo # Bug#54920 Stored functions are allowed in HANDLER statements,
--echo # but broken.
--echo #
--disable_warnings
DROP TABLE IF EXISTS t1;
DROP FUNCTION IF EXISTS f1;
--enable_warnings
CREATE TABLE t1 (a INT);
INSERT INTO t1 VALUES (1), (2);
CREATE FUNCTION f1() RETURNS INT RETURN 1;
HANDLER t1 OPEN;
--error ER_NOT_SUPPORTED_YET
HANDLER t1 READ FIRST WHERE f1() = 1;
HANDLER t1 CLOSE;
DROP FUNCTION f1;
DROP TABLE t1;
- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
--echo #
--echo # BUG#51877 - HANDLER interface causes invalid memory read
--echo #
CREATE TABLE t1(a INT, KEY using btree (a));
- Fixed that Aria works with HANDLER commands - Added test case for Aria - Tested HANDLER with HEAP (changes to HEAP code will be pushed in 5.3) - Moved all HANDLER test to suite/handler. mysql-test/Makefile.am: Added suite/handler mysql-test/mysql-test-run.pl: Added suite/handler mysql-test/r/lock_multi.result: Remove test that is already in handler test suite mysql-test/suite/handler/aria.result: Test for HANDLER with Aria storage engine mysql-test/suite/handler/aria.test: Test for HANDLER with Aria storage engine mysql-test/suite/handler/handler.inc: Extended the general handler test Moved interface testing to 'interface.test' mysql-test/suite/handler/init.inc: Common init for handler tests. mysql-test/suite/handler/innodb.result: New results mysql-test/suite/handler/innodb.test: Update to use new include files mysql-test/suite/handler/interface.result: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/interface.test: Test of HANDLER interface (not storage engine dependent parts) mysql-test/suite/handler/myisam.result: New results mysql-test/suite/handler/myisam.test: Update to use new include files mysql-test/t/lock_multi.test: Remove test that is already in handler test suite mysys/tree.c: Added missing handling of read previous (showed up in HEAP testing) sql/handler.cc: Don't marka 'HA_ERR_RECORD_CHANGED' as fatal (can be used with HANDLER READ, especially with MEMORY ENGINE) sql/handler.h: Added prototype for can_continue_handler_scan() sql/sql_handler.cc: Re-initialize search if we switch from key to table search. Check if handler can continue searching between calls (via can_continue_handler_scan()) Don't write common not fatal errors to log storage/maria/ma_extra.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_ft_boolean_search.c: Ensure that info->last_key.keyinfo is set storage/maria/ma_open.c: Don't set index 0 as default. This forces call to ma_check_index() to set up index variables. storage/maria/ma_rkey.c: Trivial optimization storage/maria/ma_rnext.c: Added missing code from mi_rnext.c to ensure that handler next/prev works. storage/maria/ma_rsame.c: Simple optimizations storage/maria/ma_search.c: Initialize info->last_key once and for all when we change keys. storage/maria/ma_unique.c: Ensure that info->last_key.keyinfo is up to date.
2011-01-10 23:22:40 +02:00
HANDLER t1 OPEN;
HANDLER t1 READ a FIRST;
INSERT INTO t1 VALUES(1);
--error 0,ER_CHECKREAD
HANDLER t1 READ a NEXT;
HANDLER t1 CLOSE;
DROP TABLE t1;