diff options
Diffstat (limited to 'sql/lock.cc')
-rw-r--r-- | sql/lock.cc | 141 |
1 files changed, 58 insertions, 83 deletions
diff --git a/sql/lock.cc b/sql/lock.cc index 7153b85d740..47db9ec6bfa 100644 --- a/sql/lock.cc +++ b/sql/lock.cc @@ -68,10 +68,6 @@ table_handler->external_lock(thd, F_UNLCK) for each table that was locked, excluding one that caused failure. That means handler must cleanup itself in case external_lock() fails. - - @todo - Change to use my_malloc() ONLY when using LOCK TABLES command or when - we are forced to use mysql_lock_merge. */ #include <my_global.h> @@ -82,10 +78,7 @@ #include "sql_parse.h" // is_log_table_write_query #include "sql_acl.h" // SUPER_ACL #include <hash.h> - -#ifdef WITH_WSREP #include "wsrep_mysqld.h" -#endif /* WITH_WSREP */ /** @defgroup Locking Locking @@ -96,7 +89,6 @@ extern HASH open_cache; static int lock_external(THD *thd, TABLE **table,uint count); static int unlock_external(THD *thd, TABLE **table,uint count); -static void print_lock_error(int error, TABLE *); /* Map the return value of thr_lock to an error from errmsg.txt */ static int thr_lock_errno_to_mysql[]= @@ -268,19 +260,24 @@ void reset_lock_data(MYSQL_LOCK *sql_lock, bool unlock) MYSQL_LOCK *mysql_lock_tables(THD *thd, TABLE **tables, uint count, uint flags) { MYSQL_LOCK *sql_lock; + uint gld_flags= GET_LOCK_STORE_LOCKS; DBUG_ENTER("mysql_lock_tables(tables)"); if (lock_tables_check(thd, tables, count, flags)) DBUG_RETURN(NULL); - if (! (sql_lock= get_lock_data(thd, tables, count, GET_LOCK_STORE_LOCKS))) + if (!(thd->variables.option_bits & OPTION_TABLE_LOCK)) + gld_flags|= GET_LOCK_ON_THD; + + if (! (sql_lock= get_lock_data(thd, tables, count, gld_flags))) DBUG_RETURN(NULL); if (mysql_lock_tables(thd, sql_lock, flags)) { /* Clear the lock type of all lock data to avoid reusage. */ reset_lock_data(sql_lock, 1); - my_free(sql_lock); + if (!(gld_flags & GET_LOCK_ON_THD)) + my_free(sql_lock); sql_lock= 0; } DBUG_RETURN(sql_lock); @@ -307,8 +304,8 @@ bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags) PSI_stage_info org_stage; DBUG_ENTER("mysql_lock_tables(sql_lock)"); - thd->enter_stage(&stage_system_lock, &org_stage, __func__, __FILE__, - __LINE__); + thd->backup_stage(&org_stage); + THD_STAGE_INFO(thd, stage_system_lock); if (sql_lock->table_count && lock_external(thd, sql_lock->table, sql_lock->table_count)) goto end; @@ -318,9 +315,6 @@ bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags) /* Copy the lock data array. thr_multi_lock() reorders its contents. */ memmove(sql_lock->locks + sql_lock->lock_count, sql_lock->locks, sql_lock->lock_count * sizeof(*sql_lock->locks)); -#ifdef WITH_WSREP - thd->lock_info.in_lock_tables= thd->in_lock_tables; -#endif /* Lock on the copied half of the lock data array. */ rc= thr_lock_errno_to_mysql[(int) thr_multi_lock(sql_lock->locks + @@ -332,26 +326,21 @@ bool mysql_lock_tables(THD *thd, MYSQL_LOCK *sql_lock, uint flags) end: THD_STAGE_INFO(thd, org_stage); -#ifdef WITH_WSREP - thd_proc_info(thd, "mysql_lock_tables(): unlocking tables II"); -#else /* WITH_WSREP */ - thd_proc_info(thd, 0); -#endif /* WITH_WSREP */ if (thd->killed) { thd->send_kill_message(); if (!rc) + { mysql_unlock_tables(thd, sql_lock, 0); + THD_STAGE_INFO(thd, stage_after_table_lock); + } rc= 1; } else if (rc > 1) my_error(rc, MYF(0)); thd->set_time_after_lock(); -#ifdef WITH_WSREP - thd_proc_info(thd, "exit mysqld_lock_tables()"); -#endif /* WITH_WSREP */ DBUG_RETURN(rc); } @@ -374,7 +363,7 @@ static int lock_external(THD *thd, TABLE **tables, uint count) if ((error=(*tables)->file->ha_external_lock(thd,lock_type))) { - print_lock_error(error, *tables); + (*tables)->file->print_error(error, MYF(0)); while (--i) { tables--; @@ -393,9 +382,18 @@ static int lock_external(THD *thd, TABLE **tables, uint count) } +void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock) +{ + mysql_unlock_tables(thd, sql_lock, + thd->variables.option_bits & OPTION_TABLE_LOCK); +} + + void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock) { DBUG_ENTER("mysql_unlock_tables"); + THD_STAGE_INFO(thd, stage_unlocking_tables); + if (sql_lock->table_count) unlock_external(thd, sql_lock->table, sql_lock->table_count); if (sql_lock->lock_count) @@ -413,9 +411,10 @@ void mysql_unlock_tables(THD *thd, MYSQL_LOCK *sql_lock, bool free_lock) void mysql_unlock_some_tables(THD *thd, TABLE **table,uint count) { - MYSQL_LOCK *sql_lock; - if ((sql_lock= get_lock_data(thd, table, count, GET_LOCK_UNLOCK))) - mysql_unlock_tables(thd, sql_lock, 1); + MYSQL_LOCK *sql_lock= + get_lock_data(thd, table, count, GET_LOCK_UNLOCK | GET_LOCK_ON_THD); + if (sql_lock) + mysql_unlock_tables(thd, sql_lock, 0); } @@ -562,11 +561,10 @@ void mysql_lock_abort(THD *thd, TABLE *table, bool upgrade_lock) MYSQL_LOCK *locked; DBUG_ENTER("mysql_lock_abort"); - if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK))) + if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK | GET_LOCK_ON_THD))) { for (uint i=0; i < locked->lock_count; i++) thr_abort_locks(locked->locks[i]->lock, upgrade_lock); - my_free(locked); } DBUG_VOID_RETURN; } @@ -590,7 +588,7 @@ bool mysql_lock_abort_for_thread(THD *thd, TABLE *table) bool result= FALSE; DBUG_ENTER("mysql_lock_abort_for_thread"); - if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK))) + if ((locked= get_lock_data(thd, &table, 1, GET_LOCK_UNLOCK | GET_LOCK_ON_THD))) { for (uint i=0; i < locked->lock_count; i++) { @@ -598,7 +596,6 @@ bool mysql_lock_abort_for_thread(THD *thd, TABLE *table) table->in_use->thread_id)) result= TRUE; } - my_free(locked); } DBUG_RETURN(result); } @@ -688,8 +685,8 @@ static int unlock_external(THD *thd, TABLE **table,uint count) (*table)->current_lock = F_UNLCK; if ((error=(*table)->file->ha_external_lock(thd, F_UNLCK))) { - error_code=error; - print_lock_error(error_code, *table); + error_code= error; + (*table)->file->print_error(error, MYF(0)); } } table++; @@ -716,7 +713,6 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags) TABLE **to, **table_buf; DBUG_ENTER("get_lock_data"); - DBUG_ASSERT((flags == GET_LOCK_UNLOCK) || (flags == GET_LOCK_STORE_LOCKS)); DBUG_PRINT("info", ("count %d", count)); for (i=lock_count=table_count=0 ; i < count ; i++) @@ -737,11 +733,12 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags) update the table values. So the second part of the array is copied from the first part immediately before calling thr_multi_lock(). */ - if (!(sql_lock= (MYSQL_LOCK*) - my_malloc(sizeof(*sql_lock) + - sizeof(THR_LOCK_DATA*) * lock_count * 2 + - sizeof(table_ptr) * table_count, - MYF(0)))) + size_t amount= sizeof(*sql_lock) + + sizeof(THR_LOCK_DATA*) * lock_count * 2 + + sizeof(table_ptr) * table_count; + if (!(sql_lock= (MYSQL_LOCK*) (flags & GET_LOCK_ON_THD ? + thd->alloc(amount) : + my_malloc(amount, MYF(0))))) DBUG_RETURN(0); locks= locks_buf= sql_lock->locks= (THR_LOCK_DATA**) (sql_lock + 1); to= table_buf= sql_lock->table= (TABLE**) (locks + lock_count * 2); @@ -760,9 +757,9 @@ MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count, uint flags) DBUG_ASSERT(lock_type != TL_WRITE_DEFAULT && lock_type != TL_READ_DEFAULT); locks_start= locks; locks= table->file->store_lock(thd, locks, - (flags & GET_LOCK_UNLOCK) ? TL_IGNORE : - lock_type); - if (flags & GET_LOCK_STORE_LOCKS) + (flags & GET_LOCK_ACTION_MASK) == GET_LOCK_UNLOCK ? TL_IGNORE : + lock_type); + if ((flags & GET_LOCK_ACTION_MASK) == GET_LOCK_STORE_LOCKS) { table->lock_position= (uint) (to - table_buf); table->lock_data_start= (uint) (locks_start - locks_buf); @@ -827,7 +824,7 @@ bool lock_schema_name(THD *thd, const char *db) if (thd->locked_tables_mode) { my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, - ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); + ER_THD(thd, ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); return TRUE; } @@ -883,7 +880,7 @@ bool lock_object_name(THD *thd, MDL_key::enum_mdl_namespace mdl_type, if (thd->locked_tables_mode) { my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, - ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); + ER_THD(thd, ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0)); return TRUE; } @@ -911,36 +908,6 @@ bool lock_object_name(THD *thd, MDL_key::enum_mdl_namespace mdl_type, } -static void print_lock_error(int error, TABLE *table) -{ - int textno; - DBUG_ENTER("print_lock_error"); - - switch (error) { - case HA_ERR_LOCK_WAIT_TIMEOUT: - textno=ER_LOCK_WAIT_TIMEOUT; - break; - case HA_ERR_READ_ONLY_TRANSACTION: - textno=ER_READ_ONLY_TRANSACTION; - break; - case HA_ERR_LOCK_DEADLOCK: - textno=ER_LOCK_DEADLOCK; - break; - case HA_ERR_WRONG_COMMAND: - my_error(ER_ILLEGAL_HA, MYF(0), table->file->table_type(), - table->s->db.str, table->s->table_name.str); - DBUG_VOID_RETURN; - default: - textno=ER_CANT_LOCK; - break; - } - - my_error(textno, MYF(0), error); - - DBUG_VOID_RETURN; -} - - /**************************************************************************** Handling of global read locks @@ -1090,7 +1057,7 @@ void Global_read_lock::unlock_global_read_lock(THD *thd) thd->mdl_context.release_lock(m_mdl_global_shared_lock); m_mdl_global_shared_lock= NULL; m_state= GRL_NONE; - + DBUG_VOID_RETURN; } @@ -1119,6 +1086,9 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) make_global_read_lock_block_commit(), do nothing. */ + if (m_state != GRL_ACQUIRED) + DBUG_RETURN(0); + #ifdef WITH_WSREP if (WSREP(thd) && m_mdl_blocks_commits_lock) { @@ -1128,9 +1098,6 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) } #endif /* WITH_WSREP */ - if (m_state != GRL_ACQUIRED) - DBUG_RETURN(0); - mdl_request.init(MDL_key::COMMIT, "", "", MDL_SHARED, MDL_EXPLICIT); if (thd->mdl_context.acquire_lock(&mdl_request, @@ -1179,12 +1146,20 @@ bool Global_read_lock::make_global_read_lock_block_commit(THD *thd) } else if (ret != -ENOSYS) /* -ENOSYS - no provider */ { - WSREP_ERROR("Failed to pause provider: %lld (%s)", -ret, strerror(-ret)); + long long ret = wsrep->pause(wsrep); + if (ret >= 0) + { + wsrep_locked_seqno= ret; + } + else if (ret != -ENOSYS) /* -ENOSYS - no provider */ + { + WSREP_ERROR("Failed to pause provider: %lld (%s)", -ret, strerror(-ret)); - /* m_mdl_blocks_commits_lock is always NULL here */ - wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; - my_error(ER_LOCK_DEADLOCK, MYF(0)); - DBUG_RETURN(TRUE); + DBUG_ASSERT(m_mdl_blocks_commits_lock == NULL); + wsrep_locked_seqno= WSREP_SEQNO_UNDEFINED; + my_error(ER_LOCK_DEADLOCK, MYF(0)); + DBUG_RETURN(TRUE); + } } #endif /* WITH_WSREP */ DBUG_RETURN(FALSE); |