Skip to content

Commit 43c0d70

Browse files
author
Dmitry Lenev
committed
Pre-requisite patch for bug #51263 "Deadlock between
transactional SELECT and ALTER TABLE ... REBUILD PARTITION". The goal of this patch is to decouple type of metadata lock acquired for table by open_tables() from type of table-level lock to be acquired on it. To achieve this we change approach to how we determine what type of metadata lock should be acquired on table to be open. Now instead of inferring it at open_tables() time from flags and type of table-level lock we rely on that type of metadata lock is properly set at parsing time and is not changed further. --BZR-- revision-id: [email protected] property-branch-nick: mysql-trunk-rt-bg51263-pre property-file-info: ld7:file_id69:sp1f-ha_ndbcluster.cc-20040414175836-rvqnoxrkqexyhfu3d62s4t345ip7rez27:message115:Now one needs to properly initialize table list element's property-file-info: MDL_request object before calling mysql_rm_table_part2().4:path20:sql/ha_ndbcluster.cced7:file_id60:sp1f-lock.cc-19700101030959-lzrt5tyolna3dcihuenjh7nlicr7llt77:message161:lock_table_names() no longer initializes table list elements' property-file-info: MDL_request objects. Now proper initialization of these property-file-info: requests is a responsibility of the caller.4:path11:sql/lock.cced7:file_id41:lock.h-20100331135644-cgcb6oowzqyx7fi3-107:message324:Removed MYSQL_OPEN_TAKE_UPGRADABLE_MDL flag which became property-file-info: unnecessary. Thanks to the fact that we don't reset type of property-file-info: requests for metadata locks between re-executions we now can property-file-info: figure out that upgradable locks are requested by simply property-file-info: looking at their type which were set in the parser. As result property-file-info: this flag became redundant.4:path10:sql/lock.hed7:file_id39:mdl.h-20080523121748-o4y2wcq3maotb9do-17:message95:Added version of new operator which simplifies allocation of property-file-info: MDL_request objects on a MEM_ROOT.4:path9:sql/mdl.hed7:file_id63:sp1f-sp_head.cc-20021208185920-jtgc5wvyqdnu2gvcdus3gazrfhxbofxd7:message231:Added comment explaining why it is OK to infer type of property-file-info: metadata lock to request from type of table-level lock property-file-info: for prelocking. property-file-info: Added enum_mdl_type argument to sp_add_to_query_tables() property-file-info: to simplify its usage in trigger implementation.4:path14:sql/sp_head.cced7:file_id62:sp1f-sp_head.h-20021208185920-yrolg3rzamehfoejkbiai4q7njg5w6cd7:message105:Added enum_mdl_type argument to sp_add_to_query_tables() property-file-info: to simplify its usage in trigger implementation.4:path13:sql/sp_head.hed7:file_id64:sp1f-sql_base.cc-19700101030959-w7tul2gb2n4jzayjwlslj3ybmf3uhk6a7:message1763:- open_table_get_mdl_lock(): property-file-info: Preserve type of MDL_request for table list element which property-file-info: was set in the parser by creating MDL_request objects on property-file-info: memory root if MYSQL_OPEN_FORCE_SHARED_MDL or property-file-info: MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL flag were specified. property-file-info: Thanks to this and to the fact that we no longer reset property-file-info: type of requests for metadata locks between re-executions property-file-info: we no longer need to acquire exclusive metadata lock on property-file-info: table to be created in a special way. This lock is acquired property-file-info: by code handling acquiring of upgradable locks. property-file-info: Also changed signature/calling convention for this function property-file-info: to simplify its usage. property-file-info: - Accordingly special lock strategy for table list elements property-file-info: which was used for such locks became unnecessary and was property-file-info: removed. Other strategies were renamed. property-file-info: - Since we no longer have guarantee that MDL_request object property-file-info: which were not satisfied due to lock conflict belongs to property-file-info: table list element Open_table_context class and its methods property-file-info: were extended to remember pointer to MDL_request which has property-file-info: caused problem at request_backoff_action() time and use it property-file-info: in recover_from_failed_open(). Similar approach is used property-file-info: for cases when problem from which we need to recover is property-file-info: not related to MDL but to the table itself. In this case property-file-info: we store pointer to the element of table list. property-file-info: - Changed open_tables()/open_tables_check_upgradable_mdl()/ property-file-info: open_tables_acquire_upgradable_mdl() not to rely on property-file-info: MYSQL_OPEN_TAKE_UPGRADABLE_MDL flag to understand when property-file-info: upgradable metadata locks should be acquired and not to property-file-info: infer type of MDL lock from type of table-level lock. property-file-info: Instead we assume that type of MDL to be acquired was set property-file-info: in the parser (we can do this as type of MDL_request is property-file-info: no longer reset between re-executions).4:path15:sql/sql_base.cced7:file_id64:sp1f-sql_class.h-19700101030959-jnqnbrjyqsvgncsibnumsmg3lyi7pa5s7:message508:Since we no longer have guarantee that MDL_request object property-file-info: which were not satisfied due to lock conflict belongs to property-file-info: table list element Open_table_context class and its methods property-file-info: were extended to remember pointer to MDL_request which has property-file-info: caused problem at request_backoff_action() time and use it property-file-info: in recover_from_failed_open(). Similar approach is used property-file-info: for cases when problem from which we need to recover is property-file-info: not related to MDL but to the table itself. In this case property-file-info: we store pointer to the element of table list.4:path15:sql/sql_class.hed7:file_id62:sp1f-sql_db.cc-19700101030959-hyw6zjuisjyda5cj5746a2zzuzz5yibr7:message140:Now one needs to properly initialize table list element's property-file-info: MDL_request object before calling mysql_rm_table_part2() property-file-info: or mysql_rename_tables().4:path13:sql/sql_db.cced7:file_id63:sp1f-sql_lex.cc-19700101030959-4pizwlu5rqkti27gcwsvxkawq6bc2kph7:message172:st_select_lex/st_select_lex_node::add_table_to_list() method property-file-info: now has argument which allows specify type of metadata lock property-file-info: to be requested for table list element being added.4:path14:sql/sql_lex.cced7:file_id62:sp1f-sql_lex.h-19700101030959-sgldb2sooc7twtw5q7pgjx7qzqiaa3sn7:message637:- st_select_lex/st_select_lex_node::add_table_to_list() property-file-info: method now has argument which specifies type of metadata property-file-info: lock to be requested for table list element being added. property-file-info: This allows to explicitly set type of MDL lock to be property-file-info: acquired for a DDL statement in parser. It is also more property-file-info: future-proof than inferring type of MDL request from type property-file-info: of table-level lock. property-file-info: - Added Yacc_state::m_mdl_type member which specifies which property-file-info: type of metadata lock should be requested for tables to be property-file-info: added to table list by a grammar rule in cases when the same property-file-info: rule is used in several statements requiring different kinds property-file-info: of metadata locks.4:path13:sql/sql_lex.hed7:file_id65:sp1f-sql_parse.cc-19700101030959-ehcre3rwhv5l3mlxqhaxg36ujenxnrcd7:message690:- st_select_lex::add_table_to_list() method now has argument property-file-info: which specifies type of metadata lock to be requested for property-file-info: table list element being added. This allows to explicitly property-file-info: set type of MDL lock to be acquired for a DDL statement in property-file-info: parser. It is also more future-proof than inferring type of property-file-info: MDL request from type of table-level lock. property-file-info: - EXCLUSIVE_DOWNGRADABLE_MDL lock strategy has a new name - property-file-info: OTLS_DOWNGRADE_IF_EXISTS. property-file-info: - Adjusted LOCK TABLES implementation to the fact that we no property-file-info: longer infer type of metadata lock to be acquired from table property-file-info: level lock and that type of MDL request is set at parsing. property-file-info: And thus MYSQL_OPEN_TAKE_UPGRADABLE_MDL flag became property-file-info: unnecessary.4:path16:sql/sql_parse.cced7:file_id67:sp1f-sql_prepare.cc-20020612210720-gtqjjiu7vpmfxb5xct2qke7urmqcabli7:message227:TABLE_LIST's lock strategy SHARED_MDL was renamed to OTLS_NONE property-file-info: as now it means that metadata lock should not be changed during property-file-info: call to open_table() (if it has been already acquired) and is property-file-info: also used for exclusive metadata lock.4:path18:sql/sql_prepare.cced7:file_id64:sp1f-sql_show.cc-19700101030959-umlljfnpplg452h7reeyqr4xnbmlkvfj7:message148:st_select_lex::add_table_to_list() method now has argument property-file-info: which specifies type of metadata lock to be requested for property-file-info: table list element being added.4:path15:sql/sql_show.cced7:file_id65:sp1f-sql_table.cc-19700101030959-tzdkvgigezpuaxnldqh3fx2h7h2ggslu7:message786:- Adjusted mysql_admin_table()'s code to the fact that property-file-info: open_tables() no longer determines what kind of metadata property-file-info: lock should be obtained basing on type of table-level property-file-info: lock and flags. Instead type of metadata lock for table property-file-info: to be open should be set before calling open_tables(). property-file-info: - Changed mysql_alter_table() code to the facts: property-file-info: a) that now it is responsibility of caller to properly property-file-info: initalize MDL_request in table list elements before calling property-file-info: lock_table_names() property-file-info: b) and that MYSQL_OPEN_TAKE_UPGRADABLE_MDL is no longer property-file-info: necessary since type of metadata lock to be obtained property-file-info: at open_tables() time is set during parsing. property-file-info: - Changed code of mysql_recreate_table() to properly set property-file-info: type of metadata and table-level lock to be obtained property-file-info: by mysql_alter_table() which it calls.4:path16:sql/sql_table.cced7:file_id67:sp1f-sql_trigger.cc-20040907122911-35k3wamrp6g7qsupxe7hisftpobcwin57:message236:Instead of relying on MYSQL_OPEN_TAKE_UPGRADABLE_MDL flag to property-file-info: force open_tables() to take an upgradable lock we now specify property-file-info: exact type of lock to be taken when constructing table list property-file-info: element for table to be open for CREATE/DROP TRIGGER.4:path18:sql/sql_trigger.cced7:file_id64:sp1f-sql_view.cc-20040715221517-nw4p4mja6nzzlvwwhzfgfqb4umxqobe47:message355:We no longer use TABLE_LIST::EXCLUSIVE_MDL strategy to force property-file-info: open_tables() to take an exclusive metadata lock on view to property-file-info: be created. Instead we rely on parser setting proper type of property-file-info: metadata lock to request and open_tables() acquiring it. property-file-info: This became possible thanks to the fact that we no longer property-file-info: reset type of MDL_request between statement re-executions.4:path15:sql/sql_view.cced7:file_id64:sp1f-sql_yacc.yy-19700101030959-wvn4qyy2drpmge7kaq3dysprbhlrv27j7:message707:Instead of inferring type of MDL_request for table to be property-file-info: open from type of table-level lock and flags passed to property-file-info: open_tables() we now explicitly specify them at parsing. property-file-info: This became possible thanks to the fact that we no longer property-file-info: reset type of MDL_request between statement re-executions. property-file-info: In future this should allow to decouple type of metadata property-file-info: lock from type of table-level lock. property-file-info: The only exception to this approach is statements implemented property-file-info: through mysql_admin_table() which re-uses same table list property-file-info: element several times with different types of table-level property-file-info: and metadata locks. property-file-info: We now also properly initialize MDL_request objects for table property-file-info: list elements which are later passed to lock_table_names() property-file-info: function.4:path15:sql/sql_yacc.yyed7:file_id61:sp1f-table.cc-19700101030959-nsxtem2adyqzwe6nz4cgrpcmts3o54v77:message253:Do not reset type of MDL_request between statement property-file-info: re-executions. This became unnecessesary as we no longer property-file-info: change type of MDL_request residing in table list element. property-file-info: In its turn this change allows to set type of MDL_request property-file-info: only once - at parsing time.4:path12:sql/table.cced7:file_id60:sp1f-table.h-19700101030959-dv72bajftxj5fbdjuajquappanuv2ija7:message659:Got rid of TABLE_LIST::EXCLUSIVE_MDL lock strategy. property-file-info: Now we can specify that we need to acquire exclusive lock property-file-info: on table to be processed by open_tables() through setting property-file-info: an appropriate type of MDL_request at parsing time (this property-file-info: became possible thanks to the fact that we no longer reset property-file-info: types of MDL_request's belonging to table list elements property-file-info: between statement re-execution). property-file-info: Strategy SHARED_MDL was renamed to OTLS_NONE as now it property-file-info: means that metadata lock should not be changed during call property-file-info: to open_table() (if it has been already acquired) and is property-file-info: also used for exclusive metadata lock. property-file-info: Strategy EXCLUSIVE_DOWNGRADABLE_MDL was renamed to property-file-info: OTLS_DOWNGRADE_IF_EXISTS.4:path11:sql/table.hee testament3-sha1: a58b5c7cbdd1729d04a448619da64d251267f983
1 parent 511cf8c commit 43c0d70

