#At file:///export/home/x/mysql-5.5-runtime-bug54332/ based on revid:jon.hauglid@stripped
3119 Jon Olav Hauglid 2010-08-24
Follow-up to Bug #54332 Deadlock with two connections doing
LOCK TABLE+INSERT DELAYED
The problem was that the server could crash if the insert delayed
handler thread was killed due to a conflicting shared metadata
lock. This could happen because the metadata lock ticket was
added to the handler thread before it was properly initialized.
This patch moves the cloning of the acquired metadata lock ticket
until after the handler thread has been properly initialized.
=== modified file 'sql/sql_insert.cc'
--- a/sql/sql_insert.cc 2010-08-23 15:42:53 +0000
+++ b/sql/sql_insert.cc 2010-08-24 11:46:08 +0000
@@ -563,15 +563,6 @@ bool open_and_lock_for_insert_delayed(TH
- If a lock was acquired above, we should release it after delayed_get_table()
- has cloned the ticket for the handler thread. Note that acquire_lock() can
- succeed because of a lock already held by the connection. In this case we
- should not release it here.
- MDL_ticket *table_ticket = mdl_savepoint == thd->mdl_context.mdl_savepoint() ?
- NULL: thd->mdl_context.mdl_savepoint();
bool error= FALSE;
if (delayed_get_table(thd, table_list))
@@ -597,12 +588,18 @@ bool open_and_lock_for_insert_delayed(TH
- if (table_ticket)
- Clone_ticket() in delayed_get_table() causes TABLE_LIST::MDL_REQUEST::ticket
- to be overwritten with the cloned ticket. Reset the ticket here in case
- we end up having to use normal insert.
+ If a lock was acquired above, we should release it after
+ handle_delayed_insert() has cloned the ticket. Note that acquire_lock() can
+ succeed because the connection already has the lock. In this case the ticket
+ will be before the mdl_savepoint and we should not release it here.
+ if (!thd->mdl_context.has_lock(mdl_savepoint, table_list->mdl_request.ticket))
+ Reset the ticket in case we end up having to use normal insert and
+ therefore will reopen the table and reaquire the metadata lock.
@@ -2063,19 +2060,8 @@ bool delayed_get_table(THD *thd, TABLE_L
/* Replace volatile strings with local copies */
di->table_list.alias= di->table_list.table_name= di->thd.query();
- Clone the ticket representing the lock on the target table for
- the insert and add it to the list of granted metadata locks held by
- the handler thread. This is safe since the handler thread is
- not holding nor waiting on any metadata locks.
- if (di->thd.mdl_context.clone_ticket(&table_list->mdl_request))
- delete di;
- my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
- goto end_create;
+ /* We need the ticket so that it can be cloned in handle_delayed_insert */
+ di->table_list.mdl_request.ticket= table_list->mdl_request.ticket;
@@ -2546,6 +2532,15 @@ pthread_handler_t handle_delayed_insert(
+ Clone the ticket representing the lock on the target table for
+ the insert and add it to the list of granted metadata locks held by
+ the handler thread. This is safe since the handler thread is
+ not holding nor waiting on any metadata locks.
+ if (thd->mdl_context.clone_ticket(&di->table_list.mdl_request))
+ goto err;
Attachment: [text/bzr-bundle] firstname.lastname@example.org
|• bzr commit into mysql-5.5-runtime branch (jon.hauglid:3119) Bug#54332||Jon Olav Hauglid||24 Aug|