Skip to content

Commit 02270b4

Browse files
committed
MDEV-14756 - Remove trx_sys_t::rw_trx_list
Let lock_validate_table_locks(), lock_rec_other_trx_holds_expl(), lock_table_locks_lookup(), trx_recover_for_mysql(), trx_get_trx_by_xid(), trx_roll_must_shutdown(), fetch_data_into_cache() iterate rw_trx_hash instead of rw_trx_list.
1 parent d8c0caa commit 02270b4

File tree

6 files changed

+347
-371
lines changed

6 files changed

+347
-371
lines changed

storage/innobase/include/trx0sys.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,20 @@ class rw_trx_hash_t
757757
@param argument opque argument passed to action
758758
759759
May return the same element multiple times if hash is under contention.
760-
Elements can be added or removed while this method is being executed.
760+
If caller doesn't like to see the same transaction multiple times, it has
761+
to call iterate_no_dups() instead.
762+
763+
May return element with committed transaction. If caller doesn't like to
764+
see committed transactions, it has to skip those under element mutex:
765+
766+
mutex_enter(&element->mutex);
767+
if (trx_t trx= element->trx)
768+
{
769+
// trx is protected against commit in this branch
770+
}
771+
mutex_exit(&element->mutex);
772+
773+
May miss concurrently inserted transactions.
761774
762775
@return
763776
@retval 0 iteration completed successfully

storage/innobase/include/trx0trx.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ int
269269
trx_recover_for_mysql(
270270
/*==================*/
271271
XID* xid_list,/*!< in/out: prepared transactions */
272-
ulintlen);/*!< in: number of slots in xid_list */
272+
uintlen);/*!< in: number of slots in xid_list */
273273
/*******************************************************************//**
274274
This function is used to find one X/Open XA distributed transaction
275275
which is in the prepared state

storage/innobase/lock/lock0lock.cc

Lines changed: 129 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1533,61 +1533,6 @@ lock_sec_rec_some_has_impl(
15331533
return(trx);
15341534
}
15351535

1536-
#ifdef UNIV_DEBUG
1537-
/*********************************************************************//**
1538-
Checks if some transaction, other than given trx_id, has an explicit
1539-
lock on the given rec, in the given precise_mode.
1540-
1541-
FIXME: if the current transaction holds implicit lock from INSERT, a
1542-
subsequent locking read should not convert it to explicit. See also
1543-
MDEV-11215.
1544-
1545-
@return the transaction, whose id is not equal to trx_id, that has an
1546-
explicit lock on the given rec, in the given precise_mode or NULL.*/
1547-
static
1548-
trx_t*
1549-
lock_rec_other_trx_holds_expl(
1550-
/*==========================*/
1551-
ulint precise_mode,/*!< in: LOCK_S or LOCK_X
1552-
possibly ORed to LOCK_GAP or
1553-
LOCK_REC_NOT_GAP. */
1554-
trx_t* trx,/*!< in: trx holding implicit
1555-
lock on rec */
1556-
const rec_t* rec,/*!< in: user record */
1557-
const buf_block_t* block)/*!< in: buffer block
1558-
containing the record */
1559-
{
1560-
ut_ad(!page_rec_is_default_row(rec));
1561-
1562-
trx_t* holds = NULL;
1563-
ulint heap_no = page_rec_get_heap_no(rec);
1564-
1565-
lock_mutex_enter();
1566-
mutex_enter(&trx_sys->mutex);
1567-
1568-
for (trx_t* t = UT_LIST_GET_FIRST(trx_sys->rw_trx_list);
1569-
t != NULL;
1570-
t = UT_LIST_GET_NEXT(trx_list, t)) {
1571-
1572-
lock_t* expl_lock = lock_rec_has_expl(
1573-
precise_mode, block, heap_no, t);
1574-
1575-
if (expl_lock && expl_lock->trx != trx) {
1576-
/* An explicit lock is held by trx other than
1577-
the trx holding the implicit lock. */
1578-
holds = expl_lock->trx;
1579-
break;
1580-
}
1581-
}
1582-
1583-
mutex_exit(&trx_sys->mutex);
1584-
1585-
lock_mutex_exit();
1586-
1587-
return(holds);
1588-
}
1589-
#endif /* UNIV_DEBUG */
1590-
15911536
/*********************************************************************//**
15921537
Return approximate number or record locks (bits set in the bitmap) for
15931538
this transaction. Since delete-marked records may be removed, the
@@ -6464,45 +6409,6 @@ lock_rec_validate_page(
64646409
return(TRUE);
64656410
}
64666411

6467-
/*********************************************************************//**
6468-
Validates the table locks.
6469-
@return TRUE if ok */
6470-
static
6471-
ibool
6472-
lock_validate_table_locks(
6473-
/*======================*/
6474-
const trx_ut_list_t* trx_list)/*!< in: trx list */
6475-
{
6476-
const trx_t* trx;
6477-
6478-
ut_ad(lock_mutex_own());
6479-
ut_ad(trx_sys_mutex_own());
6480-
6481-
ut_ad(trx_list == &trx_sys->rw_trx_list);
6482-
6483-
for (trx = UT_LIST_GET_FIRST(*trx_list);
6484-
trx != NULL;
6485-
trx = UT_LIST_GET_NEXT(trx_list, trx)) {
6486-
6487-
const lock_t* lock;
6488-
6489-
check_trx_state(trx);
6490-
6491-
for (lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
6492-
lock != NULL;
6493-
lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
6494-
6495-
if (lock_get_type_low(lock) & LOCK_TABLE) {
6496-
6497-
lock_table_queue_validate(
6498-
lock->un_member.tab_lock.table);
6499-
}
6500-
}
6501-
}
6502-
6503-
return(TRUE);
6504-
}
6505-
65066412
/*********************************************************************//**
65076413
Validate record locks up to a limit.
65086414
@return lock at limit or NULL if no more locks in the hash bucket */
@@ -6590,6 +6496,29 @@ lock_rec_block_validate(
65906496
}
65916497
}
65926498

6499+
6500+
static my_bool lock_validate_table_locks(rw_trx_hash_element_t *element,
6501+
void *arg)
6502+
{
6503+
ut_ad(lock_mutex_own());
6504+
ut_ad(trx_sys_mutex_own()); /* Do we really need this. */
6505+
mutex_enter(&element->mutex);
6506+
if (element->trx)
6507+
{
6508+
check_trx_state(element->trx);
6509+
for (const lock_t *lock= UT_LIST_GET_FIRST(element->trx->lock.trx_locks);
6510+
lock != NULL;
6511+
lock= UT_LIST_GET_NEXT(trx_locks, lock))
6512+
{
6513+
if (lock_get_type_low(lock) & LOCK_TABLE)
6514+
lock_table_queue_validate(lock->un_member.tab_lock.table);
6515+
}
6516+
}
6517+
mutex_exit(&element->mutex);
6518+
return 0;
6519+
}
6520+
6521+
65936522
/*********************************************************************//**
65946523
Validates the lock system.
65956524
@return TRUE if ok */
@@ -6609,7 +6538,9 @@ lock_validate()
66096538
lock_mutex_enter();
66106539
mutex_enter(&trx_sys->mutex);
66116540

6612-
ut_a(lock_validate_table_locks(&trx_sys->rw_trx_list));
6541+
/* Validate table locks */
6542+
trx_sys->rw_trx_hash.iterate(reinterpret_cast<my_hash_walk_action>
6543+
(lock_validate_table_locks), 0);
66136544

66146545
/* Iterate over all the record locks and validate the locks. We
66156546
don't want to hog the lock_sys_t::mutex and the trx_sys_t::mutex.
@@ -6838,6 +6769,70 @@ lock_rec_convert_impl_to_expl_for_trx(
68386769
DEBUG_SYNC_C("after_lock_rec_convert_impl_to_expl_for_trx");
68396770
}
68406771

6772+
6773+
#ifdef UNIV_DEBUG
6774+
struct lock_rec_other_trx_holds_expl_arg
6775+
{
6776+
const ulint heap_no;
6777+
const buf_block_t * const block;
6778+
const trx_t *impl_trx;
6779+
};
6780+
6781+
6782+
static my_bool lock_rec_other_trx_holds_expl_callback(
6783+
rw_trx_hash_element_t *element,
6784+
lock_rec_other_trx_holds_expl_arg *arg)
6785+
{
6786+
mutex_enter(&element->mutex);
6787+
if (element->trx)
6788+
{
6789+
lock_t *expl_lock= lock_rec_has_expl(LOCK_S | LOCK_REC_NOT_GAP, arg->block,
6790+
arg->heap_no, element->trx);
6791+
/*
6792+
An explicit lock is held by trx other than the trx holding the implicit
6793+
lock.
6794+
*/
6795+
ut_ad(!expl_lock || expl_lock->trx == arg->impl_trx);
6796+
}
6797+
mutex_exit(&element->mutex);
6798+
return 0;
6799+
}
6800+
6801+
6802+
/**
6803+
Checks if some transaction, other than given trx_id, has an explicit
6804+
lock on the given rec.
6805+
6806+
FIXME: if the current transaction holds implicit lock from INSERT, a
6807+
subsequent locking read should not convert it to explicit. See also
6808+
MDEV-11215.
6809+
6810+
@param caller_trx trx of current thread
6811+
@param[in] trx trx holding implicit lock on rec
6812+
@param[in] rec user record
6813+
@param[in] block buffer block containing the record
6814+
*/
6815+
6816+
static void lock_rec_other_trx_holds_expl(trx_t *caller_trx, trx_t *trx,
6817+
const rec_t *rec,
6818+
const buf_block_t *block)
6819+
{
6820+
if (trx)
6821+
{
6822+
ut_ad(!page_rec_is_default_row(rec));
6823+
lock_mutex_enter();
6824+
lock_rec_other_trx_holds_expl_arg arg= { page_rec_get_heap_no(rec), block,
6825+
trx };
6826+
trx_sys->rw_trx_hash.iterate(caller_trx,
6827+
reinterpret_cast<my_hash_walk_action>
6828+
(lock_rec_other_trx_holds_expl_callback),
6829+
&arg);
6830+
lock_mutex_exit();
6831+
}
6832+
}
6833+
#endif /* UNIV_DEBUG */
6834+
6835+
68416836
/*********************************************************************//**
68426837
If a transaction has an implicit x-lock on a record, but no explicit x-lock
68436838
set on the record, sets one for it. */
@@ -6872,8 +6867,8 @@ lock_rec_convert_impl_to_expl(
68726867
trx = lock_sec_rec_some_has_impl(caller_trx, rec, index,
68736868
offsets);
68746869

6875-
ut_ad(!trx || !lock_rec_other_trx_holds_expl(
6876-
LOCK_S | LOCK_REC_NOT_GAP, trx, rec, block));
6870+
ut_d(lock_rec_other_trx_holds_expl(caller_trx, trx, rec,
6871+
block));
68776872
}
68786873

68796874
if (trx != 0) {
@@ -7771,52 +7766,38 @@ lock_table_get_n_locks(
77717766
}
77727767

77737768
#ifdef UNIV_DEBUG
7774-
/*******************************************************************//**
7775-
Do an exhaustive check for any locks (table or rec) against the table.
7776-
@return lock if found */
7777-
static
7778-
const lock_t*
7779-
lock_table_locks_lookup(
7780-
/*====================*/
7781-
const dict_table_t* table,/*!< in: check if there are
7782-
any locks held on records in
7783-
this table or on the table
7784-
itself */
7785-
const trx_ut_list_t* trx_list)/*!< in: trx list to check */
7786-
{
7787-
trx_t* trx;
7788-
7789-
ut_a(table != NULL);
7790-
ut_ad(lock_mutex_own());
7791-
ut_ad(trx_sys_mutex_own());
7792-
7793-
for (trx = UT_LIST_GET_FIRST(*trx_list);
7794-
trx != NULL;
7795-
trx = UT_LIST_GET_NEXT(trx_list, trx)) {
7796-
7797-
const lock_t* lock;
7798-
7799-
check_trx_state(trx);
7800-
7801-
for (lock = UT_LIST_GET_FIRST(trx->lock.trx_locks);
7802-
lock != NULL;
7803-
lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
7804-
7805-
ut_a(lock->trx == trx);
7806-
7807-
if (lock_get_type_low(lock) == LOCK_REC) {
7808-
ut_ad(!dict_index_is_online_ddl(lock->index)
7809-
|| dict_index_is_clust(lock->index));
7810-
if (lock->index->table == table) {
7811-
return(lock);
7812-
}
7813-
} else if (lock->un_member.tab_lock.table == table) {
7814-
return(lock);
7815-
}
7816-
}
7817-
}
7818-
7819-
return(NULL);
7769+
/**
7770+
Do an exhaustive check for any locks (table or rec) against the table.
7771+
7772+
@param[in] table check if there are any locks held on records in this table
7773+
or on the table itself
7774+
*/
7775+
7776+
static my_bool lock_table_locks_lookup(rw_trx_hash_element_t *element,
7777+
const dict_table_t *table)
7778+
{
7779+
ut_ad(lock_mutex_own());
7780+
mutex_enter(&element->mutex);
7781+
if (element->trx)
7782+
{
7783+
check_trx_state(element->trx);
7784+
for (const lock_t *lock= UT_LIST_GET_FIRST(element->trx->lock.trx_locks);
7785+
lock != NULL;
7786+
lock= UT_LIST_GET_NEXT(trx_locks, lock))
7787+
{
7788+
ut_ad(lock->trx == element->trx);
7789+
if (lock_get_type_low(lock) == LOCK_REC)
7790+
{
7791+
ut_ad(!dict_index_is_online_ddl(lock->index) ||
7792+
dict_index_is_clust(lock->index));
7793+
ut_ad(lock->index->table != table);
7794+
}
7795+
else
7796+
ut_ad(lock->un_member.tab_lock.table != table);
7797+
}
7798+
}
7799+
mutex_exit(&element->mutex);
7800+
return 0;
78207801
}
78217802
#endif /* UNIV_DEBUG */
78227803

@@ -7832,17 +7813,17 @@ lock_table_has_locks(
78327813
{
78337814
ibool has_locks;
78347815

7816+
ut_ad(table != NULL);
78357817
lock_mutex_enter();
78367818

78377819
has_locks = UT_LIST_GET_LEN(table->locks) > 0 || table->n_rec_locks > 0;
78387820

78397821
#ifdef UNIV_DEBUG
78407822
if (!has_locks) {
7841-
mutex_enter(&trx_sys->mutex);
7842-
7843-
ut_ad(!lock_table_locks_lookup(table, &trx_sys->rw_trx_list));
7844-
7845-
mutex_exit(&trx_sys->mutex);
7823+
trx_sys->rw_trx_hash.iterate(
7824+
reinterpret_cast<my_hash_walk_action>
7825+
(lock_table_locks_lookup),
7826+
const_cast<dict_table_t*>(table));
78467827
}
78477828
#endif /* UNIV_DEBUG */
78487829

0 commit comments

Comments
 (0)