diff options
author | Jon Olav Hauglid <jon.hauglid@oracle.com> | 2010-11-18 16:01:58 +0100 |
---|---|---|
committer | Jon Olav Hauglid <jon.hauglid@oracle.com> | 2010-11-18 16:01:58 +0100 |
commit | a2275f0c8fd03d386cb418f5729468c95b0c3b92 (patch) | |
tree | 7cc348d24f298fedc96ce3eef04478cb467d360f /sql/sql_insert.cc | |
parent | f481c14e3ed3e0b16dc87071cbd56452c23faf15 (diff) | |
parent | a6d21fc09b46a84d292ce9ab66dc6641b43a7511 (diff) | |
download | mariadb-git-a2275f0c8fd03d386cb418f5729468c95b0c3b92.tar.gz |
Merge from mysql-5.5-runtime to mysql-5.5-bugteam
No conflicts
Diffstat (limited to 'sql/sql_insert.cc')
-rw-r--r-- | sql/sql_insert.cc | 85 |
1 files changed, 47 insertions, 38 deletions
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index eaaf7901e25..bd2aa70806a 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -77,7 +77,8 @@ #include "sql_audit.h" #ifndef EMBEDDED_LIBRARY -static bool delayed_get_table(THD *thd, TABLE_LIST *table_list); +static bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, + TABLE_LIST *table_list); static int write_delayed(THD *thd, TABLE *table, enum_duplicates duplic, LEX_STRING query, bool ignore, bool log_on); static void end_delayed_insert(THD *thd); @@ -529,32 +530,28 @@ void upgrade_lock_type(THD *thd, thr_lock_type *lock_type, static bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list) { + MDL_request protection_request; DBUG_ENTER("open_and_lock_for_insert_delayed"); #ifndef EMBEDDED_LIBRARY - if (thd->locked_tables_mode && thd->global_read_lock.is_acquired()) - { - /* - If this connection has the global read lock, the handler thread - will not be able to lock the table. It will wait for the global - read lock to go away, but this will never happen since the - connection thread will be stuck waiting for the handler thread - to open and lock the table. - If we are not in locked tables mode, INSERT will seek protection - against the global read lock (and fail), thus we will only get - to this point in locked tables mode. - */ - my_error(ER_CANT_UPDATE_WITH_READLOCK, MYF(0)); - DBUG_RETURN(TRUE); - } - /* In order for the deadlock detector to be able to find any deadlocks - caused by the handler thread locking this table, we take the metadata - lock inside the connection thread. If this goes ok, the ticket is cloned - and added to the list of granted locks held by the handler thread. + caused by the handler thread waiting for GRL or this table, we acquire + protection against GRL (global IX metadata lock) and metadata lock on + table to being inserted into inside the connection thread. + If this goes ok, the tickets are cloned and added to the list of granted + locks held by the handler thread. */ - MDL_ticket *mdl_savepoint= thd->mdl_context.mdl_savepoint(); + if (thd->global_read_lock.can_acquire_protection()) + DBUG_RETURN(TRUE); + + protection_request.init(MDL_key::GLOBAL, "", "", MDL_INTENTION_EXCLUSIVE, + MDL_STATEMENT); + + if (thd->mdl_context.acquire_lock(&protection_request, + thd->variables.lock_wait_timeout)) + DBUG_RETURN(TRUE); + if (thd->mdl_context.acquire_lock(&table_list->mdl_request, thd->variables.lock_wait_timeout)) /* @@ -564,7 +561,7 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list) DBUG_RETURN(TRUE); bool error= FALSE; - if (delayed_get_table(thd, table_list)) + if (delayed_get_table(thd, &protection_request, table_list)) error= TRUE; else if (table_list->table) { @@ -589,13 +586,13 @@ bool open_and_lock_for_insert_delayed(THD *thd, TABLE_LIST *table_list) } /* - 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. + We can't release protection against GRL and metadata lock on the table + being inserted into here. These locks might be required, for example, + because this INSERT DELAYED calls functions which may try to update + this or another tables (updating the same table is of course illegal, + but such an attempt can be discovered only later during statement + execution). */ - if (!thd->mdl_context.has_lock(mdl_savepoint, table_list->mdl_request.ticket)) - thd->mdl_context.release_lock(table_list->mdl_request.ticket); /* Reset the ticket in case we end up having to use normal insert and @@ -1873,10 +1870,11 @@ public: mysql_cond_t cond, cond_client; volatile uint tables_in_use,stacked_inserts; volatile bool status; - /* + /** When the handler thread starts, it clones a metadata lock ticket - for the table to be inserted. This is done to allow the deadlock - detector to detect deadlocks resulting from this lock. + which protects against GRL and ticket for the table to be inserted. + This is done to allow the deadlock detector to detect deadlocks + resulting from these locks. Before this is done, the connection thread cannot safely exit without causing problems for clone_ticket(). Once handler_thread_initialized has been set, it is safe for the @@ -1888,6 +1886,11 @@ public: I_List<delayed_row> rows; ulong group_count; TABLE_LIST table_list; // Argument + /** + Request for IX metadata lock protecting against GRL which is + passed from connection thread to the handler thread. + */ + MDL_request grl_protection; Delayed_insert() :locks_in_memory(0), table(0),tables_in_use(0),stacked_inserts(0), @@ -2066,7 +2069,8 @@ Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list) */ static -bool delayed_get_table(THD *thd, TABLE_LIST *table_list) +bool delayed_get_table(THD *thd, MDL_request *grl_protection_request, + TABLE_LIST *table_list) { int error; Delayed_insert *di; @@ -2111,7 +2115,10 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) /* Replace volatile strings with local copies */ di->table_list.alias= di->table_list.table_name= di->thd.query(); di->table_list.db= di->thd.db; - /* We need the ticket so that it can be cloned in handle_delayed_insert */ + /* We need the tickets so that they can be cloned in handle_delayed_insert */ + di->grl_protection.init(MDL_key::GLOBAL, "", "", + MDL_INTENTION_EXCLUSIVE, MDL_STATEMENT); + di->grl_protection.ticket= grl_protection_request->ticket; init_mdl_requests(&di->table_list); di->table_list.mdl_request.ticket= table_list->mdl_request.ticket; @@ -2651,13 +2658,15 @@ pthread_handler_t handle_delayed_insert(void *arg) thd->set_current_stmt_binlog_format_row_if_mixed(); /* - 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. + Clone tickets representing protection against GRL and the lock on + the target table for the insert and add them 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)) + if (thd->mdl_context.clone_ticket(&di->grl_protection) || + thd->mdl_context.clone_ticket(&di->table_list.mdl_request)) { + thd->mdl_context.release_transactional_locks(); di->handler_thread_initialized= TRUE; goto err; } |