From: Dmitry Lenev Date: November 8 2010 10:04am Subject: bzr push into mysql-5.5-runtime branch (Dmitry.Lenev:3188 to 3189) List-Archive: http://lists.mysql.com/commits/123055 Message-Id: <20101108100430.79A7A2F0E23@mockturtle> MIME-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit 3189 Dmitry Lenev 2010-11-08 More changes to draft patch refactoring global read lock implementation. Makes GRL yet another type of metadata lock and thus exposes it to deadlock detector in MDL subsystem. Solves bugs #54673 "It takes too long to get readlock for 'FLUSH TABLES WITH READ LOCK'" and #57006 "Deadlock between HANDLER and FLUSH TABLES WITH READ LOCK". Work-in-progress. Minor after review fixes. modified: sql/lock.cc sql/sql_base.cc sql/sql_class.h sql/sql_insert.cc sql/sql_parse.cc sql/sql_parse.h 3188 Dmitry Lenev 2010-11-03 [merge] Merge recent changes from mysql-5.5-runtime into mysql-5.5-rt-stage tree. removed: storage/innobase/handler/mysql_addons.cc storage/innobase/include/mysql_addons.h storage/innobase/mysql-test/ storage/innobase/mysql-test/patches/ storage/innobase/mysql-test/patches/README storage/innobase/mysql-test/patches/index_merge_innodb-explain.diff storage/innobase/mysql-test/patches/information_schema.diff storage/innobase/mysql-test/patches/innodb_change_buffering_basic.diff storage/innobase/mysql-test/patches/innodb_file_per_table.diff storage/innobase/mysql-test/patches/innodb_lock_wait_timeout.diff storage/innobase/mysql-test/patches/innodb_thread_concurrency_basic.diff storage/innobase/mysql-test/patches/partition_innodb.diff added: mysql-test/extra/rpl_tests/rpl_stop_slave.test mysql-test/include/have_plugin_interface.inc mysql-test/include/have_plugin_server.inc mysql-test/r/lowercase_table4.result mysql-test/r/plugin_auth_qa.result mysql-test/r/plugin_auth_qa_1.result mysql-test/r/plugin_auth_qa_2.result mysql-test/r/plugin_auth_qa_3.result mysql-test/suite/innodb/r/innodb_bug56143.result mysql-test/suite/innodb/r/innodb_bug56632.result mysql-test/suite/innodb/r/innodb_bug56680.result mysql-test/suite/innodb/r/innodb_bug57252.result mysql-test/suite/innodb/r/innodb_bug57255.result mysql-test/suite/innodb/t/innodb_bug56143.test mysql-test/suite/innodb/t/innodb_bug56632.test mysql-test/suite/innodb/t/innodb_bug56680.test mysql-test/suite/innodb/t/innodb_bug57252.test mysql-test/suite/innodb/t/innodb_bug57255.test mysql-test/suite/rpl/r/rpl_stop_slave.result mysql-test/suite/rpl/t/rpl_stop_slave.test mysql-test/t/lowercase_table4-master.opt mysql-test/t/lowercase_table4.test mysql-test/t/plugin_auth_qa-master.opt mysql-test/t/plugin_auth_qa.test mysql-test/t/plugin_auth_qa_1-master.opt mysql-test/t/plugin_auth_qa_1.test mysql-test/t/plugin_auth_qa_2-master.opt mysql-test/t/plugin_auth_qa_2.test mysql-test/t/plugin_auth_qa_3-master.opt mysql-test/t/plugin_auth_qa_3.test plugin/auth/qa_auth_client.c plugin/auth/qa_auth_interface.c plugin/auth/qa_auth_server.c modified: BUILD/SETUP.sh CMakeLists.txt Makefile.am client/mysql.cc client/mysqlbinlog.cc client/mysqltest.cc client/sql_string.h cmake/abi_check.cmake cmake/os/Linux.cmake cmd-line-utils/libedit/common.c cmd-line-utils/libedit/readline.c cmd-line-utils/libedit/vi.c cmd-line-utils/readline/complete.c cmd-line-utils/readline/histexpand.c cmd-line-utils/readline/histfile.c cmd-line-utils/readline/isearch.c cmd-line-utils/readline/parens.c cmd-line-utils/readline/readline.c cmd-line-utils/readline/terminal.c cmd-line-utils/readline/text.c config/ac-macros/maintainer.m4 configure.cmake configure.in dbug/dbug.c include/my_compiler.h include/my_dbug.h include/my_getopt.h include/my_pthread.h include/mysql/client_plugin.h include/mysql/client_plugin.h.pp include/mysql/plugin_auth.h mysql-test/collections/default.experimental mysql-test/extra/binlog_tests/implicit.test mysql-test/extra/rpl_tests/create_recursive_construct.inc mysql-test/extra/rpl_tests/rpl_get_master_version_and_clock.test mysql-test/extra/rpl_tests/rpl_loaddata.test mysql-test/extra/rpl_tests/rpl_start_stop_slave.test mysql-test/include/check_concurrent_insert.inc mysql-test/include/check_no_concurrent_insert.inc mysql-test/include/get_relay_log_pos.inc mysql-test/include/kill_query.inc mysql-test/include/kill_query_and_diff_master_slave.inc mysql-test/include/mtr_warnings.sql mysql-test/include/setup_fake_relay_log.inc mysql-test/include/show_events.inc mysql-test/include/show_rpl_debug_info.inc mysql-test/include/wait_for_slave_io_error.inc mysql-test/include/wait_for_slave_param.inc mysql-test/include/wait_for_slave_sql_error.inc mysql-test/include/wait_for_status_var.inc mysql-test/lib/mtr_misc.pl mysql-test/lib/mtr_process.pl mysql-test/mysql-test-run.pl mysql-test/r/ctype_binary.result mysql-test/r/ctype_cp1251.result mysql-test/r/ctype_latin1.result mysql-test/r/ctype_ucs.result mysql-test/r/ctype_utf8.result mysql-test/r/func_time.result mysql-test/r/grant.result mysql-test/r/grant3.result mysql-test/r/ipv4_as_ipv6.result mysql-test/r/kill.result mysql-test/r/mysqlbinlog.result mysql-test/r/ps.result mysql-test/r/select.result mysql-test/r/signal.result mysql-test/r/sp-error.result mysql-test/r/trigger.result mysql-test/r/type_blob.result mysql-test/suite/binlog/t/binlog_unsafe.test mysql-test/suite/binlog/t/disabled.def mysql-test/suite/funcs_1/r/innodb_trig_08.result mysql-test/suite/funcs_1/r/memory_trig_08.result mysql-test/suite/funcs_1/r/myisam_trig_08.result mysql-test/suite/perfschema/include/setup_helper.inc mysql-test/suite/perfschema/r/dml_threads.result mysql-test/suite/perfschema/r/func_file_io.result mysql-test/suite/perfschema/r/schema.result mysql-test/suite/perfschema/r/selects.result mysql-test/suite/perfschema/t/dml_threads.test mysql-test/suite/perfschema/t/func_file_io.test mysql-test/suite/perfschema/t/selects.test mysql-test/suite/perfschema/t/thread_cache.test mysql-test/suite/rpl/r/rpl_do_grant.result mysql-test/suite/rpl/r/rpl_row_trig003.result mysql-test/suite/rpl/r/rpl_stm_start_stop_slave.result mysql-test/suite/rpl/r/rpl_temp_table_mix_row.result mysql-test/suite/rpl/t/rpl_do_grant.test mysql-test/suite/rpl/t/rpl_killed_ddl.test mysql-test/suite/rpl/t/rpl_temp_table_mix_row.test mysql-test/suite/sys_vars/r/all_vars.result mysql-test/suite/sys_vars/t/all_vars.test mysql-test/t/disabled.def mysql-test/t/func_time.test mysql-test/t/grant.test mysql-test/t/grant3.test mysql-test/t/kill.test mysql-test/t/mysqlbinlog.test mysql-test/t/mysqltest.test mysql-test/t/ps.test mysql-test/t/select.test mysql-test/t/sp-error.test mysql-test/t/type_blob.test mysql-test/t/wait_timeout.test mysys/my_gethostbyname.c mysys/my_gethwaddr.c mysys/my_getopt.c mysys/my_sync.c mysys/thr_mutex.c plugin/auth/CMakeLists.txt plugin/auth/Makefile.am plugin/auth/dialog.c plugin/auth/test_plugin.c regex/main.c scripts/mysql_system_tables.sql sql/event_queue.cc sql/field.cc sql/field.h sql/ha_ndbcluster.cc sql/handler.cc sql/item_func.cc sql/item_subselect.cc sql/item_timefunc.h sql/key.cc sql/log.cc sql/log_event.cc sql/log_event.h sql/my_decimal.h sql/rpl_record.cc sql/rpl_rli.h sql/slave.cc sql/sp.cc sql/sp_head.cc sql/sp_head.h sql/sql_acl.cc sql/sql_base.h sql/sql_class.cc sql/sql_class.h sql/sql_help.cc sql/sql_lex.h sql/sql_parse.cc sql/sql_partition.cc sql/sql_partition_admin.cc sql/sql_prepare.cc sql/sql_select.cc sql/sql_show.cc sql/sql_string.h sql/sql_union.cc sql/sql_yacc.yy storage/innobase/CMakeLists.txt storage/innobase/Makefile.am storage/innobase/btr/btr0cur.c storage/innobase/buf/buf0buddy.c storage/innobase/buf/buf0buf.c storage/innobase/buf/buf0flu.c storage/innobase/buf/buf0lru.c storage/innobase/dict/dict0load.c storage/innobase/handler/ha_innodb.cc storage/innobase/handler/ha_innodb.h storage/innobase/ibuf/ibuf0ibuf.c storage/innobase/include/btr0cur.h storage/innobase/include/buf0buddy.h storage/innobase/include/buf0buddy.ic storage/innobase/include/buf0buf.h storage/innobase/include/buf0buf.ic storage/innobase/include/buf0flu.h storage/innobase/include/data0type.h storage/innobase/include/db0err.h storage/innobase/include/dict0load.h storage/innobase/include/dict0mem.h storage/innobase/include/ibuf0ibuf.h storage/innobase/include/os0sync.h storage/innobase/include/que0que.h storage/innobase/include/rem0rec.h storage/innobase/include/row0mysql.h storage/innobase/include/row0upd.h storage/innobase/include/srv0srv.h storage/innobase/include/sync0sync.h storage/innobase/include/trx0trx.h storage/innobase/include/trx0undo.h storage/innobase/lock/lock0lock.c storage/innobase/log/log0log.c storage/innobase/os/os0file.c storage/innobase/os/os0sync.c storage/innobase/plug.in storage/innobase/rem/rem0rec.c storage/innobase/row/row0merge.c storage/innobase/row/row0mysql.c storage/innobase/row/row0sel.c storage/innobase/row/row0upd.c storage/innobase/srv/srv0srv.c storage/innobase/srv/srv0start.c storage/innobase/sync/sync0sync.c storage/innobase/trx/trx0i_s.c storage/innobase/trx/trx0trx.c storage/innobase/trx/trx0undo.c storage/innobase/ut/ut0ut.c storage/myisam/myisamchk.c storage/perfschema/table_threads.cc storage/perfschema/table_threads.h strings/ctype-ucs2.c support-files/mysql.spec.sh unittest/examples/skip-t.c unittest/examples/skip_all-t.c unittest/examples/todo-t.c unittest/mytap/t/basic-t.c unittest/mytap/tap.c unittest/mytap/tap.h === modified file 'sql/lock.cc' --- a/sql/lock.cc 2010-11-03 18:09:02 +0000 +++ b/sql/lock.cc 2010-11-08 09:55:43 +0000 @@ -779,17 +779,8 @@ bool lock_schema_name(THD *thd, const ch if (thd->global_read_lock.can_acquire_protection()) return TRUE; - - /* - This function can be only called during execution of a DDL statement. - Since such statements release all metadata locks at its end we don't - need to do anything special to ensure that protection against GRL is - released. - */ - DBUG_ASSERT(stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END)); - - thd->global_read_lock.init_protection_request(&global_request); - + global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, + MDL_STATEMENT); mdl_request.init(MDL_key::SCHEMA, db, "", MDL_EXCLUSIVE, MDL_TRANSACTION); mdl_requests.push_front(&mdl_request); @@ -847,16 +838,8 @@ bool lock_object_name(THD *thd, MDL_key: if (thd->global_read_lock.can_acquire_protection()) return TRUE; - - /* - This function can be only called during execution of a DDL statement. - Since such statements release all metadata locks at its end we don't - need to do anything special to ensure that protection against GRL is - released. - */ - DBUG_ASSERT(stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END)); - - thd->global_read_lock.init_protection_request(&global_request); + global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, + MDL_STATEMENT); schema_request.init(MDL_key::SCHEMA, db, "", MDL_INTENTION_EXCLUSIVE, MDL_TRANSACTION); mdl_request.init(mdl_type, db, name, MDL_EXCLUSIVE, MDL_TRANSACTION); @@ -1034,38 +1017,6 @@ void Global_read_lock::unlock_global_rea /** - Check if this connection can acquire protecting against GRL and - emit error if otherwise. - - QQ: Does it make sense to make it inline? -*/ - -bool Global_read_lock::can_acquire_protection() -{ - if (m_state) - { - my_error(ER_CANT_UPDATE_WITH_READLOCK, MYF(0)); - return TRUE; - } - return FALSE; -} - - -/** - Initialize request for lock protecting normal statement from GRL - (and vice versa). - - QQ: Does it make sense to make it inline? -*/ - -void Global_read_lock::init_protection_request(MDL_request *request) -{ - request->init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, - MDL_STATEMENT); -} - - -/** Make global read lock also block commits. The scenario is: === modified file 'sql/sql_base.cc' --- a/sql/sql_base.cc 2010-11-03 14:30:33 +0000 +++ b/sql/sql_base.cc 2010-11-08 09:55:43 +0000 @@ -2822,7 +2822,8 @@ bool open_table(THD *thd, TABLE_LIST *ta if (thd->global_read_lock.can_acquire_protection()) DBUG_RETURN(TRUE); - thd->global_read_lock.init_protection_request(&protection_request); + protection_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, + MDL_STATEMENT); /* Install error handler which if possible will convert deadlock error into request to back-off and restart process of opening tables. @@ -4579,18 +4580,15 @@ lock_table_names(THD *thd, mdl_requests.push_front(schema_request); } - if (thd->global_read_lock.can_acquire_protection()) - return TRUE; - /* - We can get here only during execution of code which will release - all metadata locks by the statement's end. So we don't need to do - anything special to ensure that protection against GRL is released. - - QQ: This assumption is kind of ugly and hard to enforce using asserts. - Is there any nice way to get rid of it? + Protect this statement against concurrent global read lock + by acquiring global intention exclusive lock with statement + duration. */ - thd->global_read_lock.init_protection_request(&global_request); + if (thd->global_read_lock.can_acquire_protection()) + return TRUE; + global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, + MDL_STATEMENT); mdl_requests.push_front(&global_request); } === modified file 'sql/sql_class.h' --- a/sql/sql_class.h 2010-11-03 18:09:02 +0000 +++ b/sql/sql_class.h 2010-11-08 09:55:43 +0000 @@ -1343,9 +1343,19 @@ public: bool lock_global_read_lock(THD *thd); void unlock_global_read_lock(THD *thd); - bool can_acquire_protection(); - bool has_read_lock() const { return (m_state != GRL_NONE); } - void init_protection_request(MDL_request *request); + /** + Check if this connection can acquire protection against GRL and + emit error if otherwise. + */ + bool can_acquire_protection() const + { + if (m_state) + { + my_error(ER_CANT_UPDATE_WITH_READLOCK, MYF(0)); + return TRUE; + } + return FALSE; + } bool make_global_read_lock_block_commit(THD *thd); bool is_acquired() const { return m_state != GRL_NONE; } void set_explicit_lock_duration(THD *thd); === modified file 'sql/sql_insert.cc' --- a/sql/sql_insert.cc 2010-11-03 14:30:33 +0000 +++ b/sql/sql_insert.cc 2010-11-08 09:55:43 +0000 @@ -545,7 +545,8 @@ bool open_and_lock_for_insert_delayed(TH if (thd->global_read_lock.can_acquire_protection()) DBUG_RETURN(TRUE); - thd->global_read_lock.init_protection_request(&protection_request); + protection_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, + MDL_STATEMENT); if (thd->mdl_context.acquire_lock(&protection_request, thd->variables.lock_wait_timeout)) === modified file 'sql/sql_parse.cc' --- a/sql/sql_parse.cc 2010-11-03 18:09:02 +0000 +++ b/sql/sql_parse.cc 2010-11-08 09:55:43 +0000 @@ -187,7 +187,7 @@ static bool some_non_temp_table_to_be_up @param mask Bitmask used for the SQL command match. */ -bool stmt_causes_implicit_commit(THD *thd, uint mask) +static bool stmt_causes_implicit_commit(THD *thd, uint mask) { LEX *lex= thd->lex; bool skip= FALSE; === modified file 'sql/sql_parse.h' --- a/sql/sql_parse.h 2010-10-18 12:33:49 +0000 +++ b/sql/sql_parse.h 2010-11-08 09:55:43 +0000 @@ -78,7 +78,6 @@ bool check_host_name(LEX_STRING *str); bool check_identifier_name(LEX_STRING *str, uint max_char_length, uint err_code, const char *param_for_err_msg); bool mysql_test_parse_for_slave(THD *thd,char *inBuf,uint length); -bool stmt_causes_implicit_commit(THD *thd, uint mask); bool sqlcom_can_generate_row_events(const THD *thd); bool is_update_query(enum enum_sql_command command); bool is_log_table_write_query(enum enum_sql_command command); No bundle (reason: useless for push emails).