summaryrefslogtreecommitdiff
path: root/sql/lock.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/lock.cc')
-rw-r--r--sql/lock.cc141
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);