@@ -1877,7 +1877,7 @@ Add the lock to the record lock hash and the transaction's lock list
18771877@param[in,out] lock Newly created record lock to add to the rec hash
18781878@param[in] add_to_hash If the lock should be added to the hash table */
18791879void
1880- RecLock::lock_add (lock_t * lock, bool add_to_hash)
1880+ RecLock::lock_add (lock_t * lock, bool add_to_hash) const
18811881{
18821882ut_ad (lock_mutex_own ());
18831883ut_ad (trx_mutex_own (lock->trx ));
@@ -1929,7 +1929,7 @@ RecLock::create(
19291929#ifdef WITH_WSREP
19301930,lock_t * c_lock
19311931#endif /* WITH_WSREP */
1932- )
1932+ ) const
19331933{
19341934ut_ad (lock_mutex_own ());
19351935ut_ad (owns_trx_mutex == trx_mutex_own (trx));
@@ -2389,88 +2389,6 @@ lock_rec_add_to_queue(
23892389rec_lock.create (trx, caller_owns_trx_mutex, true );
23902390}
23912391
2392- /* ********************************************************************/ /* *
2393- This is a fast routine for locking a record in the most common cases:
2394- there are no explicit locks on the page, or there is just one lock, owned
2395- by this transaction, and of the right type_mode. This is a low-level function
2396- which does NOT look at implicit locks! Checks lock compatibility within
2397- explicit locks. This function sets a normal next-key lock, or in the case of
2398- a page supremum record, a gap type lock.
2399- @return whether the locking succeeded */
2400- UNIV_INLINE
2401- lock_rec_req_status
2402- lock_rec_lock_fast (
2403- /* ===============*/
2404- bool impl,/* !< in: if TRUE, no lock is set
2405- if no wait is necessary: we
2406- assume that the caller will
2407- set an implicit lock */
2408- ulint mode,/* !< in: lock mode: LOCK_X or
2409- LOCK_S possibly ORed to either
2410- LOCK_GAP or LOCK_REC_NOT_GAP */
2411- const buf_block_t * block,/* !< in: buffer block containing
2412- the record */
2413- ulint heap_no,/* !< in: heap number of record */
2414- dict_index_t * index,/* !< in: index of record */
2415- que_thr_t * thr)/* !< in: query thread */
2416- {
2417- ut_ad (lock_mutex_own ());
2418- ut_ad (!srv_read_only_mode);
2419- ut_ad ((LOCK_MODE_MASK & mode) != LOCK_S
2420- || lock_table_has (thr_get_trx (thr), index->table , LOCK_IS));
2421- ut_ad ((LOCK_MODE_MASK & mode) != LOCK_X
2422- || lock_table_has (thr_get_trx (thr), index->table , LOCK_IX)
2423- || srv_read_only_mode);
2424- ut_ad ((LOCK_MODE_MASK & mode) == LOCK_S
2425- || (LOCK_MODE_MASK & mode) == LOCK_X);
2426- ut_ad (mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
2427- || mode - (LOCK_MODE_MASK & mode) == 0
2428- || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
2429- ut_ad (dict_index_is_clust (index) || !dict_index_is_online_ddl (index));
2430-
2431- DBUG_EXECUTE_IF (" innodb_report_deadlock" , return (LOCK_REC_FAIL););
2432-
2433- lock_t * lock = lock_rec_get_first_on_page (lock_sys->rec_hash , block);
2434-
2435- trx_t * trx = thr_get_trx (thr);
2436-
2437- lock_rec_req_status status = LOCK_REC_SUCCESS;
2438-
2439- if (lock == NULL ) {
2440-
2441- if (!impl) {
2442- RecLockrec_lock (index, block, heap_no, mode);
2443-
2444- /* Note that we don't own the trx mutex. */
2445- rec_lock.create (trx, false , true );
2446- }
2447-
2448- status = LOCK_REC_SUCCESS_CREATED;
2449- } else {
2450- trx_mutex_enter (trx);
2451-
2452- if (lock_rec_get_next_on_page (lock)
2453- || lock->trx != trx
2454- || lock->type_mode != (mode | LOCK_REC)
2455- || lock_rec_get_n_bits (lock) <= heap_no) {
2456-
2457- status = LOCK_REC_FAIL;
2458- } else if (!impl) {
2459- /* If the nth bit of the record lock is already set
2460- then we do not set a new lock bit, otherwise we do
2461- set */
2462- if (!lock_rec_get_nth_bit (lock, heap_no)) {
2463- lock_rec_set_nth_bit (lock, heap_no);
2464- status = LOCK_REC_SUCCESS_CREATED;
2465- }
2466- }
2467-
2468- trx_mutex_exit (trx);
2469- }
2470-
2471- return (status);
2472- }
2473-
24742392/* ********************************************************************/ /* *
24752393This is the general, and slower, routine for locking a record. This is a
24762394low-level function which does NOT look at implicit locks! Checks lock
@@ -2496,33 +2414,12 @@ lock_rec_lock_slow(
24962414que_thr_t * thr)/* !< in: query thread */
24972415{
24982416ut_ad (lock_mutex_own ());
2499- ut_ad (!srv_read_only_mode);
2500- ut_ad ((LOCK_MODE_MASK & mode) != LOCK_S
2501- || lock_table_has (thr_get_trx (thr), index->table , LOCK_IS));
2502- ut_ad ((LOCK_MODE_MASK & mode) != LOCK_X
2503- || lock_table_has (thr_get_trx (thr), index->table , LOCK_IX));
2504- ut_ad ((LOCK_MODE_MASK & mode) == LOCK_S
2505- || (LOCK_MODE_MASK & mode) == LOCK_X);
2506- ut_ad (mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
2507- || mode - (LOCK_MODE_MASK & mode) == 0
2508- || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
2509- ut_ad (dict_index_is_clust (index) || !dict_index_is_online_ddl (index));
2510-
2511- DBUG_EXECUTE_IF (" innodb_report_deadlock" , return (DB_DEADLOCK););
25122417
2513- dberr_t err;
25142418trx_t * trx = thr_get_trx (thr);
2419+ ut_ad (trx_mutex_own (trx));
25152420
2516- trx_mutex_enter (trx);
2517-
2518- if (lock_rec_has_expl (mode, block, heap_no, trx)) {
2519-
2520- /* The trx already has a strong enough lock on rec: do
2521- nothing */
2522-
2523- err = DB_SUCCESS;
2524-
2525- } else {
2421+ /* Do nothing if the trx already has a strong enough lock on rec */
2422+ if (!lock_rec_has_expl (mode, block, heap_no, trx)) {
25262423lock_t * wait_for = lock_rec_other_has_conflicting (
25272424mode, block, heap_no, trx);
25282425
@@ -2535,7 +2432,7 @@ lock_rec_lock_slow(
25352432
25362433RecLockrec_lock (thr, index, block, heap_no, mode);
25372434
2538- err = rec_lock.add_to_waitq (wait_for);
2435+ return rec_lock.add_to_waitq (wait_for);
25392436
25402437} else if (!impl) {
25412438
@@ -2546,15 +2443,10 @@ lock_rec_lock_slow(
25462443LOCK_REC | mode, block, heap_no, index, trx,
25472444true );
25482445
2549- err = DB_SUCCESS_LOCKED_REC;
2550- } else {
2551- err = DB_SUCCESS;
2446+ return DB_SUCCESS_LOCKED_REC;
25522447}
25532448}
2554-
2555- trx_mutex_exit (trx);
2556-
2557- return (err);
2449+ return DB_SUCCESS;
25582450}
25592451
25602452/* ********************************************************************/ /* *
@@ -2582,33 +2474,61 @@ lock_rec_lock(
25822474dict_index_t * index,/* !< in: index of record */
25832475que_thr_t * thr)/* !< in: query thread */
25842476{
2585- ut_ad (lock_mutex_own ());
2586- ut_ad (!srv_read_only_mode);
2587- ut_ad ((LOCK_MODE_MASK & mode) != LOCK_S
2588- || lock_table_has (thr_get_trx (thr), index->table , LOCK_IS));
2589- ut_ad ((LOCK_MODE_MASK & mode) != LOCK_X
2590- || lock_table_has (thr_get_trx (thr), index->table , LOCK_IX));
2591- ut_ad ((LOCK_MODE_MASK & mode) == LOCK_S
2592- || (LOCK_MODE_MASK & mode) == LOCK_X);
2593- ut_ad (mode - (LOCK_MODE_MASK & mode) == LOCK_GAP
2594- || mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
2595- || mode - (LOCK_MODE_MASK & mode) == 0 );
2596- ut_ad (dict_index_is_clust (index) || !dict_index_is_online_ddl (index));
2597-
2598- /* We try a simplified and faster subroutine for the most
2599- common cases */
2600- switch (lock_rec_lock_fast (impl, mode, block, heap_no, index, thr)) {
2601- case LOCK_REC_SUCCESS:
2602- return (DB_SUCCESS);
2603- case LOCK_REC_SUCCESS_CREATED:
2604- return (DB_SUCCESS_LOCKED_REC);
2605- case LOCK_REC_FAIL:
2606- return (lock_rec_lock_slow (impl, mode, block,
2607- heap_no, index, thr));
2608- }
2609-
2610- ut_error;
2611- return (DB_ERROR);
2477+ trx_t *trx= thr_get_trx (thr);
2478+ dberr_t err= DB_SUCCESS;
2479+
2480+ ut_ad (!srv_read_only_mode);
2481+ ut_ad ((LOCK_MODE_MASK & mode) == LOCK_S ||
2482+ (LOCK_MODE_MASK & mode) == LOCK_X);
2483+ ut_ad ((mode & LOCK_TYPE_MASK) == LOCK_GAP ||
2484+ (mode & LOCK_TYPE_MASK) == LOCK_REC_NOT_GAP ||
2485+ (mode & LOCK_TYPE_MASK) == 0 );
2486+ ut_ad (dict_index_is_clust (index) || !dict_index_is_online_ddl (index));
2487+ DBUG_EXECUTE_IF (" innodb_report_deadlock" , return DB_DEADLOCK;);
2488+
2489+ lock_mutex_enter ();
2490+ ut_ad ((LOCK_MODE_MASK & mode) != LOCK_S ||
2491+ lock_table_has (trx, index->table , LOCK_IS));
2492+ ut_ad ((LOCK_MODE_MASK & mode) != LOCK_X ||
2493+ lock_table_has (trx, index->table , LOCK_IX));
2494+
2495+ if (lock_t *lock= lock_rec_get_first_on_page (lock_sys->rec_hash , block))
2496+ {
2497+ trx_mutex_enter (trx);
2498+ if (lock_rec_get_next_on_page (lock) ||
2499+ lock->trx != trx ||
2500+ lock->type_mode != (mode | LOCK_REC) ||
2501+ lock_rec_get_n_bits (lock) <= heap_no)
2502+ {
2503+ err= lock_rec_lock_slow (impl, mode, block, heap_no, index, thr);
2504+ }
2505+ else if (!impl)
2506+ {
2507+ /*
2508+ If the nth bit of the record lock is already set then we do not set
2509+ a new lock bit, otherwise we do set
2510+ */
2511+ if (!lock_rec_get_nth_bit (lock, heap_no))
2512+ {
2513+ lock_rec_set_nth_bit (lock, heap_no);
2514+ err= DB_SUCCESS_LOCKED_REC;
2515+ }
2516+ }
2517+ trx_mutex_exit (trx);
2518+ }
2519+ else
2520+ {
2521+ /*
2522+ Simplified and faster path for the most common cases
2523+ Note that we don't own the trx mutex.
2524+ */
2525+ if (!impl)
2526+ RecLock (index, block, heap_no, mode).create (trx, false , true );
2527+ err= DB_SUCCESS_LOCKED_REC;
2528+ }
2529+ lock_mutex_exit ();
2530+ MONITOR_ATOMIC_INC (MONITOR_NUM_RECLOCK_REQ);
2531+ return err;
26122532}
26132533
26142534/* ********************************************************************/ /* *
@@ -6575,17 +6495,9 @@ lock_clust_rec_modify_check_and_lock(
65756495lock_rec_convert_impl_to_expl (thr_get_trx (thr), block, rec, index,
65766496 offsets);
65776497
6578- lock_mutex_enter ();
6579-
6580- ut_ad (lock_table_has (thr_get_trx (thr), index->table , LOCK_IX));
6581-
65826498err = lock_rec_lock (TRUE , LOCK_X | LOCK_REC_NOT_GAP,
65836499 block, heap_no, index, thr);
65846500
6585- MONITOR_INC (MONITOR_NUM_RECLOCK_REQ);
6586-
6587- lock_mutex_exit ();
6588-
65896501ut_ad (lock_rec_queue_validate (FALSE , block, rec, index, offsets));
65906502
65916503if (err == DB_SUCCESS_LOCKED_REC) {
@@ -6638,17 +6550,9 @@ lock_sec_rec_modify_check_and_lock(
66386550index record, and this would not have been possible if another active
66396551transaction had modified this secondary index record. */
66406552
6641- lock_mutex_enter ();
6642-
6643- ut_ad (lock_table_has (thr_get_trx (thr), index->table , LOCK_IX));
6644-
66456553err = lock_rec_lock (TRUE , LOCK_X | LOCK_REC_NOT_GAP,
66466554 block, heap_no, index, thr);
66476555
6648- MONITOR_INC (MONITOR_NUM_RECLOCK_REQ);
6649-
6650- lock_mutex_exit ();
6651-
66526556#ifdef UNIV_DEBUG
66536557{
66546558mem_heap_t * heap = NULL ;
@@ -6740,20 +6644,9 @@ lock_sec_rec_read_check_and_lock(
67406644 index, offsets);
67416645}
67426646
6743- lock_mutex_enter ();
6744-
6745- ut_ad (mode != LOCK_X
6746- || lock_table_has (thr_get_trx (thr), index->table , LOCK_IX));
6747- ut_ad (mode != LOCK_S
6748- || lock_table_has (thr_get_trx (thr), index->table , LOCK_IS));
6749-
67506647err = lock_rec_lock (FALSE , mode | gap_mode,
67516648 block, heap_no, index, thr);
67526649
6753- MONITOR_INC (MONITOR_NUM_RECLOCK_REQ);
6754-
6755- lock_mutex_exit ();
6756-
67576650ut_ad (lock_rec_queue_validate (FALSE , block, rec, index, offsets));
67586651
67596652return (err);
@@ -6816,19 +6709,8 @@ lock_clust_rec_read_check_and_lock(
68166709 index, offsets);
68176710}
68186711
6819- lock_mutex_enter ();
6820-
6821- ut_ad (mode != LOCK_X
6822- || lock_table_has (thr_get_trx (thr), index->table , LOCK_IX));
6823- ut_ad (mode != LOCK_S
6824- || lock_table_has (thr_get_trx (thr), index->table , LOCK_IS));
6825-
68266712err = lock_rec_lock (FALSE , mode | gap_mode, block, heap_no, index, thr);
68276713
6828- MONITOR_INC (MONITOR_NUM_RECLOCK_REQ);
6829-
6830- lock_mutex_exit ();
6831-
68326714ut_ad (lock_rec_queue_validate (FALSE , block, rec, index, offsets));
68336715
68346716DEBUG_SYNC_C (" after_lock_clust_rec_read_check_and_lock" );
0 commit comments