26 #define LOCK_MODULE_IMPLEMENTATION
32 #include "lock0lock.ic"
33 #include "lock0priv.ic"
55 #define LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK 1000000
59 #define LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK 200
64 #define LOCK_RELEASE_INTERVAL 1000
70 #define LOCK_PAGE_BITMAP_MARGIN 64
306 #define LOCK_STACK_SIZE OS_THREAD_MAX_N
323 static const byte lock_compatibility_matrix[5][5] = {
325 { TRUE, TRUE, TRUE, FALSE, TRUE},
326 { TRUE, TRUE, FALSE, FALSE, TRUE},
327 { TRUE, FALSE, TRUE, FALSE, FALSE},
328 { FALSE, FALSE, FALSE, FALSE, FALSE},
329 { TRUE, TRUE, FALSE, FALSE, FALSE}
341 static const byte lock_strength_matrix[5][5] = {
343 { TRUE, FALSE, FALSE, FALSE, FALSE},
344 { TRUE, TRUE, FALSE, FALSE, FALSE},
345 { TRUE, FALSE, TRUE, FALSE, FALSE},
346 { TRUE, TRUE, TRUE, TRUE, TRUE},
347 { FALSE, FALSE, FALSE, FALSE, TRUE}
382 static const ulint lock_types = UT_ARR_SIZE(lock_compatibility_matrix);
384 #ifdef UNIV_PFS_MUTEX
386 UNIV_INTERN mysql_pfs_key_t lock_sys_mutex_key;
388 UNIV_INTERN mysql_pfs_key_t lock_sys_wait_mutex_key;
392 UNIV_INTERN ibool lock_print_waits = FALSE;
407 lock_rec_validate_page(
410 __attribute__((nonnull, warn_unused_result));
420 static FILE* lock_latest_err_file;
432 lock_deadlock_check_and_resolve(
457 b = ((
const byte*) &lock[1]) + (i / 8);
459 return(1 & *b >> (i % 8));
475 fputs(
" InnoDB: Error: transaction id associated with record\n",
478 fputs(
"InnoDB: in ", stderr);
481 "InnoDB: is " TRX_ID_FMT " which is higher than the"
483 "InnoDB: The table is corrupt. You have to do"
484 " dump + drop + reimport.\n",
494 static __attribute__((nonnull, warn_unused_result))
497 lock_check_trx_id_sanity(
507 ut_ad(rec_offs_validate(rec, index, offsets));
510 is_ok = trx_id < max_trx_id;
512 if (UNIV_UNLIKELY(!is_ok)) {
514 rec, index, offsets, max_trx_id);
538 ut_ad(rec_offs_validate(rec, index, offsets));
582 return(max_trx_id < view->up_limit_id);
595 lock_sys_sz =
sizeof(*lock_sys)
601 mem_zalloc(
sizeof(*lock_stack) * LOCK_STACK_SIZE));
603 void* ptr = &lock_sys[1];
605 lock_sys->waiting_threads =
static_cast<srv_slot_t*
>(ptr);
607 lock_sys->last_slot = lock_sys->waiting_threads;
609 mutex_create(lock_sys_mutex_key, &lock_sys->mutex, SYNC_LOCK_SYS);
611 mutex_create(lock_sys_wait_mutex_key,
612 &lock_sys->wait_mutex, SYNC_LOCK_WAIT_SYS);
616 lock_sys->rec_hash = hash_create(n_cells);
620 ut_a(lock_latest_err_file);
631 if (lock_latest_err_file != NULL) {
632 fclose(lock_latest_err_file);
633 lock_latest_err_file = NULL;
638 mutex_free(&lock_sys->mutex);
639 mutex_free(&lock_sys->wait_mutex);
656 return((ulint)
sizeof(
lock_t));
700 enum lock_mode*
mode)
722 enum lock_mode lock_mode;
728 if (dest == tab_lock->
table) {
733 src = tab_lock->
table;
741 }
else if (src != tab_lock->
table) {
751 if (lock_mode == LOCK_IX || lock_mode == LOCK_IS) {
752 if (*mode != LOCK_NONE && *mode != lock_mode) {
795 if (lock->
trx != trx) {
921 enum lock_mode mode1,
922 enum lock_mode mode2)
924 ut_ad((ulint) mode1 < lock_types);
925 ut_ad((ulint) mode2 < lock_types);
927 return(lock_strength_matrix[mode1][mode2]);
937 enum lock_mode mode1,
938 enum lock_mode mode2)
940 ut_ad((ulint) mode1 < lock_types);
941 ut_ad((ulint) mode2 < lock_types);
943 return(lock_compatibility_matrix[mode1][mode2]);
962 ibool lock_is_on_supremum)
970 if (trx != lock2->
trx
978 if ((lock_is_on_supremum || (type_mode &
LOCK_GAP))
989 if (!(type_mode & LOCK_INSERT_INTENTION)
998 if ((type_mode & LOCK_GAP)
1042 ut_ad(lock1 && lock2);
1044 if (lock1->
trx != lock2->
trx
1093 ut_ad(i < lock->un_member.rec_lock.n_bits);
1098 ((byte*) &lock[1])[byte_index] |= 1 << bit_index;
1122 return(ULINT_UNDEFINED);
1140 ut_ad(i < lock->un_member.rec_lock.n_bits);
1145 ((byte*) &lock[1])[byte_index] &= ~(1 << bit_index);
1211 for (lock = static_cast<lock_t*>(
1265 for (lock = static_cast<lock_t*>(
1343 lock_rec_bitmap_reset(
1358 memset(&lock[1], 0, n_bytes);
1377 return(static_cast<lock_t*>(
mem_heap_dup(heap, lock, size)));
1393 lock_t* found_lock = NULL;
1407 if (lock == in_lock) {
1431 enum lock_mode
mode)
1443 enum lock_mode lock_mode;
1445 lock = *
static_cast<const lock_t**
>(
1494 || (precise_mode & LOCK_MODE_MASK) == LOCK_X);
1501 if (lock->
trx == trx
1506 static_cast<enum lock_mode>(
1507 precise_mode & LOCK_MODE_MASK))
1510 || heap_no == PAGE_HEAP_NO_SUPREMUM)
1513 || heap_no == PAGE_HEAP_NO_SUPREMUM)) {
1528 lock_rec_other_has_expl_req(
1530 enum lock_mode
mode,
1547 ut_ad(mode == LOCK_X || mode == LOCK_S);
1555 if (lock->
trx != trx
1558 || heap_no == PAGE_HEAP_NO_SUPREMUM))
1576 lock_rec_other_has_conflicting(
1578 enum lock_mode mode,
1592 is_supremum = (heap_no == PAGE_HEAP_NO_SUPREMUM);
1626 if (lock->
trx == trx
1646 lock_sec_rec_some_has_impl(
1660 ut_ad(rec_offs_validate(rec, index, offsets));
1674 }
else if (!lock_check_trx_id_sanity(max_trx_id, rec, index, offsets)) {
1703 ulint n_records = 0;
1715 for (n_bit = 0; n_bit < n_bits; n_bit++) {
1744 ibool caller_owns_trx_mutex)
1765 page = block->
frame;
1773 if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
1781 n_bytes = 1 + n_bits / 8;
1783 lock =
static_cast<lock_t*
>(
1798 lock_rec_bitmap_reset(lock);
1810 if (!caller_owns_trx_mutex) {
1822 if (!caller_owns_trx_mutex) {
1841 lock_rec_enqueue_waiting(
1878 return(DB_QUE_THR_SUSPENDED);
1887 fputs(
" InnoDB: Error: a record lock wait happens"
1888 " in a dictionary operation!\n"
1889 "InnoDB: ", stderr);
1892 "InnoDB: Submit a detailed bug report"
1893 " to http://bugs.mysql.com\n",
1902 lock = lock_rec_create(
1923 victim_trx_id = lock_deadlock_check_and_resolve(lock, trx);
1927 if (victim_trx_id != 0) {
1929 ut_ad(victim_trx_id == trx->
id);
1934 return(DB_DEADLOCK);
1953 if (lock_print_waits) {
1954 fprintf(stderr,
"Lock wait for trx " TRX_ID_FMT " in index ",
1962 return(DB_LOCK_WAIT);
1975 lock_rec_add_to_queue(
1985 ibool caller_owns_trx_mutex)
2009 = lock_rec_other_has_expl_req(mode, 0,
LOCK_WAIT,
2010 block, heap_no, trx);
2022 if (UNIV_UNLIKELY(heap_no == PAGE_HEAP_NO_SUPREMUM)) {
2040 goto somebody_waits;
2044 if (UNIV_LIKELY(!(type_mode &
LOCK_WAIT))) {
2051 type_mode, heap_no, first_lock, trx);
2062 return(lock_rec_create(
2063 type_mode, block, heap_no, index, trx,
2064 caller_owns_trx_mutex));
2107 ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2109 ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
2111 ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
2112 || (LOCK_MODE_MASK & mode) == LOCK_X);
2114 || mode - (LOCK_MODE_MASK & mode) == 0
2118 DBUG_EXECUTE_IF(
"innodb_report_deadlock",
return(
LOCK_REC_FAIL););
2127 lock = lock_rec_create(
2128 mode, block, heap_no, index, trx, FALSE);
2137 || lock->type_mode != (mode |
LOCK_REC)
2186 ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2188 ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
2190 ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
2191 || (LOCK_MODE_MASK & mode) == LOCK_X);
2193 || mode - (LOCK_MODE_MASK & mode) == 0
2197 DBUG_EXECUTE_IF(
"innodb_report_deadlock",
return(DB_DEADLOCK););
2214 goto enqueue_waiting;
2226 }
else if (lock_rec_other_has_conflicting(
2227 static_cast<enum lock_mode>(mode),
2228 block, heap_no, trx)) {
2235 ut_ad(lock == NULL);
2237 err = lock_rec_enqueue_waiting(
2238 mode, block, heap_no, lock, index, thr);
2244 lock_rec_add_to_queue(
2245 LOCK_REC | mode, block, heap_no, index, trx, TRUE);
2281 ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2283 ut_ad((LOCK_MODE_MASK & mode) != LOCK_X
2285 ut_ad((LOCK_MODE_MASK & mode) == LOCK_S
2286 || (LOCK_MODE_MASK & mode) == LOCK_X);
2289 || mode - (LOCK_MODE_MASK & mode) == 0);
2300 return(lock_rec_lock_slow(impl, mode, block,
2301 heap_no, index, thr));
2313 lock_rec_has_to_wait_in_queue(
2332 bit_offset = heap_no / 8;
2333 bit_mask = 1 << (heap_no % 8);
2339 const byte* p = (
const byte*) &lock[1];
2342 && (p[bit_offset] & bit_mask)
2372 "InnoDB: Error: trx already had"
2373 " an AUTO-INC lock!\n");
2377 ib_vector_push(lock->
trx->autoinc_locks, &lock);
2382 if (lock_print_waits) {
2383 fprintf(stderr,
"Lock wait for trx " TRX_ID_FMT " ends\n",
2449 lock_rec_dequeue_from_page(
2467 trx_lock = &in_lock->
trx->
lock;
2480 MONITOR_DEC(MONITOR_NUM_RECLOCK);
2491 && !lock_rec_has_to_wait_in_queue(lock)) {
2517 trx_lock = &in_lock->
trx->
lock;
2530 MONITOR_DEC(MONITOR_NUM_RECLOCK);
2539 lock_rec_free_all_from_discard_page(
2555 while (lock != NULL) {
2561 lock_rec_discard(lock);
2574 lock_rec_reset_and_release_wait(
2589 lock_rec_cancel(lock);
2607 lock_rec_inherit_to_gap(
2637 <= TRX_ISO_READ_COMMITTED)
2640 lock_rec_add_to_queue(
2642 heir_block, heir_heap_no, lock->
index,
2654 lock_rec_inherit_to_gap_if_gap_lock(
2673 && (heap_no == PAGE_HEAP_NO_SUPREMUM
2676 lock_rec_add_to_queue(
2678 block, heir_heap_no, lock->
index,
2697 ulint receiver_heap_no,
2701 ulint donator_heap_no)
2714 const ulint type_mode = lock->
type_mode;
2718 if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
2725 lock_rec_add_to_queue(
2726 type_mode, receiver, receiver_heap_no,
2748 UT_LIST_BASE_NODE_T(
lock_t) old_locks;
2772 lock_t* old_lock = lock_rec_copy(lock, heap);
2777 lock_rec_bitmap_reset(lock);
2785 }
while (lock != NULL);
2807 ut_ad(comp || !memcmp(page_cur_get_rec(&cur1),
2808 page_cur_get_rec(&cur2),
2812 if (UNIV_LIKELY(comp)) {
2814 page_cur_get_rec(&cur2));
2816 page_cur_get_rec(&cur1));
2819 page_cur_get_rec(&cur2));
2821 page_cur_get_rec(&cur1));
2833 lock_rec_add_to_queue(
2846 (new_heap_no == PAGE_HEAP_NO_SUPREMUM)) {
2848 ut_ad(old_heap_no == PAGE_HEAP_NO_SUPREMUM);
2861 if (UNIV_UNLIKELY(i != ULINT_UNDEFINED)) {
2863 "lock_move_reorganize_page():"
2864 " %lu not moved in %p\n",
2865 (ulong) i, (
void*) lock);
2876 #ifdef UNIV_DEBUG_LOCK_VALIDATE
2877 ut_ad(lock_rec_validate_page(block));
2908 const ulint type_mode = lock->
type_mode;
2927 page_cur_get_rec(&cur1));
2930 page_cur_get_rec(&cur1));
2931 ut_ad(!memcmp(page_cur_get_rec(&cur1),
2932 page_cur_get_rec(&cur2),
2934 page_cur_get_rec(&cur2))));
2940 if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
2946 page_cur_get_rec(&cur2));
2949 page_cur_get_rec(&cur2));
2952 lock_rec_add_to_queue(
2953 type_mode, new_block, heap_no,
2964 #ifdef UNIV_DEBUG_LOCK_VALIDATE
2965 ut_ad(lock_rec_validate_page(block));
2966 ut_ad(lock_rec_validate_page(new_block));
2983 const rec_t* old_end)
3001 const ulint type_mode = lock->
type_mode;
3012 while (page_cur_get_rec(&cur1) != rec) {
3017 page_cur_get_rec(&cur1));
3020 page_cur_get_rec(&cur1));
3021 ut_ad(!memcmp(page_cur_get_rec(&cur1),
3022 page_cur_get_rec(&cur2),
3031 if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
3037 page_cur_get_rec(&cur2));
3040 page_cur_get_rec(&cur2));
3043 lock_rec_add_to_queue(
3044 type_mode, new_block, heap_no,
3056 for (i = PAGE_HEAP_NO_USER_LOW;
3062 "lock_move_rec_list_start():"
3063 " %lu not moved in %p\n",
3064 (ulong) i, (
void*) lock);
3074 #ifdef UNIV_DEBUG_LOCK_VALIDATE
3075 ut_ad(lock_rec_validate_page(block));
3095 lock_rec_move(right_block, left_block,
3096 PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
3101 lock_rec_inherit_to_gap(left_block, right_block,
3102 PAGE_HEAP_NO_SUPREMUM, heap_no);
3115 const rec_t* orig_succ,
3129 lock_rec_inherit_to_gap(right_block, left_block,
3131 PAGE_HEAP_NO_SUPREMUM);
3136 lock_rec_reset_and_release_wait(left_block,
3137 PAGE_HEAP_NO_SUPREMUM);
3139 lock_rec_free_all_from_discard_page(left_block);
3163 lock_rec_move(block, root,
3164 PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
3185 lock_rec_move(new_block, block,
3186 PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
3187 lock_rec_free_all_from_discard_page(block);
3208 lock_rec_inherit_to_gap(left_block, right_block,
3209 PAGE_HEAP_NO_SUPREMUM, heap_no);
3222 const rec_t* orig_pred,
3228 const rec_t* left_next_rec;
3241 lock_rec_inherit_to_gap(left_block, left_block,
3243 PAGE_HEAP_NO_SUPREMUM);
3248 lock_rec_reset_and_release_wait(left_block,
3249 PAGE_HEAP_NO_SUPREMUM);
3255 lock_rec_move(left_block, right_block,
3256 PAGE_HEAP_NO_SUPREMUM, PAGE_HEAP_NO_SUPREMUM);
3258 lock_rec_free_all_from_discard_page(right_block);
3283 lock_rec_reset_and_release_wait(heir_block, heir_heap_no);
3285 lock_rec_inherit_to_gap(heir_block, block, heir_heap_no, heap_no);
3321 rec = page + PAGE_NEW_INFIMUM;
3326 lock_rec_inherit_to_gap(heir_block, block,
3327 heir_heap_no, heap_no);
3329 lock_rec_reset_and_release_wait(block, heap_no);
3332 }
while (heap_no != PAGE_HEAP_NO_SUPREMUM);
3334 rec = page + PAGE_OLD_INFIMUM;
3339 lock_rec_inherit_to_gap(heir_block, block,
3340 heir_heap_no, heap_no);
3342 lock_rec_reset_and_release_wait(block, heap_no);
3345 }
while (heap_no != PAGE_HEAP_NO_SUPREMUM);
3348 lock_rec_free_all_from_discard_page(block);
3362 ulint receiver_heap_no;
3363 ulint donator_heap_no;
3380 lock_rec_inherit_to_gap_if_gap_lock(
3381 block, receiver_heap_no, donator_heap_no);
3415 lock_rec_inherit_to_gap(block, block, next_heap_no, heap_no);
3419 lock_rec_reset_and_release_wait(block, heap_no);
3448 lock_rec_move(block, block, PAGE_HEAP_NO_INFIMUM, heap_no);
3473 lock_rec_move(block, donator, heap_no, PAGE_HEAP_NO_INFIMUM);
3492 rewind(lock_latest_err_file);
3497 fprintf(stderr,
"InnoDB: transactions deadlock detected, "
3498 "dumping detailed information.\n");
3512 fputs(msg, lock_latest_err_file);
3527 ulint max_query_len)
3540 n_rec_locks, n_trx_locks, heap_size);
3544 n_rec_locks, n_trx_locks, heap_size);
3577 static ib_uint64_t lock_mark_counter = 0;
3580 #define lock_deadlock_too_deep(c) \
3581 (c->depth > LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK \
3582 || c->cost > LOCK_MAX_N_STEPS_IN_DEADLOCK_CHECK)
3602 ut_ad(heap_no != ULINT_UNDEFINED);
3605 ut_ad(heap_no == ULINT_UNDEFINED);
3610 }
while (lock != NULL
3628 lock_get_first_lock(
3644 ut_ad(*heap_no != ULINT_UNDEFINED);
3656 *heap_no = ULINT_UNDEFINED;
3673 lock_deadlock_notify(
3705 "*** (2) WAITING FOR THIS LOCK TO BE GRANTED:\n");
3711 if (lock_print_waits) {
3712 fputs(
"Deadlock detected\n", stderr);
3722 lock_deadlock_select_victim(
3753 return(&lock_stack[--ctx->
depth]);
3771 if (LOCK_STACK_SIZE > ctx->
depth) {
3774 stack = &lock_stack[ctx->
depth++];
3792 lock_deadlock_search(
3808 lock = lock_get_first_lock(ctx, &heap_no);
3816 while (ctx->
depth > 0 && lock == NULL) {
3821 stack = lock_deadlock_pop(ctx);
3827 lock = lock_get_next_lock(ctx, lock, heap_no);
3843 ut_ad(lock_mark_counter > 0);
3850 lock = lock_get_next_lock(ctx, lock, heap_no);
3852 }
else if (lock->
trx == ctx->
start) {
3856 lock_deadlock_notify(ctx, lock);
3858 return(lock_deadlock_select_victim(ctx)->
id);
3877 if (!lock_deadlock_push(ctx, lock, heap_no)) {
3888 lock = lock_get_first_lock(ctx, &heap_no);
3891 lock = lock_get_next_lock(ctx, lock, heap_no);
3895 lock = lock_get_next_lock(ctx, lock, heap_no);
3909 lock_deadlock_joining_trx_print(
3923 "TOO DEEP OR LONG SEARCH IN THE LOCK TABLE"
3924 " WAITS-FOR GRAPH, WE WILL ROLL BACK"
3925 " FOLLOWING TRANSACTION \n\n"
3926 "*** TRANSACTION:\n");
3939 lock_deadlock_trx_rollback(
3970 lock_deadlock_check_and_resolve(
3978 ut_ad(lock != NULL);
3994 victim_trx_id = lock_deadlock_search(&ctx);
4000 ut_a(victim_trx_id == trx->
id);
4003 lock_deadlock_joining_trx_print(trx, lock);
4008 }
else if (victim_trx_id != 0 && victim_trx_id != trx->
id) {
4011 lock_deadlock_trx_rollback(&ctx);
4013 lock_deadlock_found = TRUE;
4018 }
while (victim_trx_id != 0 && victim_trx_id != trx->
id);
4021 if (victim_trx_id != 0) {
4022 ut_a(victim_trx_id == trx->
id);
4026 lock_deadlock_found = TRUE;
4029 return(victim_trx_id);
4050 ut_ad(table && trx);
4059 if ((type_mode & LOCK_MODE_MASK) == LOCK_AUTO_INC) {
4066 if (type_mode == LOCK_AUTO_INC) {
4072 ib_vector_push(trx->autoinc_locks, &lock);
4074 lock =
static_cast<lock_t*
>(
4088 if (UNIV_UNLIKELY(type_mode & LOCK_WAIT)) {
4118 ib_vector_pop(trx->autoinc_locks);
4137 lint
i = ib_vector_size(trx->autoinc_locks) - 1;
4149 autoinc_lock = *
static_cast<lock_t**
>(
4154 if (autoinc_lock == lock) {
4158 ut_a(autoinc_lock != NULL);
4163 autoinc_lock = *
static_cast<lock_t**
>(
4166 if (UNIV_LIKELY(autoinc_lock == lock)) {
4167 void* null_var = NULL;
4229 MONITOR_DEC(MONITOR_NUM_TABLELOCK);
4241 lock_table_enqueue_waiting(
4265 return(DB_QUE_THR_SUSPENDED);
4274 fputs(
" InnoDB: Error: a table lock wait happens"
4275 " in a dictionary operation!\n"
4276 "InnoDB: Table name ", stderr);
4279 "InnoDB: Submit a detailed bug report"
4280 " to http://bugs.mysql.com\n",
4299 victim_trx_id = lock_deadlock_check_and_resolve(lock, trx);
4303 if (victim_trx_id != 0) {
4304 ut_ad(victim_trx_id == trx->
id);
4311 return(DB_DEADLOCK);
4328 return(DB_LOCK_WAIT);
4345 enum lock_mode mode)
4355 if (lock->
trx != trx
4378 enum lock_mode mode,
4385 ut_ad(table && thr);
4412 trx, LOCK_WAIT, table, mode);
4419 if (wait_for != NULL) {
4420 err = lock_table_enqueue_waiting(mode | flags, table, thr);
4424 ut_a(!flags || mode == LOCK_S || mode == LOCK_X);
4457 trx, LOCK_WAIT, table, LOCK_IX));
4470 lock_table_has_to_wait_in_queue(
4524 && !lock_table_has_to_wait_in_queue(lock)) {
4547 enum lock_mode lock_mode)
4571 for (lock = first_lock; lock != NULL;
4584 " InnoDB: Error: unlock row could not"
4585 " find a %lu mode lock on the record\n",
4588 fprintf(stderr,
" InnoDB: current statement: %.*s\n",
4589 (
int) stmt_len, stmt);
4599 for (lock = first_lock; lock != NULL;
4602 && !lock_rec_has_to_wait_in_queue(lock)) {
4650 lock_rec_dequeue_from_page(lock);
4661 if (table->
id < DICT_HDR_FIRST_ID
4679 lock_table_dequeue(lock);
4682 if (count == LOCK_RELEASE_INTERVAL) {
4710 #define IS_LOCK_S_OR_X(lock) \
4711 (lock_get_mode(lock) == LOCK_S \
4712 || lock_get_mode(lock) == LOCK_X)
4718 lock_trx_table_locks_remove(
4720 const lock_t* lock_to_remove)
4737 lock = *
static_cast<lock_t**
>(
4748 if (lock == lock_to_remove) {
4749 void* null_var = NULL;
4775 lock_remove_all_on_table_for_trx(
4779 ibool remove_also_table_sx_locks)
4797 lock_rec_discard(lock);
4800 && (remove_also_table_sx_locks
4801 || !IS_LOCK_S_OR_X(lock))) {
4805 lock_trx_table_locks_remove(lock);
4817 lock_remove_recovered_trx_record_locks(
4824 ulint n_recovered_trx = 0;
4826 ut_a(table != NULL);
4865 lock_trx_table_locks_remove(lock);
4871 lock_rec_discard(lock);
4881 return(n_recovered_trx);
4895 ibool remove_also_table_sx_locks)
4913 if (remove_also_table_sx_locks
4915 && IS_LOCK_S_OR_X(lock))) {
4920 lock_remove_all_on_table_for_trx(
4921 table, lock->
trx, remove_also_table_sx_locks);
4923 if (prev_lock == NULL) {
4927 un_member.tab_lock.locks, lock);
4933 prev_lock) != lock) {
4938 un_member.tab_lock.locks, prev_lock);
4942 un_member.tab_lock.locks, lock);
4951 if (!lock_sys->rollback_complete
4952 && lock_remove_recovered_trx_record_locks(table) == 0) {
4954 lock_sys->rollback_complete = TRUE;
4974 fputs(
"TABLE LOCK table ", file);
4980 fputs(
" lock mode S", file);
4982 fputs(
" lock mode X", file);
4984 fputs(
" lock mode IS", file);
4986 fputs(
" lock mode IX", file);
4988 fputs(
" lock mode AUTO-INC", file);
4990 fprintf(file,
" unknown lock mode %lu",
4995 fputs(
" waiting", file);
5016 ulint offsets_[REC_OFFS_NORMAL_SIZE];
5017 ulint* offsets = offsets_;
5018 rec_offs_init(offsets_);
5026 fprintf(file,
"RECORD LOCKS space id %lu page no %lu n bits %lu ",
5027 (ulong) space, (ulong) page_no,
5033 fputs(
" lock mode S", file);
5035 fputs(
" lock_mode X", file);
5041 fputs(
" locks gap before rec", file);
5045 fputs(
" locks rec but not gap", file);
5049 fputs(
" insert intention", file);
5053 fputs(
" waiting", file);
5068 fprintf(file,
"Record lock, heap no %lu", (ulong) i);
5074 buf_block_get_frame(block), i);
5076 offsets = rec_get_offsets(
5077 rec, lock->
index, offsets,
5078 ULINT_UNDEFINED, &heap);
5088 if (UNIV_LIKELY_NULL(heap)) {
5097 #define PRINT_NUM_OF_LOCK_STRUCTS
5100 #ifdef PRINT_NUM_OF_LOCK_STRUCTS
5106 lock_get_n_rec_locks(
void)
5117 for (lock = static_cast<const lock_t*>(
5120 lock =
static_cast<const lock_t*
>(
5148 fputs(
"FAIL TO OBTAIN LOCK MUTEX, "
5149 "SKIP LOCK INFO PRINTING\n", file);
5153 if (lock_deadlock_found) {
5154 fputs(
"------------------------\n"
5155 "LATEST DETECTED DEADLOCK\n"
5156 "------------------------\n", file);
5163 fputs(
"------------\n"
5165 "------------\n", file);
5167 fprintf(file,
"Trx id counter " TRX_ID_FMT "\n",
5187 fprintf(file,
"disabled");
5191 fprintf(file,
"running");
5194 fprintf(file,
" but idle");
5199 fprintf(file,
"stopped");
5203 fprintf(file,
"\n");
5206 "History list length %lu\n",
5209 #ifdef PRINT_NUM_OF_LOCK_STRUCTS
5211 "Total number of lock structs in row lock hash table %lu\n",
5212 (ulong) lock_get_n_rec_locks());
5228 ibool load_page_first = TRUE;
5236 fprintf(file,
"LIST OF TRANSACTIONS FOR EACH SESSION:\n");
5252 ut_ad(trx->in_mysql_trx_list);
5270 trx && (i < nth_trx);
5292 ut_ad(lock_validate());
5299 if (nth_lock == 0) {
5304 if (trx->read_view) {
5306 "Trx read view will not see trx with"
5309 trx->read_view->low_limit_id,
5310 trx->read_view->up_limit_id);
5316 "------- TRX HAS BEEN WAITING %lu SEC"
5317 " FOR THIS LOCK TO BE GRANTED:\n",
5319 trx->lock.wait_started));
5327 fputs(
"------------------\n", file);
5331 if (!srv_print_innodb_lock_monitor) {
5343 while (lock && (i < nth_lock)) {
5356 if (load_page_first) {
5361 if (UNIV_UNLIKELY(zip_size == ULINT_UNDEFINED)) {
5369 fprintf(file,
"RECORD LOCKS on"
5370 " non-existing space %lu\n",
5381 space, zip_size, page_no, &mtr);
5385 load_page_first = FALSE;
5402 load_page_first = TRUE;
5406 if (nth_lock >= 10) {
5407 fputs(
"10 LOCKS PRINTED FOR THIS TRX:"
5408 " SUPPRESSING FURTHER PRINTS\n",
5424 lock_trx_table_locks_find(
5430 ibool found = FALSE;
5437 lock = *
static_cast<const lock_t**
>(
5442 }
else if (lock == find_lock) {
5463 lock_table_queue_validate(
5480 ut_ad(trx_assert_started(lock->
trx));
5485 lock->
trx, 0, table,
5489 ut_a(lock_table_has_to_wait_in_queue(lock));
5492 ut_a(lock_trx_table_locks_find(lock->
trx, lock));
5503 lock_rec_queue_validate(
5505 ibool locked_lock_trx_sys,
5512 const ulint* offsets)
5514 const trx_t* impl_trx;
5520 ut_ad(rec_offs_validate(rec, index, offsets));
5528 if (!locked_lock_trx_sys) {
5539 ut_a(trx_in_trx_list(lock->
trx));
5542 ut_a(lock_rec_has_to_wait_in_queue(lock));
5567 if (impl_trx != NULL
5568 && lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
5569 block, heap_no, impl_trx)) {
5572 block, heap_no, impl_trx));
5580 ut_a(trx_in_trx_list(lock->
trx));
5588 enum lock_mode
mode;
5595 ut_a(!lock_rec_other_has_expl_req(
5596 mode, 0, 0, block, heap_no, lock->
trx));
5600 ut_a(lock_rec_has_to_wait_in_queue(lock));
5605 if (!locked_lock_trx_sys) {
5618 lock_rec_validate_page(
5628 ulint offsets_[REC_OFFS_NORMAL_SIZE];
5629 ulint* offsets = offsets_;
5630 rec_offs_init(offsets_);
5644 #if defined UNIV_DEBUG_FILE_ACCESSES || defined UNIV_DEBUG
5645 ut_a(!block->
page.file_page_was_freed);
5648 for (i = 0; i < nth_lock; i++) {
5657 ut_a(trx_in_trx_list(lock->
trx));
5659 # ifdef UNIV_SYNC_DEBUG
5664 if (!sync_thread_levels_contains(SYNC_FSP))
5672 offsets = rec_get_offsets(rec, lock->
index, offsets,
5673 ULINT_UNDEFINED, &heap);
5676 "Validating %u %u\n",
5684 lock_rec_queue_validate(
5685 TRUE, block, rec, lock->
index, offsets);
5702 if (UNIV_LIKELY_NULL(heap)) {
5713 lock_validate_table_locks(
5715 const trx_list_t* trx_list)
5740 lock_table_queue_validate(
5752 static __attribute__((nonnull, warn_unused_result))
5764 for (
const lock_t* lock = static_cast<const lock_t*>(
5767 lock = static_cast<const lock_t*>(
HASH_GET_NEXT(hash, lock))) {
5769 ib_uint64_t current;
5771 ut_a(trx_in_trx_list(lock->
trx));
5778 if (current > *limit) {
5779 *limit = current + 1;
5791 lock_rec_block_validate(
5810 page_no, RW_X_LATCH, NULL,
5812 __FILE__, __LINE__, &mtr);
5814 buf_block_dbg_add_level(block, SYNC_NO_ORDER_CHECK);
5816 ut_ad(lock_rec_validate_page(block));
5831 typedef std::pair<ulint, ulint> page_addr_t;
5832 typedef std::set<page_addr_t> page_addr_set;
5833 page_addr_set pages;
5847 ib_uint64_t limit = 0;
5849 while ((lock = lock_rec_validate(i, &limit)) != 0) {
5854 pages.insert(std::make_pair(space, page_no));
5861 for (page_addr_set::const_iterator it = pages.begin();
5864 lock_rec_block_validate((*it).first, (*it).second);
5895 const rec_t* next_rec;
5899 ulint next_rec_heap_no;
5927 if (UNIV_LIKELY(lock == NULL)) {
5956 if (lock_rec_other_has_conflicting(
5957 static_cast<enum lock_mode>(
5959 block, next_rec_heap_no, trx)) {
5964 err = lock_rec_enqueue_waiting(
5966 block, next_rec_heap_no, NULL, index, thr);
5995 ulint offsets_[REC_OFFS_NORMAL_SIZE];
5997 rec_offs_init(offsets_);
5999 offsets = rec_get_offsets(next_rec, index, offsets_,
6000 ULINT_UNDEFINED, &heap);
6002 ut_ad(lock_rec_queue_validate(
6003 FALSE, block, next_rec, index, offsets));
6005 if (UNIV_LIKELY_NULL(heap)) {
6019 lock_rec_convert_impl_to_expl(
6024 const ulint* offsets)
6030 ut_ad(rec_offs_validate(rec, index, offsets));
6040 trx_id = lock_sec_rec_some_has_impl(rec, index, offsets);
6060 if (impl_trx != NULL
6062 heap_no, impl_trx)) {
6063 ulint type_mode = (
LOCK_REC | LOCK_X
6071 && lock_rec_other_has_conflicting(
6072 static_cast<enum lock_mode>
6074 heap_no, impl_trx)) {
6076 type_mode |= (LOCK_WAIT
6080 lock_rec_add_to_queue(
6081 type_mode, block, heap_no, index,
6107 const ulint* offsets,
6113 ut_ad(rec_offs_validate(rec, index, offsets));
6129 lock_rec_convert_impl_to_expl(block, rec, index, offsets);
6136 block, heap_no, index, thr);
6142 ut_ad(lock_rec_queue_validate(FALSE, block, rec, index, offsets));
6196 block, heap_no, index, thr);
6205 ulint offsets_[REC_OFFS_NORMAL_SIZE];
6207 rec_offs_init(offsets_);
6209 offsets = rec_get_offsets(rec, index, offsets_,
6210 ULINT_UNDEFINED, &heap);
6212 ut_ad(lock_rec_queue_validate(
6213 FALSE, block, rec, index, offsets));
6215 if (UNIV_LIKELY_NULL(heap)) {
6252 const ulint* offsets,
6253 enum lock_mode mode,
6269 ut_ad(rec_offs_validate(rec, index, offsets));
6270 ut_ad(mode == LOCK_X || mode == LOCK_S);
6287 lock_rec_convert_impl_to_expl(block, rec, index, offsets);
6292 ut_ad(mode != LOCK_X
6294 ut_ad(mode != LOCK_S
6297 err = lock_rec_lock(FALSE, mode | gap_mode,
6298 block, heap_no, index, thr);
6304 ut_ad(lock_rec_queue_validate(FALSE, block, rec, index, offsets));
6330 const ulint* offsets,
6331 enum lock_mode mode,
6348 ut_ad(rec_offs_validate(rec, index, offsets));
6357 if (UNIV_LIKELY(heap_no != PAGE_HEAP_NO_SUPREMUM)) {
6359 lock_rec_convert_impl_to_expl(block, rec, index, offsets);
6364 ut_ad(mode != LOCK_X
6366 ut_ad(mode != LOCK_S
6369 err = lock_rec_lock(FALSE, mode | gap_mode,
6370 block, heap_no, index, thr);
6376 ut_ad(lock_rec_queue_validate(FALSE, block, rec, index, offsets));
6402 enum lock_mode mode,
6412 ulint offsets_[REC_OFFS_NORMAL_SIZE];
6413 ulint* offsets = offsets_;
6415 rec_offs_init(offsets_);
6417 offsets = rec_get_offsets(rec, index, offsets,
6418 ULINT_UNDEFINED, &tmp_heap);
6420 offsets, mode, gap_mode, thr);
6447 last = ib_vector_size(autoinc_locks) - 1;
6457 lock_table_dequeue(lock);
6460 lock_trx_table_locks_remove(lock);
6468 lock_trx_holds_autoinc_locks(
6472 ut_a(trx->autoinc_locks != NULL);
6481 lock_release_autoinc_locks(
6490 ut_a(trx->autoinc_locks != NULL);
6528 return(lock->
trx->
id);
6650 return(table->
name);
6666 return(lock->
index);
6733 lock_rec_dequeue_from_page(lock);
6737 if (lock->
trx->autoinc_locks != NULL) {
6739 lock_release_autoinc_locks(lock->
trx);
6742 lock_table_dequeue(lock);
6782 if (lock_trx_holds_autoinc_locks(trx)) {
6785 lock_release_autoinc_locks(trx);
6836 trx->
state = TRX_STATE_COMMITTED_IN_MEMORY;
6901 ulint n_table_locks;
6909 return(n_table_locks);
6918 lock_table_locks_lookup(
6924 const trx_list_t* trx_list)
6928 ut_a(table != NULL);
7006 lock_trx_has_sys_table_locks(
7011 const lock_t* strongest_lock = 0;
7012 lock_mode strongest = LOCK_NONE;
7020 lock = *
static_cast<const lock_t**
>(
7027 ut_ad(strongest != LOCK_NONE);
7028 strongest_lock = lock;
7033 if (strongest == LOCK_NONE) {
7038 for (; i >= 0; --
i) {
7041 lock = *
static_cast<const lock_t**
>(
7058 strongest_lock = lock;
7064 return(strongest_lock);
7072 lock_trx_has_rec_x_lock(
7079 ut_ad(heap_no > PAGE_HEAP_NO_SUPREMUM);
7084 block, heap_no, trx));