Commit 465bdabb authored by Marko Mäkelä's avatar Marko Mäkelä

Cleanup: Reduce some lock_sys.mutex contention

lock_table(): Remove the constant parameter flags=0.

lock_table_resurrect(): Merge lock_table_ix_resurrect() and
lock_table_x_resurrect().

lock_rec_lock(): Only acquire LockMutexGuard if lock_table_has()
does not hold.
parent de407e7c
...@@ -384,25 +384,17 @@ be granted immediately, the query thread is put to wait. ...@@ -384,25 +384,17 @@ be granted immediately, the query thread is put to wait.
dberr_t dberr_t
lock_table( lock_table(
/*=======*/ /*=======*/
unsigned flags, /*!< in: if BTR_NO_LOCKING_FLAG bit is set,
does nothing */
dict_table_t* table, /*!< in/out: database table dict_table_t* table, /*!< in/out: database table
in dictionary cache */ in dictionary cache */
lock_mode mode, /*!< in: lock mode */ lock_mode mode, /*!< in: lock mode */
que_thr_t* thr) /*!< in: query thread */ que_thr_t* thr) /*!< in: query thread */
MY_ATTRIBUTE((warn_unused_result)); MY_ATTRIBUTE((warn_unused_result));
/*********************************************************************//**
Creates a table IX lock object for a resurrected transaction. */
void
lock_table_ix_resurrect(
/*====================*/
dict_table_t* table, /*!< in/out: table */
trx_t* trx); /*!< in/out: transaction */
/** Create a table X lock object for a resurrected TRX_UNDO_EMPTY transaction. /** Create a table lock object for a resurrected transaction.
@param table table to be X-locked @param table table to be X-locked
@param trx transaction */ @param trx transaction
void lock_table_x_resurrect(dict_table_t *table, trx_t *trx); @param mode LOCK_X or LOCK_IX */
void lock_table_resurrect(dict_table_t *table, trx_t *trx, lock_mode mode);
/** Release a table X lock after rolling back an insert into an empty table /** Release a table X lock after rolling back an insert into an empty table
(which was covered by a TRX_UNDO_EMPTY record). (which was covered by a TRX_UNDO_EMPTY record).
......
...@@ -1542,7 +1542,6 @@ lock_rec_lock( ...@@ -1542,7 +1542,6 @@ lock_rec_lock(
que_thr_t* thr) /*!< in: query thread */ que_thr_t* thr) /*!< in: query thread */
{ {
trx_t *trx= thr_get_trx(thr); trx_t *trx= thr_get_trx(thr);
dberr_t err= DB_SUCCESS;
ut_ad(!srv_read_only_mode); ut_ad(!srv_read_only_mode);
ut_ad(((LOCK_MODE_MASK | LOCK_TABLE) & mode) == LOCK_S || ut_ad(((LOCK_MODE_MASK | LOCK_TABLE) & mode) == LOCK_S ||
...@@ -1551,16 +1550,22 @@ lock_rec_lock( ...@@ -1551,16 +1550,22 @@ lock_rec_lock(
ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index)); ut_ad(dict_index_is_clust(index) || !dict_index_is_online_ddl(index));
DBUG_EXECUTE_IF("innodb_report_deadlock", return DB_DEADLOCK;); DBUG_EXECUTE_IF("innodb_report_deadlock", return DB_DEADLOCK;);
lock_sys.mutex_lock();
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S || ut_ad((LOCK_MODE_MASK & mode) != LOCK_S ||
lock_table_has(trx, index->table, LOCK_IS)); lock_table_has(trx, index->table, LOCK_IS));
ut_ad((LOCK_MODE_MASK & mode) != LOCK_X || ut_ad((LOCK_MODE_MASK & mode) != LOCK_X ||
lock_table_has(trx, index->table, LOCK_IX)); lock_table_has(trx, index->table, LOCK_IX));
if (lock_table_has(trx, index->table, if (lock_table_has(trx, index->table,
static_cast<lock_mode>(LOCK_MODE_MASK & mode))); static_cast<lock_mode>(LOCK_MODE_MASK & mode)))
else if (lock_t *lock= lock_sys.get_first(block->page.id())) return DB_SUCCESS;
MONITOR_ATOMIC_INC(MONITOR_NUM_RECLOCK_REQ);
const page_id_t id{block->page.id()};
LockMutexGuard g;
if (lock_t *lock= lock_sys.get_first(id))
{ {
dberr_t err= DB_SUCCESS;
trx->mutex.wr_lock(); trx->mutex.wr_lock();
if (lock_rec_get_next_on_page(lock) || if (lock_rec_get_next_on_page(lock) ||
lock->trx != trx || lock->trx != trx ||
...@@ -1608,6 +1613,7 @@ lock_rec_lock( ...@@ -1608,6 +1613,7 @@ lock_rec_lock(
} }
} }
trx->mutex.wr_unlock(); trx->mutex.wr_unlock();
return err;
} }
else else
{ {
...@@ -1622,11 +1628,8 @@ lock_rec_lock( ...@@ -1622,11 +1628,8 @@ lock_rec_lock(
#endif #endif
mode, block, heap_no, index, trx, false); mode, block, heap_no, index, trx, false);
err= DB_SUCCESS_LOCKED_REC; return DB_SUCCESS_LOCKED_REC;
} }
lock_sys.mutex_unlock();
MONITOR_ATOMIC_INC(MONITOR_NUM_RECLOCK_REQ);
return err;
} }
/*********************************************************************//** /*********************************************************************//**
...@@ -2137,7 +2140,7 @@ lock_rec_inherit_to_gap_if_gap_lock( ...@@ -2137,7 +2140,7 @@ lock_rec_inherit_to_gap_if_gap_lock(
&& (heap_no == PAGE_HEAP_NO_SUPREMUM && (heap_no == PAGE_HEAP_NO_SUPREMUM
|| !lock->is_record_not_gap()) || !lock->is_record_not_gap())
&& !lock_table_has(lock->trx, lock->index->table, && !lock_table_has(lock->trx, lock->index->table,
LOCK_X)) { LOCK_X)) {
lock_rec_add_to_queue(LOCK_GAP | lock->mode(), block, lock_rec_add_to_queue(LOCK_GAP | lock->mode(), block,
heir_heap_no, heir_heap_no,
lock->index, lock->trx, false); lock->index, lock->trx, false);
...@@ -3481,8 +3484,6 @@ be granted immediately, the query thread is put to wait. ...@@ -3481,8 +3484,6 @@ be granted immediately, the query thread is put to wait.
dberr_t dberr_t
lock_table( lock_table(
/*=======*/ /*=======*/
unsigned flags, /*!< in: if BTR_NO_LOCKING_FLAG bit is set,
does nothing */
dict_table_t* table, /*!< in/out: database table dict_table_t* table, /*!< in/out: database table
in dictionary cache */ in dictionary cache */
lock_mode mode, /*!< in: lock mode */ lock_mode mode, /*!< in: lock mode */
...@@ -3492,28 +3493,18 @@ lock_table( ...@@ -3492,28 +3493,18 @@ lock_table(
dberr_t err; dberr_t err;
lock_t* wait_for; lock_t* wait_for;
ut_ad(table && thr); if (table->is_temporary()) {
return DB_SUCCESS;
/* Given limited visibility of temp-table we can avoid
locking overhead */
if ((flags & BTR_NO_LOCKING_FLAG)
|| srv_read_only_mode
|| table->is_temporary()) {
return(DB_SUCCESS);
} }
ut_a(flags == 0);
trx = thr_get_trx(thr); trx = thr_get_trx(thr);
/* Look for equal or stronger locks the same trx already /* Look for equal or stronger locks the same trx already
has on the table. No need to acquire the lock mutex here has on the table. No need to acquire LockMutexGuard here
because only this transacton can add/access table locks because only this transacton can add/access table locks
to/from trx_t::table_locks. */ to/from trx_t::table_locks. */
if (lock_table_has(trx, table, mode)) { if (lock_table_has(trx, table, mode) || srv_read_only_mode) {
return(DB_SUCCESS); return(DB_SUCCESS);
} }
...@@ -3558,55 +3549,26 @@ lock_table( ...@@ -3558,55 +3549,26 @@ lock_table(
return(err); return(err);
} }
/*********************************************************************//** /** Create a table lock object for a resurrected transaction.
Creates a table IX lock object for a resurrected transaction. */
void
lock_table_ix_resurrect(
/*====================*/
dict_table_t* table, /*!< in/out: table */
trx_t* trx) /*!< in/out: transaction */
{
ut_ad(trx->is_recovered);
if (lock_table_has(trx, table, LOCK_IX)) {
return;
}
auto mutex= &trx->mutex;
lock_sys.mutex_lock();
/* We have to check if the new lock is compatible with any locks
other transactions have in the table lock queue. */
ut_ad(!lock_table_other_has_incompatible(
trx, LOCK_WAIT, table, LOCK_IX));
mutex->wr_lock();
lock_table_create(table, LOCK_IX, trx);
lock_sys.mutex_unlock();
mutex->wr_unlock();
}
/** Create a table X lock object for a resurrected TRX_UNDO_EMPTY transaction.
@param table table to be X-locked @param table table to be X-locked
@param trx transaction */ @param trx transaction
void lock_table_x_resurrect(dict_table_t *table, trx_t *trx) @param mode LOCK_X or LOCK_IX */
void lock_table_resurrect(dict_table_t *table, trx_t *trx, lock_mode mode)
{ {
ut_ad(trx->is_recovered); ut_ad(trx->is_recovered);
if (lock_table_has(trx, table, LOCK_X)) ut_ad(mode == LOCK_X || mode == LOCK_IX);
if (lock_table_has(trx, table, mode))
return; return;
auto mutex= &trx->mutex; {
lock_sys.mutex_lock(); LockMutexGuard g;
/* We have to check if the new lock is compatible with any locks ut_ad(!lock_table_other_has_incompatible(trx, LOCK_WAIT, table, mode));
other transactions have in the table lock queue. */
ut_ad(!lock_table_other_has_incompatible(trx, LOCK_WAIT, table, LOCK_X));
mutex->wr_lock(); trx->mutex.wr_lock();
lock_table_create(table, LOCK_X, trx); lock_table_create(table, mode, trx);
lock_sys.mutex_unlock(); }
mutex->wr_unlock(); trx->mutex.wr_unlock();
} }
/*********************************************************************//** /*********************************************************************//**
...@@ -3751,7 +3713,7 @@ lock_table_for_trx( ...@@ -3751,7 +3713,7 @@ lock_table_for_trx(
thr->run_node = thr; thr->run_node = thr;
thr->prev_node = thr->common.parent; thr->prev_node = thr->common.parent;
err = lock_table(0, table, mode, thr); err = lock_table(table, mode, thr);
trx->error_state = err; trx->error_state = err;
...@@ -4870,7 +4832,6 @@ lock_rec_insert_check_and_lock( ...@@ -4870,7 +4832,6 @@ lock_rec_insert_check_and_lock(
lock_t* c_lock = lock_t* c_lock =
#endif /* WITH_WSREP */ #endif /* WITH_WSREP */
lock_rec_other_has_conflicting(type_mode, block, heap_no, trx)) { lock_rec_other_has_conflicting(type_mode, block, heap_no, trx)) {
/* Note that we may get DB_SUCCESS also here! */
trx->mutex.wr_lock(); trx->mutex.wr_lock();
err = lock_rec_enqueue_waiting( err = lock_rec_enqueue_waiting(
......
...@@ -1166,7 +1166,7 @@ row_ins_foreign_check_on_constraint( ...@@ -1166,7 +1166,7 @@ row_ins_foreign_check_on_constraint(
/* Set an X-lock on the row to delete or update in the child table */ /* Set an X-lock on the row to delete or update in the child table */
err = lock_table(0, table, LOCK_IX, thr); err = lock_table(table, LOCK_IX, thr);
if (err == DB_SUCCESS) { if (err == DB_SUCCESS) {
/* Here it suffices to use a LOCK_REC_NOT_GAP type lock; /* Here it suffices to use a LOCK_REC_NOT_GAP type lock;
...@@ -1609,7 +1609,7 @@ row_ins_check_foreign_constraint( ...@@ -1609,7 +1609,7 @@ row_ins_check_foreign_constraint(
/* We already have a LOCK_IX on table, but not necessarily /* We already have a LOCK_IX on table, but not necessarily
on check_table */ on check_table */
err = lock_table(0, check_table, LOCK_IS, thr); err = lock_table(check_table, LOCK_IS, thr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
...@@ -2667,7 +2667,7 @@ row_ins_clust_index_entry_low( ...@@ -2667,7 +2667,7 @@ row_ins_clust_index_entry_low(
DEBUG_SYNC_C("empty_root_page_insert"); DEBUG_SYNC_C("empty_root_page_insert");
if (!index->table->is_temporary()) { if (!index->table->is_temporary()) {
err = lock_table(0, index->table, LOCK_X, thr); err = lock_table(index->table, LOCK_X, thr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
trx->error_state = err; trx->error_state = err;
...@@ -3797,7 +3797,7 @@ row_ins_step( ...@@ -3797,7 +3797,7 @@ row_ins_step(
goto same_trx; goto same_trx;
} }
err = lock_table(0, node->table, LOCK_IX, thr); err = lock_table(node->table, LOCK_IX, thr);
DBUG_EXECUTE_IF("ib_row_ins_ix_lock_wait", DBUG_EXECUTE_IF("ib_row_ins_ix_lock_wait",
err = DB_LOCK_WAIT;); err = DB_LOCK_WAIT;);
......
...@@ -1195,7 +1195,7 @@ row_lock_table_autoinc_for_mysql( ...@@ -1195,7 +1195,7 @@ row_lock_table_autoinc_for_mysql(
trx_start_if_not_started_xa(trx, true); trx_start_if_not_started_xa(trx, true);
err = lock_table(0, prebuilt->table, LOCK_AUTO_INC, thr); err = lock_table(prebuilt->table, LOCK_AUTO_INC, thr);
trx->error_state = err; trx->error_state = err;
} while (err != DB_SUCCESS } while (err != DB_SUCCESS
...@@ -1237,7 +1237,7 @@ row_lock_table(row_prebuilt_t* prebuilt) ...@@ -1237,7 +1237,7 @@ row_lock_table(row_prebuilt_t* prebuilt)
trx_start_if_not_started_xa(trx, false); trx_start_if_not_started_xa(trx, false);
err = lock_table(0, prebuilt->table, static_cast<lock_mode>( err = lock_table(prebuilt->table, static_cast<lock_mode>(
prebuilt->select_lock_type), thr); prebuilt->select_lock_type), thr);
trx->error_state = err; trx->error_state = err;
} while (err != DB_SUCCESS } while (err != DB_SUCCESS
...@@ -3147,7 +3147,7 @@ row_mysql_lock_table( ...@@ -3147,7 +3147,7 @@ row_mysql_lock_table(
thr->run_node = thr; thr->run_node = thr;
thr->prev_node = thr->common.parent; thr->prev_node = thr->common.parent;
err = lock_table(0, table, mode, thr); err = lock_table(table, mode, thr);
trx->error_state = err; trx->error_state = err;
} while (err != DB_SUCCESS } while (err != DB_SUCCESS
......
...@@ -2278,8 +2278,7 @@ row_sel_step( ...@@ -2278,8 +2278,7 @@ row_sel_step(
que_node_get_next(table_node))) { que_node_get_next(table_node))) {
dberr_t err = lock_table( dberr_t err = lock_table(
0, table_node->table, i_lock_mode, table_node->table, i_lock_mode, thr);
thr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
trx_t* trx; trx_t* trx;
...@@ -4610,7 +4609,7 @@ row_search_mvcc( ...@@ -4610,7 +4609,7 @@ row_search_mvcc(
trx->read_view.open(trx); trx->read_view.open(trx);
} else { } else {
wait_table_again: wait_table_again:
err = lock_table(0, prebuilt->table, err = lock_table(prebuilt->table,
prebuilt->select_lock_type == LOCK_S prebuilt->select_lock_type == LOCK_S
? LOCK_IS : LOCK_IX, thr); ? LOCK_IS : LOCK_IX, thr);
......
/***************************************************************************** /*****************************************************************************
Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved. Copyright (c) 1996, 2017, Oracle and/or its affiliates. All Rights Reserved.
Copyright (c) 2015, 2020, MariaDB Corporation. Copyright (c) 2015, 2021, MariaDB Corporation.
This program is free software; you can redistribute it and/or modify it under This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software the terms of the GNU General Public License as published by the Free Software
...@@ -3084,7 +3084,7 @@ row_upd_step( ...@@ -3084,7 +3084,7 @@ row_upd_step(
/* It may be that the current session has not yet /* It may be that the current session has not yet
started its transaction, or it has been committed: */ started its transaction, or it has been committed: */
err = lock_table(0, node->table, LOCK_IX, thr); err = lock_table(node->table, LOCK_IX, thr);
if (err != DB_SUCCESS) { if (err != DB_SUCCESS) {
......
...@@ -618,15 +618,12 @@ trx_resurrect_table_locks( ...@@ -618,15 +618,12 @@ trx_resurrect_table_locks(
trx->mod_tables.emplace(table, 0); trx->mod_tables.emplace(table, 0);
} }
if (p.second) { lock_table_resurrect(table, trx,
lock_table_x_resurrect(table, trx); p.second ? LOCK_X : LOCK_IX);
} else {
lock_table_ix_resurrect(table, trx);
}
DBUG_LOG("ib_trx", DBUG_LOG("ib_trx",
"resurrect " << ib::hex(trx->id) "resurrect " << ib::hex(trx->id)
<< " IX lock on " << table->name); << " lock on " << table->name);
dict_table_close(table, FALSE, FALSE); dict_table_close(table, FALSE, FALSE);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment