@@ -1533,61 +1533,6 @@ lock_sec_rec_some_has_impl(
15331533return (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/* ********************************************************************/ /* *
15921537Return approximate number or record locks (bits set in the bitmap) for
15931538this transaction. Since delete-marked records may be removed, the
@@ -6464,45 +6409,6 @@ lock_rec_validate_page(
64646409return (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/* ********************************************************************/ /* *
65076413Validate 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/* ********************************************************************/ /* *
65946523Validates the lock system.
65956524@return TRUE if ok */
@@ -6609,7 +6538,9 @@ lock_validate()
66096538lock_mutex_enter ();
66106539mutex_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
66156546don'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(
68386769DEBUG_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/* ********************************************************************/ /* *
68426837If a transaction has an implicit x-lock on a record, but no explicit x-lock
68436838set on the record, sets one for it. */
@@ -6872,8 +6867,8 @@ lock_rec_convert_impl_to_expl(
68726867trx = 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
68796874if (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{
78337814ibool has_locks;
78347815
7816+ ut_ad (table != NULL );
78357817lock_mutex_enter ();
78367818
78377819has_locks = UT_LIST_GET_LEN (table->locks ) > 0 || table->n_rec_locks > 0 ;
78387820
78397821#ifdef UNIV_DEBUG
78407822if (!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