#At file:///home/dlenev/src/bzr/mysql-next-4284-nl-review/ based on revid:kostja@stripped
3075 Dmitry Lenev 2010-01-28
Tentative patch implementing new type-of-operation-aware metadata locks.
Fixes bug #46272 "MySQL 5.4.4, new MDL: unnecessary deadlock" and bug
#37346 "innodb does not detect deadlock between update and alter table".
After-review fixes in progress.
modified:
sql/sql_base.cc
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2010-01-28 12:08:24 +0000
+++ b/sql/sql_base.cc 2010-01-28 17:45:43 +0000
@@ -4343,6 +4343,70 @@ end:
/**
+ Acquire upgradable (SNW, SNRW) metadata locks on tables to be opened
+ for LOCK TABLES or a DDL statement.
+
+ @param thd Thread context.
+ @param tables_start Start of list of tables on which upgradable locks
+ should be acquired.
+ @param tables_end End of list of tables.
+ @param ot_ctx Context of open_tables() operation.
+
+ @retval FALSE Success.
+ @retval TRUE Failure (e.g. connection was killed)
+*/
+
+static bool
+open_tables_acquire_upgradable_mdl(THD *thd, TABLE_LIST *tables_start,
+ TABLE_LIST *tables_end,
+ Open_table_context *ot_ctx)
+{
+ MDL_request_list mdl_requests;
+ TABLE_LIST *table;
+
+ for (table= tables_start; table && table != tables_end;
+ table= table->next_global)
+ {
+ if (table->lock_type >= TL_WRITE_ALLOW_WRITE)
+ {
+ table->mdl_request.set_type(table->lock_type > TL_WRITE_ALLOW_READ ?
+ MDL_SHARED_NO_READ_WRITE :
+ MDL_SHARED_NO_WRITE);
+ mdl_requests.push_front(&table->mdl_request);
+ }
+ }
+
+ if (! mdl_requests.is_empty())
+ {
+ MDL_request *global_request;
+
+ if (!(global_request= ot_ctx->get_global_mdl_request(thd)))
+ return TRUE;
+ if (! global_request->ticket)
+ {
+ if (thd->mdl_context.acquire_global_intention_exclusive_lock(global_request))
+ return TRUE;
+ }
+ }
+
+ if (thd->mdl_context.acquire_exclusive_locks(&mdl_requests))
+ return TRUE;
+
+ for (table= tables_start; table && table != tables_end;
+ table= table->next_global)
+ {
+ if (table->lock_type >= TL_WRITE_ALLOW_WRITE)
+ {
+ table->mdl_request.ticket= NULL;
+ table->mdl_request.set_type(MDL_SHARED_WRITE);
+ }
+ }
+
+ return FALSE;
+}
+
+
+/**
Open all tables in list
@param[in] thd Thread context.
@@ -4426,52 +4490,16 @@ restart:
we will be opening corresponding table pre-acquired metadata
lock will be reused (thanks to the fact that in recursive case
metadata locks are acquired without waiting).
-
- QQ: Is there a better place or a way to do this?
- I am reluctant to put code into Prelocking_strategy as this
- has nothing to do with extending of prelocking set and is
- rather about the order in which we acquire MDL locks...
*/
if ((flags & MYSQL_OPEN_TAKE_UPGRADABLE_MDL) &&
! thd->locked_tables_mode)
{
- MDL_request_list mdl_requests;
-
- for (tables= *start; tables && tables != thd->lex->first_not_own_table();
- tables= tables->next_global)
+ if (open_tables_acquire_upgradable_mdl(thd, *start,
+ thd->lex->first_not_own_table(),
+ &ot_ctx))
{
- if (tables->lock_type >= TL_WRITE_ALLOW_WRITE)
- {
- tables->mdl_request.set_type(tables->lock_type > TL_WRITE_ALLOW_READ ?
- MDL_SHARED_NO_READ_WRITE :
- MDL_SHARED_NO_WRITE);
- mdl_requests.push_front(&tables->mdl_request);
- }
- }
-
- if (! mdl_requests.is_empty())
- {
- MDL_request *global_request;
-
- if (!(global_request= ot_ctx.get_global_mdl_request(thd)))
- return 1;
- if (! global_request->ticket)
- {
- if (thd->mdl_context.acquire_global_intention_exclusive_lock(global_request))
- return 1;
- }
- }
-
- thd->mdl_context.acquire_exclusive_locks(&mdl_requests);
-
- for (tables= *start; tables && tables != thd->lex->first_not_own_table();
- tables= tables->next_global)
- {
- if (tables->lock_type >= TL_WRITE_ALLOW_WRITE)
- {
- tables->mdl_request.ticket= NULL;
- tables->mdl_request.set_type(MDL_SHARED_WRITE);
- }
+ error= TRUE;
+ goto err;
}
}
Attachment: [text/bzr-bundle] bzr/dlenev@mysql.com-20100128174543-xlnj29ub4iua0sjz.bundle
| Thread |
|---|
| • bzr commit into mysql-5.6-next-mr branch (dlenev:3075) Bug#46272 | Dmitry Lenev | 28 Jan |