diff options
Diffstat (limited to 'storage/innobase/lock/lock0lock.cc')
-rw-r--r-- | storage/innobase/lock/lock0lock.cc | 336 |
1 files changed, 160 insertions, 176 deletions
diff --git a/storage/innobase/lock/lock0lock.cc b/storage/innobase/lock/lock0lock.cc index eb3d260e78a..0fade62e7aa 100644 --- a/storage/innobase/lock/lock0lock.cc +++ b/storage/innobase/lock/lock0lock.cc @@ -1,7 +1,7 @@ /***************************************************************************** Copyright (c) 1996, 2016, Oracle and/or its affiliates. All Rights Reserved. -Copyright (c) 2014, 2018, MariaDB Corporation. +Copyright (c) 2014, 2019, MariaDB Corporation. 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 @@ -13,7 +13,7 @@ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., -51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA +51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA *****************************************************************************/ @@ -383,6 +383,20 @@ struct lock_stack_t { ulint heap_no; /*!< heap number if rec lock */ }; +/** Pretty-print a table lock. +@param[in,out] file output stream +@param[in] lock table lock +@param[in] now current time */ +static void lock_table_print(FILE* file, const lock_t* lock, time_t now); + +/** Pretty-print a record lock. +@param[in,out] file output stream +@param[in] lock record lock +@param[in] now current time +@param[in,out] mtr mini-transaction */ +static void lock_rec_print(FILE* file, const lock_t* lock, time_t now, + mtr_t* mtr = NULL); + /*********************************************************************//** Checks if a waiting record lock request still has to wait in a queue. @return lock that is causing the wait */ @@ -466,20 +480,18 @@ UNIV_INTERN ibool lock_deadlock_found = FALSE; /** Only created if !srv_read_only_mode */ static FILE* lock_latest_err_file; -/********************************************************************//** -Checks if a joining lock request results in a deadlock. If a deadlock is +/** Check if a joining lock request results in a deadlock. If a deadlock is found this function will resolve the dadlock by choosing a victim transaction -and rolling it back. It will attempt to resolve all deadlocks. The returned -transaction id will be the joining transaction id or 0 if some other -transaction was chosen as a victim and rolled back or no deadlock found. - -@return id of transaction chosen as victim or 0 */ -static -trx_id_t -lock_deadlock_check_and_resolve( -/*===========================*/ - const lock_t* lock, /*!< in: lock the transaction is requesting */ - const trx_t* trx); /*!< in: transaction */ +and rolling it back. It will attempt to resolve all deadlocks. +@param[in] trx joining transaction +@param[in] lock the requested lock +@param[in] now current time +@return trx->id of the victim transaction +@retval 0 if some other transaction was chosen as a victim and +rolled back, or no deadlock was found. */ +static trx_id_t lock_deadlock_check_and_resolve(const trx_t* trx, + const lock_t* lock, + time_t now); /*********************************************************************//** Gets the nth bit of a record lock. @@ -898,7 +910,7 @@ UNIV_INLINE void lock_reset_lock_and_trx_wait( /*=========================*/ - lock_t* lock) /*!< in/out: record lock */ + lock_t* lock) /*!< in/out: record lock */ { ut_ad(lock_get_wait(lock)); ut_ad(lock_mutex_own()); @@ -1135,12 +1147,11 @@ lock_rec_has_to_wait( thread, we need to look at trx ordering and lock types */ if (wsrep_thd_is_BF(trx->mysql_thd, FALSE) && wsrep_thd_is_BF(lock2->trx->mysql_thd, TRUE)) { - if (wsrep_debug) { fprintf(stderr, "BF-BF lock conflict, locking: %lu\n", for_locking); - lock_rec_print(stderr, lock2); + lock_rec_print(stderr, lock2, time(NULL)); } if (wsrep_trx_order_before(trx->mysql_thd, @@ -1159,7 +1170,8 @@ lock_rec_has_to_wait( "conflicts states: my %d locked %d\n", wsrep_thd_conflict_state(trx->mysql_thd, FALSE), wsrep_thd_conflict_state(lock2->trx->mysql_thd, FALSE) ); - lock_rec_print(stderr, lock2); + lock_rec_print(stderr, lock2, + time(NULL)); if (for_locking) return FALSE; //abort(); } @@ -1786,10 +1798,12 @@ wsrep_kill_victim( fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n", stderr); + time_t now = time(NULL); + if (lock_get_type(lock) == LOCK_REC) { - lock_rec_print(stderr, lock); + lock_rec_print(stderr, lock, now); } else { - lock_table_print(stderr, lock); + lock_table_print(stderr, lock, now); } } @@ -2032,16 +2046,20 @@ wsrep_print_wait_locks( { if (wsrep_debug && c_lock->trx->lock.wait_lock != c_lock) { fprintf(stderr, "WSREP: c_lock != wait lock\n"); + time_t now = time(NULL); + if (lock_get_type_low(c_lock) & LOCK_TABLE) { - lock_table_print(stderr, c_lock); + lock_table_print(stderr, c_lock, now); } else { - lock_rec_print(stderr, c_lock); + lock_rec_print(stderr, c_lock, now); } if (lock_get_type_low(c_lock->trx->lock.wait_lock) & LOCK_TABLE) { - lock_table_print(stderr, c_lock->trx->lock.wait_lock); + lock_table_print(stderr, c_lock->trx->lock.wait_lock, + now); } else { - lock_rec_print(stderr, c_lock->trx->lock.wait_lock); + lock_rec_print(stderr, c_lock->trx->lock.wait_lock, + now); } } } @@ -2153,7 +2171,7 @@ lock_rec_create( /* Set the bit corresponding to rec */ lock_rec_set_nth_bit(lock, heap_no); - lock->requested_time = ut_time(); + lock->requested_time = time(NULL); lock->wait_time = 0; index->table->n_rec_locks++; @@ -2216,13 +2234,6 @@ lock_rec_create( trx_mutex_enter(trx); } - /* trx might not wait for c_lock, but some other lock - does not matter if wait_lock was released above - */ - if (c_lock->trx->lock.wait_lock == c_lock) { - lock_reset_lock_and_trx_wait(lock); - } - trx_mutex_exit(c_lock->trx); if (wsrep_debug) { @@ -2286,10 +2297,7 @@ If neither of them is wait lock, the first one has higher priority. If only one of them is a wait lock, it has lower priority. Otherwise, the one with an older transaction has higher priority. @returns true if lock1 has higher priority, false otherwise. */ -bool -has_higher_priority( - lock_t *lock1, - lock_t *lock2) +static bool has_higher_priority(lock_t *lock1, lock_t *lock2) { if (lock1 == NULL) { return false; @@ -2487,7 +2495,8 @@ lock_rec_enqueue_waiting( trx_mutex_exit(trx); - victim_trx_id = lock_deadlock_check_and_resolve(lock, trx); + const time_t now = time(NULL); + victim_trx_id = lock_deadlock_check_and_resolve(trx, lock, now); trx_mutex_enter(trx); @@ -2511,7 +2520,7 @@ lock_rec_enqueue_waiting( trx->lock.que_state = TRX_QUE_LOCK_WAIT; trx->lock.was_chosen_as_deadlock_victim = FALSE; - trx->lock.wait_started = ut_time(); + trx->lock.wait_started = now; ut_a(que_thr_stop(thr)); @@ -2652,7 +2661,8 @@ lock_rec_add_to_queue( "BF skipping wait: " TRX_ID_FMT "\n", trx->id); - lock_rec_print(stderr, lock); + lock_rec_print(stderr, lock, + time(NULL)); } } else #endif @@ -2968,13 +2978,14 @@ lock_rec_has_to_wait_in_queue( if (wsrep_thd_is_BF(wait_lock->trx->mysql_thd, FALSE) && wsrep_thd_is_BF(lock->trx->mysql_thd, TRUE)) { if (wsrep_debug) { + time_t now = time(NULL); fprintf(stderr, "BF-BF lock conflict " TRX_ID_FMT " : " TRX_ID_FMT "\n", wait_lock->trx->id, lock->trx->id); - lock_rec_print(stderr, wait_lock); - lock_rec_print(stderr, lock); + lock_rec_print(stderr, wait_lock, now); + lock_rec_print(stderr, lock, now); } /* don't wait for another BF lock */ continue; @@ -3041,16 +3052,18 @@ lock_grant( } } + const time_t now = time(NULL); + /* Cumulate total lock wait time for statistics */ if (lock_get_type_low(lock) & LOCK_TABLE) { lock->trx->total_table_lock_wait_time += - (ulint)difftime(ut_time(), lock->trx->lock.wait_started); + (ulint)difftime(now, lock->trx->lock.wait_started); } else { lock->trx->total_rec_lock_wait_time += - (ulint)difftime(ut_time(), lock->trx->lock.wait_started); + (ulint)difftime(now, lock->trx->lock.wait_started); } - lock->wait_time = (ulint)difftime(ut_time(), lock->requested_time); + lock->wait_time = (ulint)difftime(now, lock->requested_time); if (!owns_trx_mutex) { trx_mutex_exit(lock->trx); @@ -4303,28 +4316,26 @@ lock_deadlock_trx_print( mutex_exit(&trx_sys->mutex); } -/*********************************************************************//** -Print lock data to the deadlock file and possibly to stderr. */ -UNIV_INLINE -void -lock_deadlock_lock_print( -/*=====================*/ - const lock_t* lock) /*!< in: record or table type lock */ +/** Print lock data to the deadlock file and possibly to stderr. +@param[in] lock record or table lock +@param[in] now current time */ +static void lock_deadlock_lock_print(const lock_t* lock, time_t now) { ut_ad(lock_mutex_own()); ut_ad(!srv_read_only_mode); if (lock_get_type_low(lock) == LOCK_REC) { - lock_rec_print(lock_latest_err_file, lock); + mtr_t mtr; + lock_rec_print(lock_latest_err_file, lock, now, &mtr); if (srv_print_all_deadlocks) { - lock_rec_print(stderr, lock); + lock_rec_print(stderr, lock, now, &mtr); } } else { - lock_table_print(lock_latest_err_file, lock); + lock_table_print(lock_latest_err_file, lock, now); if (srv_print_all_deadlocks) { - lock_table_print(stderr, lock); + lock_table_print(stderr, lock, now); } } } @@ -4437,6 +4448,8 @@ lock_deadlock_notify( ut_ad(lock_mutex_own()); ut_ad(!srv_read_only_mode); + const time_t now = time(NULL); + lock_deadlock_start_print(); lock_deadlock_fputs("\n*** (1) TRANSACTION:\n"); @@ -4445,7 +4458,7 @@ lock_deadlock_notify( lock_deadlock_fputs("*** (1) WAITING FOR THIS LOCK TO BE GRANTED:\n"); - lock_deadlock_lock_print(ctx->wait_lock); + lock_deadlock_lock_print(ctx->wait_lock, now); lock_deadlock_fputs("*** (2) TRANSACTION:\n"); @@ -4453,7 +4466,7 @@ lock_deadlock_notify( lock_deadlock_fputs("*** (2) HOLDS THE LOCK(S):\n"); - lock_deadlock_lock_print(lock); + lock_deadlock_lock_print(lock, now); /* It is possible that the joining transaction was granted its lock when we rolled back some other waiting transaction. */ @@ -4462,7 +4475,7 @@ lock_deadlock_notify( lock_deadlock_fputs( "*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n"); - lock_deadlock_lock_print(ctx->start->lock.wait_lock); + lock_deadlock_lock_print(ctx->start->lock.wait_lock, now); } #ifdef UNIV_DEBUG @@ -4710,14 +4723,12 @@ lock_deadlock_search( return(0); } -/********************************************************************//** -Print info about transaction that was rolled back. */ -static -void -lock_deadlock_joining_trx_print( -/*============================*/ - const trx_t* trx, /*!< in: transaction rolled back */ - const lock_t* lock) /*!< in: lock trx wants */ +/** Print info about transaction that was rolled back. +@param[in] trx victim transaction +@param[in] lock the requested lock +@param[in] now current time */ +static void lock_deadlock_joining_trx_print(const trx_t* trx, + const lock_t* lock, time_t now) { ut_ad(lock_mutex_own()); ut_ad(!srv_read_only_mode); @@ -4737,7 +4748,7 @@ lock_deadlock_joining_trx_print( lock_deadlock_fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n"); - lock_deadlock_lock_print(lock); + lock_deadlock_lock_print(lock, now); } /********************************************************************//** @@ -4807,20 +4818,17 @@ lock_report_waiters_to_mysql( } -/********************************************************************//** -Checks if a joining lock request results in a deadlock. If a deadlock is +/** Check if a joining lock request results in a deadlock. If a deadlock is found this function will resolve the dadlock by choosing a victim transaction -and rolling it back. It will attempt to resolve all deadlocks. The returned -transaction id will be the joining transaction id or 0 if some other -transaction was chosen as a victim and rolled back or no deadlock found. - -@return id of transaction chosen as victim or 0 */ -static -trx_id_t -lock_deadlock_check_and_resolve( -/*============================*/ - const lock_t* lock, /*!< in: lock the transaction is requesting */ - const trx_t* trx) /*!< in: transaction */ +and rolling it back. It will attempt to resolve all deadlocks. +@param[in] trx joining transaction +@param[in] lock the requested lock +@param[in] now current time +@return trx->id of the victim transaction +@retval 0 if some other transaction was chosen as a victim and +rolled back, or no deadlock was found. */ +static trx_id_t lock_deadlock_check_and_resolve(const trx_t* trx, + const lock_t* lock, time_t now) { trx_id_t victim_trx_id; struct thd_wait_reports waitee_buf; @@ -4872,17 +4880,12 @@ lock_deadlock_check_and_resolve( ut_a(victim_trx_id == trx->id); #ifdef WITH_WSREP - if (!wsrep_thd_is_BF(ctx.start->mysql_thd, TRUE)) - { + if (!wsrep_thd_is_BF(ctx.start->mysql_thd, TRUE)); else #endif /* WITH_WSREP */ - if (!srv_read_only_mode) { - lock_deadlock_joining_trx_print(trx, lock); - } -#ifdef WITH_WSREP - } else { - /* BF processor */; + if (!srv_read_only_mode) { + lock_deadlock_joining_trx_print(trx, lock, + now); } -#endif /* WITH_WSREP */ MONITOR_INC(MONITOR_DEADLOCK); @@ -4960,7 +4963,7 @@ lock_table_create( lock->type_mode = type_mode | LOCK_TABLE; lock->trx = trx; - lock->requested_time = ut_time(); + lock->requested_time = time(NULL); lock->wait_time = 0; lock->un_member.tab_lock.table = table; @@ -4970,19 +4973,18 @@ lock_table_create( UT_LIST_ADD_LAST(trx_locks, trx->lock.trx_locks, lock); #ifdef WITH_WSREP - if (wsrep_thd_is_wsrep(trx->mysql_thd)) { - if (c_lock && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { + if (c_lock && wsrep_on_trx(trx)) { + if (wsrep_thd_is_wsrep(trx->mysql_thd) + && wsrep_thd_is_BF(trx->mysql_thd, FALSE)) { UT_LIST_INSERT_AFTER( un_member.tab_lock.locks, table->locks, c_lock, lock); } else { UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); } - if (c_lock) { - trx_mutex_enter(c_lock->trx); - } + trx_mutex_enter(c_lock->trx); - if (c_lock && c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { + if (c_lock->trx->lock.que_state == TRX_QUE_LOCK_WAIT) { c_lock->trx->lock.was_chosen_as_deadlock_victim = TRUE; @@ -4991,36 +4993,21 @@ lock_table_create( wsrep_print_wait_locks(c_lock->trx->lock.wait_lock); } - /* have to release trx mutex for the duration of - victim lock release. This will eventually call - lock_grant, which wants to grant trx mutex again - */ - /* caller has trx_mutex, have to release for lock cancel */ + /* The lock release will call lock_grant(), + which would acquire trx->mutex again. */ trx_mutex_exit(trx); lock_cancel_waiting_and_release(c_lock->trx->lock.wait_lock); trx_mutex_enter(trx); - /* trx might not wait for c_lock, but some other lock - does not matter if wait_lock was released above - */ - if (c_lock->trx->lock.wait_lock == c_lock) { - lock_reset_lock_and_trx_wait(lock); - } - if (wsrep_debug) { fprintf(stderr, "WSREP: c_lock canceled " TRX_ID_FMT "\n", c_lock->trx->id); } } - if (c_lock) { - trx_mutex_exit(c_lock->trx); - } - } else { + trx_mutex_exit(c_lock->trx); + } else #endif /* WITH_WSREP */ UT_LIST_ADD_LAST(un_member.tab_lock.locks, table->locks, lock); -#ifdef WITH_WSREP - } -#endif /* WITH_WSREP */ if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) { @@ -5225,9 +5212,10 @@ lock_table_enqueue_waiting( /* Enqueue the lock request that will wait to be granted */ #ifdef WITH_WSREP - if (trx->lock.was_chosen_as_deadlock_victim) { + if (trx->lock.was_chosen_as_deadlock_victim && wsrep_on_trx(trx)) { return(DB_DEADLOCK); } + lock = lock_table_create(c_lock, table, mode | LOCK_WAIT, trx); #else lock = lock_table_create(table, mode | LOCK_WAIT, trx); @@ -5243,7 +5231,9 @@ lock_table_enqueue_waiting( trx_mutex_exit(trx); - victim_trx_id = lock_deadlock_check_and_resolve(lock, trx); + const time_t now = time(NULL); + + victim_trx_id = lock_deadlock_check_and_resolve(trx, lock, now); trx_mutex_enter(trx); @@ -5265,7 +5255,7 @@ lock_table_enqueue_waiting( trx->lock.que_state = TRX_QUE_LOCK_WAIT; - trx->lock.wait_started = ut_time(); + trx->lock.wait_started = now; trx->lock.was_chosen_as_deadlock_victim = FALSE; trx->n_table_lock_waits++; @@ -5372,7 +5362,7 @@ lock_table( lock_mutex_enter(); DBUG_EXECUTE_IF("fatal-semaphore-timeout", - { os_thread_sleep(3600000000); }); + { os_thread_sleep(3600000000U); }); /* We have to check if the new lock is compatible with any locks other transactions have in the table lock queue. */ @@ -6009,14 +5999,11 @@ lock_remove_all_on_table( /*===================== VALIDATION AND DEBUGGING ====================*/ -/*********************************************************************//** -Prints info of a table lock. */ -UNIV_INTERN -void -lock_table_print( -/*=============*/ - FILE* file, /*!< in: file where to print */ - const lock_t* lock) /*!< in: table type lock */ +/** Pretty-print a table lock. +@param[in,out] file output stream +@param[in] lock table lock +@param[in] now current time */ +static void lock_table_print(FILE* file, const lock_t* lock, time_t now) { ut_ad(lock_mutex_own()); ut_a(lock_get_type_low(lock) == LOCK_TABLE); @@ -6046,30 +6033,22 @@ lock_table_print( } fprintf(file, " lock hold time %lu wait time before grant %lu ", - (ulint)difftime(ut_time(), lock->requested_time), + (ulint)difftime(now, lock->requested_time), lock->wait_time); putc('\n', file); } -/*********************************************************************//** -Prints info of a record lock. */ -UNIV_INTERN -void -lock_rec_print( -/*===========*/ - FILE* file, /*!< in: file where to print */ - const lock_t* lock) /*!< in: record type lock */ +/** Pretty-print a record lock. +@param[in,out] file output stream +@param[in] lock record lock +@param[in] now current time +@param[in,out] mtr mini-transaction */ +static void lock_rec_print(FILE* file, const lock_t* lock, time_t now, + mtr_t* mtr) { - const buf_block_t* block; ulint space; ulint page_no; - ulint i; - mtr_t mtr; - mem_heap_t* heap = NULL; - ulint offsets_[REC_OFFS_NORMAL_SIZE]; - ulint* offsets = offsets_; - rec_offs_init(offsets_); ut_ad(lock_mutex_own()); ut_a(lock_get_type_low(lock) == LOCK_REC); @@ -6114,17 +6093,25 @@ lock_rec_print( fputs(" waiting", file); } - mtr_start(&mtr); - fprintf(file, " lock hold time %lu wait time before grant %lu ", - (ulint)difftime(ut_time(), lock->requested_time), + (ulint)difftime(now, lock->requested_time), lock->wait_time); putc('\n', file); - block = buf_page_try_get(space, page_no, &mtr); + if (!mtr) { + return; + } + + mem_heap_t* heap = NULL; + ulint offsets_[REC_OFFS_NORMAL_SIZE]; + ulint* offsets = offsets_; + rec_offs_init(offsets_); - for (i = 0; i < lock_rec_get_n_bits(lock); ++i) { + mtr_start(mtr); + const buf_block_t* block = buf_page_try_get(space, page_no, mtr); + + for (ulint i = 0; i < lock_rec_get_n_bits(lock); ++i) { if (!lock_rec_get_nth_bit(lock, i)) { continue; @@ -6149,7 +6136,7 @@ lock_rec_print( putc('\n', file); } - mtr_commit(&mtr); + mtr_commit(mtr); if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } @@ -6305,6 +6292,8 @@ lock_print_info_all_transactions( ut_ad(lock_mutex_own()); + const time_t now = time(NULL); + mutex_enter(&trx_sys->mutex); /* First print info on non-active transactions */ @@ -6391,13 +6380,14 @@ loop: fprintf(file, "------- TRX HAS BEEN WAITING %lu SEC" " FOR THIS LOCK TO BE GRANTED:\n", - (ulong) difftime(ut_time(), - trx->lock.wait_started)); + (ulong) difftime(now, trx->lock.wait_started)); if (lock_get_type_low(trx->lock.wait_lock) == LOCK_REC) { - lock_rec_print(file, trx->lock.wait_lock); + lock_rec_print(file, trx->lock.wait_lock, now, + &mtr); } else { - lock_table_print(file, trx->lock.wait_lock); + lock_table_print(file, trx->lock.wait_lock, + now); } fputs("------------------\n", file); @@ -6482,11 +6472,11 @@ loop: } print_rec: - lock_rec_print(file, lock); + lock_rec_print(file, lock, now, &mtr); } else { ut_ad(lock_get_type_low(lock) & LOCK_TABLE); - lock_table_print(file, lock); + lock_table_print(file, lock, now); } load_page_first = TRUE; @@ -6918,10 +6908,10 @@ lock_rec_block_validate( page_no, RW_X_LATCH, NULL, BUF_GET_POSSIBLY_FREED, __FILE__, __LINE__, &mtr); - - buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); - - ut_ad(lock_rec_validate_page(block)); + if (block) { + buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK); + ut_ad(lock_rec_validate_page(block)); + } mtr_commit(&mtr); fil_space_release(space); @@ -7930,7 +7920,8 @@ lock_trx_release_locks( { assert_trx_in_list(trx); - if (trx_state_eq(trx, TRX_STATE_PREPARED)) { + if (trx_state_eq(trx, TRX_STATE_PREPARED) + || trx_state_eq(trx, TRX_STATE_PREPARED_RECOVERED)) { mutex_enter(&trx_sys->mutex); ut_a(trx_sys->n_prepared_trx > 0); trx_sys->n_prepared_trx--; @@ -8000,26 +7991,19 @@ lock_trx_handle_wait( /*=================*/ trx_t* trx) /*!< in/out: trx lock state */ { - dberr_t err; - - lock_mutex_enter(); - - trx_mutex_enter(trx); + ut_ad(lock_mutex_own()); + ut_ad(trx_mutex_own(trx)); if (trx->lock.was_chosen_as_deadlock_victim) { - err = DB_DEADLOCK; - } else if (trx->lock.wait_lock != NULL) { - lock_cancel_waiting_and_release(trx->lock.wait_lock); - err = DB_LOCK_WAIT; - } else { + return DB_DEADLOCK; + } + if (!trx->lock.wait_lock) { /* The lock was probably granted before we got here. */ - err = DB_SUCCESS; + return DB_SUCCESS; } - lock_mutex_exit(); - trx_mutex_exit(trx); - - return(err); + lock_cancel_waiting_and_release(trx->lock.wait_lock); + return DB_LOCK_WAIT; } /*********************************************************************//** |