20 files changed

+357
-225
lines changed

sql/ha_ndbcluster.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7408,9 +7408,10 @@ int ndbcluster_find_files(handlerton *hton, THD *thd,
74087408
DBUG_PRINT("info", ("Remove table %s/%s", db, file_name_str));
74097409
// Delete the table and all related files
74107410
TABLE_LIST table_list;
7411-
bzero((char*) &table_list,sizeof(table_list));
7412-
table_list.db= (char*) db;
7413-
table_list.alias= table_list.table_name= (char*)file_name_str;
7411+
table_list.init_one_table(db, strlen(db), file_name_str,
7412+
strlen(file_name_str), file_name_str,
7413+
TL_WRITE);
7414+
table_list.mdl_request.set_tpye(MDL_EXCLUSIVE);
74147415
(void)mysql_rm_table_part2(thd, &table_list,
74157416
FALSE, /* if_exists */
74167417
FALSE, /* drop_temporary */

sql/lock.cc

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,8 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
880880
before calling it. Also it cannot be called while holding
881881
LOCK_open mutex. Both these invariants are enforced by asserts
882882
in MDL_context::acquire_locks().
883+
@note Initialization of MDL_request members of TABLE_LIST elements
884+
is a responsibility of the caller.
883885
884886
@retval FALSE Success.
885887
@retval TRUE Failure (OOM or thread was killed).
@@ -894,12 +896,7 @@ bool lock_table_names(THD *thd, TABLE_LIST *table_list)
894896
global_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE);
895897

896898
for (lock_table= table_list; lock_table; lock_table= lock_table->next_local)
897-
{
898-
lock_table->mdl_request.init(MDL_key::TABLE,
899-
lock_table->db, lock_table->table_name,
900-
MDL_EXCLUSIVE);
901899
mdl_requests.push_front(&lock_table->mdl_request);
902-
}
903900

904901
mdl_requests.push_front(&global_request);
905902

sql/lock.h

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,33 +15,32 @@ typedef struct st_mysql_lock MYSQL_LOCK;
1515
#define MYSQL_OPEN_TEMPORARY_ONLY 0x0004
1616
#define MYSQL_LOCK_IGNORE_GLOBAL_READ_ONLY 0x0008
1717
#define MYSQL_LOCK_LOG_TABLE 0x0010
18-
#define MYSQL_OPEN_TAKE_UPGRADABLE_MDL 0x0020
1918
/**
2019
Do not try to acquire a metadata lock on the table: we
2120
already have one.
2221
*/
23-
#define MYSQL_OPEN_HAS_MDL_LOCK 0x0040
22+
#define MYSQL_OPEN_HAS_MDL_LOCK 0x0020
2423
/**
2524
If in locked tables mode, ignore the locked tables and get
2625
a new instance of the table.
2726
*/
28-
#define MYSQL_OPEN_GET_NEW_TABLE 0x0080
27+
#define MYSQL_OPEN_GET_NEW_TABLE 0x0040
2928
/** Don't look up the table in the list of temporary tables. */
30-
#define MYSQL_OPEN_SKIP_TEMPORARY 0x0100
29+
#define MYSQL_OPEN_SKIP_TEMPORARY 0x0080
3130
/** Fail instead of waiting when conficting metadata lock is discovered. */
32-
#define MYSQL_OPEN_FAIL_ON_MDL_CONFLICT 0x0200
31+
#define MYSQL_OPEN_FAIL_ON_MDL_CONFLICT 0x0100
3332
/** Open tables using MDL_SHARED lock instead of one specified in parser. */
34-
#define MYSQL_OPEN_FORCE_SHARED_MDL 0x0400
33+
#define MYSQL_OPEN_FORCE_SHARED_MDL 0x0200
3534
/**
3635
Open tables using MDL_SHARED_HIGH_PRIO lock instead of one specified
3736
in parser.
3837
*/
39-
#define MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL 0x0800
38+
#define MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL 0x0400
4039
/**
4140
When opening or locking the table, use the maximum timeout
4241
(LONG_TIMEOUT = 1 year) rather than the user-supplied timeout value.
4342
*/
44-
#define MYSQL_LOCK_IGNORE_TIMEOUT 0x1000
43+
#define MYSQL_LOCK_IGNORE_TIMEOUT 0x0800
4544

4645
/** Please refer to the internals manual. */
4746
#define MYSQL_OPEN_REOPEN (MYSQL_OPEN_IGNORE_FLUSH |\

sql/mdl.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,10 @@ class MDL_request
308308
MDL_key key;
309309

310310
public:
311+
static void *operator new(size_t size, MEM_ROOT *mem_root) throw ()
312+
{ return alloc_root(mem_root, size); }
313+
static void operator delete(void *ptr, MEM_ROOT *mem_root) {}
314+
311315
void init(MDL_key::enum_mdl_namespace namespace_arg,
312316
const char *db_arg, const char *name_arg,
313317
enum_mdl_type mdl_type_arg);

sql/sp_head.cc

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4010,6 +4010,11 @@ sp_head::add_used_tables_to_table_list(THD *thd,
40104010
table->prelocking_placeholder= 1;
40114011
table->belong_to_view= belong_to_view;
40124012
table->trg_event_map= stab->trg_event_map;
4013+
/*
4014+
Since we don't allow DDL on base tables in prelocked mode it
4015+
is safe to infer the type of metadata lock from the type of
4016+
table lock.
4017+
*/
40134018
table->mdl_request.init(MDL_key::TABLE, table->db, table->table_name,
40144019
table->lock_type >= TL_WRITE_ALLOW_WRITE ?
40154020
MDL_SHARED_WRITE : MDL_SHARED_READ);
@@ -4040,7 +4045,8 @@ sp_head::add_used_tables_to_table_list(THD *thd,
40404045
TABLE_LIST *
40414046
sp_add_to_query_tables(THD *thd, LEX *lex,
40424047
const char *db, const char *name,
4043-
thr_lock_type locktype)
4048+
thr_lock_type locktype,
4049+
enum_mdl_type mdl_type)
40444050
{
40454051
TABLE_LIST *table;
40464052

@@ -4055,8 +4061,7 @@ sp_add_to_query_tables(THD *thd, LEX *lex,
40554061
table->select_lex= lex->current_select;
40564062
table->cacheable_table= 1;
40574063
table->mdl_request.init(MDL_key::TABLE, table->db, table->table_name,
4058-
table->lock_type >= TL_WRITE_ALLOW_WRITE ?
4059-
MDL_SHARED_WRITE : MDL_SHARED_READ);
4064+
mdl_type);
40604065

40614066
lex->add_to_query_tables(table);
40624067
return table;

sql/sp_head.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1346,7 +1346,9 @@ set_routine_security_ctx(THD *thd, sp_head *sp, bool is_proc,
13461346
TABLE_LIST *
13471347
sp_add_to_query_tables(THD *thd, LEX *lex,
13481348
const char *db, const char *name,
1349-
thr_lock_type locktype);
1349+
thr_lock_type locktype,
1350+
enum_mdl_type mdl_type);
1351+
13501352
Item *
13511353
sp_prepare_func_item(THD* thd, Item **it_addr);
13521354

0 commit comments

Comments
 (0)