1
1
/*****************************************************************************
3
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
5
5
This program is free software; you can redistribute it and/or modify it under
6
6
the terms of the GNU General Public License as published by the Free Software
374
374
/* Flags for recursive deadlock search */
375
375
#define LOCK_VICTIM_IS_START 1
376
376
#define LOCK_VICTIM_IS_OTHER 2
377
#define LOCK_EXCEED_MAX_DEPTH 3
379
378
/********************************************************************//**
380
379
Checks if a lock request results in a deadlock.
393
392
deadlock and we chose 'start' as the victim, LOCK_VICTIM_IS_OTHER if a
394
393
deadlock was found and we chose some other trx as a victim: we must do
395
394
the search again in this last case because there may be another
397
LOCK_EXCEED_MAX_DEPTH if the lock search exceeds max steps or max depth. */
400
398
lock_deadlock_recursive(
401
399
/*====================*/
402
400
trx_t* start, /*!< in: recursion starting point */
403
401
trx_t* trx, /*!< in: a transaction waiting for a lock */
404
lock_t* wait_lock, /*!< in: lock that is waiting to be granted */
402
lock_t* wait_lock, /*!< in: the lock trx is waiting to be granted */
405
403
ulint* cost, /*!< in/out: number of calculation steps thus
406
404
far: if this exceeds LOCK_MAX_N_STEPS_...
407
we return LOCK_EXCEED_MAX_DEPTH */
405
we return LOCK_VICTIM_IS_START */
408
406
ulint depth); /*!< in: recursion depth: if this exceeds
409
407
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
410
return LOCK_EXCEED_MAX_DEPTH */
408
return LOCK_VICTIM_IS_START */
412
410
/*********************************************************************//**
413
411
Gets the nth bit of a record lock.
414
@return TRUE if bit set also if i == ULINT_UNDEFINED return FALSE*/
412
@return TRUE if bit set */
417
415
lock_rec_get_nth_bit(
466
464
/* A sanity check: the trx_id in rec must be smaller than the global
467
465
trx id counter */
469
if (UNIV_UNLIKELY(trx_id >= trx_sys->max_trx_id)) {
467
if (ut_dulint_cmp(trx_id, trx_sys->max_trx_id) >= 0) {
470
468
ut_print_timestamp(stderr);
471
469
fputs(" InnoDB: Error: transaction id associated"
472
470
" with record\n",
479
477
" global trx id counter " TRX_ID_FMT "!\n"
480
478
"InnoDB: The table is corrupt. You have to do"
481
479
" dump + drop + reimport.\n",
482
trx_id, trx_sys->max_trx_id);
480
TRX_ID_PREP_PRINTF(trx_id),
481
TRX_ID_PREP_PRINTF(trx_sys->max_trx_id));
555
554
max_trx_id = page_get_max_trx_id(page_align(rec));
555
ut_ad(!ut_dulint_is_zero(max_trx_id));
558
return(max_trx_id < view->up_limit_id);
557
return(ut_dulint_cmp(max_trx_id, view->up_limit_id) < 0);
561
560
/*********************************************************************//**
567
566
ulint n_cells) /*!< in: number of slots in lock hash table */
569
lock_sys = static_cast<lock_sys_t *>(mem_alloc(sizeof(lock_sys_t)));
568
lock_sys = mem_alloc(sizeof(lock_sys_t));
571
570
lock_sys->rec_hash = hash_create(n_cells);
918
917
ut_ad(lock_get_type_low(lock2) == LOCK_REC);
920
919
if (trx != lock2->trx
921
&& !lock_mode_compatible(static_cast<lock_mode>(LOCK_MODE_MASK & type_mode),
920
&& !lock_mode_compatible(LOCK_MODE_MASK & type_mode,
922
921
lock_get_mode(lock2))) {
924
923
/* We have somewhat complex rules when gap type record locks
1146
1145
ut_ad(mutex_own(&kernel_mutex));
1148
lock = static_cast<lock_t *>(HASH_GET_FIRST(lock_sys->rec_hash,
1149
lock_rec_hash(space, page_no)));
1147
lock = HASH_GET_FIRST(lock_sys->rec_hash,
1148
lock_rec_hash(space, page_no));
1151
1150
if ((lock->un_member.rec_lock.space == space)
1152
1151
&& (lock->un_member.rec_lock.page_no == page_no)) {
1205
1204
hash = buf_block_get_lock_hash_val(block);
1207
lock = static_cast<lock_t *>(HASH_GET_FIRST(lock_sys->rec_hash, hash));
1206
lock = HASH_GET_FIRST(lock_sys->rec_hash, hash);
1210
1209
if ((lock->un_member.rec_lock.space == space)
1222
1221
/*********************************************************************//**
1223
1222
Gets the next explicit lock request on a record.
1224
@return next lock, NULL if none exists or if heap_no == ULINT_UNDEFINED */
1223
@return next lock, NULL if none exists */
1227
1226
lock_rec_get_next(
1304
1303
size = sizeof(lock_t) + lock_rec_get_n_bits(lock) / 8;
1306
return static_cast<lock_t *>(mem_heap_dup(heap, lock, size));
1305
return(mem_heap_dup(heap, lock, size));
1309
1308
/*********************************************************************//**
1419
1418
if (lock->trx == trx
1420
1419
&& lock_mode_stronger_or_eq(lock_get_mode(lock),
1421
static_cast<lock_mode>(precise_mode & LOCK_MODE_MASK))
1420
precise_mode & LOCK_MODE_MASK)
1422
1421
&& !lock_get_wait(lock)
1423
1422
&& (!lock_rec_get_rec_not_gap(lock)
1424
1423
|| (precise_mode & LOCK_REC_NOT_GAP)
1591
1590
max trx id to the log, and therefore during recovery, this value
1592
1591
for a page may be incorrect. */
1594
if (page_get_max_trx_id(page) < trx_list_get_min_trx_id()
1593
if (!(ut_dulint_cmp(page_get_max_trx_id(page),
1594
trx_list_get_min_trx_id()) >= 0)
1595
1595
&& !recv_recovery_is_on()) {
1694
1694
n_bits = page_dir_get_n_heap(page) + LOCK_PAGE_BITMAP_MARGIN;
1695
1695
n_bytes = 1 + n_bits / 8;
1697
lock = static_cast<lock_t *>(mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes));
1697
lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes);
1699
1699
UT_LIST_ADD_LAST(trx_locks, trx->trx_locks, lock);
1729
1729
Enqueues a waiting request for a lock which cannot be granted immediately.
1730
1730
Checks for deadlocks.
1731
1731
@return DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED, or
1732
DB_SUCCESS_LOCKED_REC; DB_SUCCESS_LOCKED_REC means that
1733
there was a deadlock, but another transaction was chosen as a victim,
1734
and we got the lock immediately: no need to wait then */
1732
DB_SUCCESS; DB_SUCCESS means that there was a deadlock, but another
1733
transaction was chosen as a victim, and we got the lock immediately:
1734
no need to wait then */
1737
1737
lock_rec_enqueue_waiting(
1738
1738
/*=====================*/
1739
1739
ulint type_mode,/*!< in: lock mode this
1817
1817
#ifdef UNIV_DEBUG
1818
1818
if (lock_print_waits) {
1819
fprintf(stderr, "Lock wait for trx " TRX_ID_FMT " in index ",
1819
fprintf(stderr, "Lock wait for trx %lu in index ",
1820
(ulong) ut_dulint_get_low(trx->id));
1821
1821
ut_print_name(stderr, trx, FALSE, index->name);
1823
1823
#endif /* UNIV_DEBUG */
1921
1921
return(lock_rec_create(type_mode, block, heap_no, index, trx));
1924
/** Record locking request status */
1925
enum lock_rec_req_status {
1926
/** Failed to acquire a lock */
1928
/** Succeeded in acquiring a lock (implicit or already acquired) */
1930
/** Explicitly created a new lock */
1931
LOCK_REC_SUCCESS_CREATED
1934
1924
/*********************************************************************//**
1935
1925
This is a fast routine for locking a record in the most common cases:
1936
1926
there are no explicit locks on the page, or there is just one lock, owned
1938
1928
which does NOT look at implicit locks! Checks lock compatibility within
1939
1929
explicit locks. This function sets a normal next-key lock, or in the case of
1940
1930
a page supremum record, a gap type lock.
1941
@return whether the locking succeeded */
1931
@return TRUE if locking succeeded */
1943
enum lock_rec_req_status
1944
1934
lock_rec_lock_fast(
1945
1935
/*===============*/
1946
1936
ibool impl, /*!< in: if TRUE, no lock is set
1979
1969
lock_rec_create(mode, block, heap_no, index, trx);
1982
return(LOCK_REC_SUCCESS_CREATED);
1985
1975
if (lock_rec_get_next_on_page(lock)) {
1987
return(LOCK_REC_FAIL);
1990
1980
if (lock->trx != trx
1991
1981
|| lock->type_mode != (mode | LOCK_REC)
1992
1982
|| lock_rec_get_n_bits(lock) <= heap_no) {
1994
return(LOCK_REC_FAIL);
2001
1991
if (!lock_rec_get_nth_bit(lock, heap_no)) {
2002
1992
lock_rec_set_nth_bit(lock, heap_no);
2003
return(LOCK_REC_SUCCESS_CREATED);
2007
return(LOCK_REC_SUCCESS);
2010
1999
/*********************************************************************//**
2012
2001
low-level function which does NOT look at implicit locks! Checks lock
2013
2002
compatibility within explicit locks. This function sets a normal next-key
2014
2003
lock, or in the case of a page supremum record, a gap type lock.
2015
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
2016
or DB_QUE_THR_SUSPENDED */
2004
@return DB_SUCCESS, DB_LOCK_WAIT, or error code */
2019
2007
lock_rec_lock_slow(
2020
2008
/*===============*/
2021
2009
ibool impl, /*!< in: if TRUE, no lock is set
2050
2039
/* The trx already has a strong enough lock on rec: do
2053
} else if (lock_rec_other_has_conflicting(static_cast<lock_mode>(mode), block, heap_no, trx)) {
2043
} else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) {
2055
2045
/* If another transaction has a non-gap conflicting request in
2056
2046
the queue, as this transaction does not have a lock strong
2057
2047
enough already granted on the record, we have to wait. */
2059
return(lock_rec_enqueue_waiting(mode, block, heap_no,
2062
/* Set the requested lock on the record */
2064
lock_rec_add_to_queue(LOCK_REC | mode, block,
2065
heap_no, index, trx);
2066
return(DB_SUCCESS_LOCKED_REC);
2049
err = lock_rec_enqueue_waiting(mode, block, heap_no,
2053
/* Set the requested lock on the record */
2055
lock_rec_add_to_queue(LOCK_REC | mode, block,
2056
heap_no, index, trx);
2072
2065
/*********************************************************************//**
2075
2068
which does NOT look at implicit locks! Checks lock compatibility within
2076
2069
explicit locks. This function sets a normal next-key lock, or in the case
2077
2070
of a page supremum record, a gap type lock.
2078
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
2079
or DB_QUE_THR_SUSPENDED */
2071
@return DB_SUCCESS, DB_LOCK_WAIT, or error code */
2084
2076
ibool impl, /*!< in: if TRUE, no lock is set
2094
2086
dict_index_t* index, /*!< in: index of record */
2095
2087
que_thr_t* thr) /*!< in: query thread */
2097
2091
ut_ad(mutex_own(&kernel_mutex));
2098
2092
ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2099
2093
|| lock_table_has(thr_get_trx(thr), index->table, LOCK_IS));
2105
2099
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP
2106
2100
|| mode - (LOCK_MODE_MASK & mode) == 0);
2108
/* We try a simplified and faster subroutine for the most
2110
switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) {
2111
case LOCK_REC_SUCCESS:
2113
case LOCK_REC_SUCCESS_CREATED:
2114
return(DB_SUCCESS_LOCKED_REC);
2116
return(lock_rec_lock_slow(impl, mode, block,
2117
heap_no, index, thr));
2102
if (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) {
2104
/* We try a simplified and faster subroutine for the most
2109
err = lock_rec_lock_slow(impl, mode, block,
2110
heap_no, index, thr);
2124
2116
/*********************************************************************//**
2190
2182
#ifdef UNIV_DEBUG
2191
2183
if (lock_print_waits) {
2192
fprintf(stderr, "Lock wait for trx " TRX_ID_FMT " ends\n",
2184
fprintf(stderr, "Lock wait for trx %lu ends\n",
2185
(ulong) ut_dulint_get_low(lock->trx->id));
2195
2187
#endif /* UNIV_DEBUG */
2404
2396
if (!lock_rec_get_insert_intention(lock)
2405
2397
&& !((srv_locks_unsafe_for_binlog
2406
2398
|| lock->trx->isolation_level
2407
<= TRX_ISO_READ_COMMITTED)
2399
== TRX_ISO_READ_COMMITTED)
2408
2400
&& lock_get_mode(lock) == LOCK_X)) {
2410
2402
lock_rec_add_to_queue(LOCK_REC | LOCK_GAP
3285
3279
ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0);
3288
case LOCK_VICTIM_IS_OTHER:
3281
if (ret == LOCK_VICTIM_IS_OTHER) {
3289
3282
/* We chose some other trx as a victim: retry if there still
3290
3283
is a deadlock */
3293
case LOCK_EXCEED_MAX_DEPTH:
3294
/* If the lock search exceeds the max step
3295
or the max depth, the current trx will be
3296
the victim. Print its information. */
3297
rewind(lock_latest_err_file);
3298
ut_print_timestamp(lock_latest_err_file);
3300
fputs("TOO DEEP OR LONG SEARCH IN THE LOCK TABLE"
3301
" WAITS-FOR GRAPH, WE WILL ROLL BACK"
3302
" FOLLOWING TRANSACTION \n",
3303
lock_latest_err_file);
3305
fputs("\n*** TRANSACTION:\n", lock_latest_err_file);
3306
trx_print(lock_latest_err_file, trx, 3000);
3308
fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n",
3309
lock_latest_err_file);
3311
if (lock_get_type(lock) == LOCK_REC) {
3312
lock_rec_print(lock_latest_err_file, lock);
3288
if (UNIV_UNLIKELY(ret == LOCK_VICTIM_IS_START)) {
3289
if (lock_get_type_low(lock) & LOCK_TABLE) {
3290
table = lock->un_member.tab_lock.table;
3314
lock_table_print(lock_latest_err_file, lock);
3293
index = lock->index;
3294
table = index->table;
3318
case LOCK_VICTIM_IS_START:
3297
lock_deadlock_found = TRUE;
3319
3299
fputs("*** WE ROLL BACK TRANSACTION (2)\n",
3320
3300
lock_latest_err_file);
3324
/* No deadlock detected*/
3328
lock_deadlock_found = TRUE;
3333
3308
/********************************************************************//**
3336
3311
deadlock and we chose 'start' as the victim, LOCK_VICTIM_IS_OTHER if a
3337
3312
deadlock was found and we chose some other trx as a victim: we must do
3338
3313
the search again in this last case because there may be another
3340
LOCK_EXCEED_MAX_DEPTH if the lock search exceeds max steps or max depth. */
3343
3317
lock_deadlock_recursive(
3344
3318
/*====================*/
3345
3319
trx_t* start, /*!< in: recursion starting point */
3346
3320
trx_t* trx, /*!< in: a transaction waiting for a lock */
3347
lock_t* wait_lock, /*!< in: lock that is waiting to be granted */
3321
lock_t* wait_lock, /*!< in: the lock trx is waiting to be granted */
3348
3322
ulint* cost, /*!< in/out: number of calculation steps thus
3349
3323
far: if this exceeds LOCK_MAX_N_STEPS_...
3350
we return LOCK_EXCEED_MAX_DEPTH */
3324
we return LOCK_VICTIM_IS_START */
3351
3325
ulint depth) /*!< in: recursion depth: if this exceeds
3352
3326
LOCK_MAX_DEPTH_IN_DEADLOCK_CHECK, we
3353
return LOCK_EXCEED_MAX_DEPTH */
3327
return LOCK_VICTIM_IS_START */
3330
ulint bit_no = ULINT_UNDEFINED;
3358
ulint heap_no = ULINT_UNDEFINED;
3372
3346
*cost = *cost + 1;
3374
3350
if (lock_get_type_low(wait_lock) == LOCK_REC) {
3378
heap_no = lock_rec_find_set_bit(wait_lock);
3379
ut_a(heap_no != ULINT_UNDEFINED);
3381
space = wait_lock->un_member.rec_lock.space;
3382
page_no = wait_lock->un_member.rec_lock.page_no;
3384
lock = lock_rec_get_first_on_page_addr(space, page_no);
3386
/* Position the iterator on the first matching record lock. */
3388
&& lock != wait_lock
3389
&& !lock_rec_get_nth_bit(lock, heap_no)) {
3391
lock = lock_rec_get_next_on_page(lock);
3394
if (lock == wait_lock) {
3398
ut_ad(lock == NULL || lock_rec_get_nth_bit(lock, heap_no));
3352
bit_no = lock_rec_find_set_bit(wait_lock);
3354
ut_a(bit_no != ULINT_UNDEFINED);
3404
3357
/* Look at the locks ahead of wait_lock in the lock queue */
3407
/* Get previous table lock. */
3408
if (heap_no == ULINT_UNDEFINED) {
3410
lock = UT_LIST_GET_PREV(
3411
un_member.tab_lock.locks, lock);
3360
if (lock_get_type_low(lock) & LOCK_TABLE) {
3362
lock = UT_LIST_GET_PREV(un_member.tab_lock.locks,
3365
ut_ad(lock_get_type_low(lock) == LOCK_REC);
3366
ut_a(bit_no != ULINT_UNDEFINED);
3368
lock = (lock_t*) lock_rec_get_prev(lock, bit_no);
3414
3371
if (lock == NULL) {
3474
3431
#ifdef UNIV_DEBUG
3475
3432
if (lock_print_waits) {
3476
fputs("Deadlock detected\n",
3433
fputs("Deadlock detected"
3434
" or too long search\n",
3479
3437
#endif /* UNIV_DEBUG */
3481
if (trx_weight_ge(wait_lock->trx, start)) {
3440
fputs("TOO DEEP OR LONG SEARCH"
3441
" IN THE LOCK TABLE"
3442
" WAITS-FOR GRAPH\n", ef);
3444
return(LOCK_VICTIM_IS_START);
3447
if (trx_weight_cmp(wait_lock->trx,
3482
3449
/* Our recursion starting point
3483
3450
transaction is 'smaller', let us
3484
3451
choose 'start' as the victim and roll
3511
3478
return(LOCK_VICTIM_IS_OTHER);
3517
if (lock_print_waits) {
3518
fputs("Deadlock search exceeds"
3519
" max steps or depth.\n",
3522
#endif /* UNIV_DEBUG */
3523
/* The information about transaction/lock
3524
to be rolled back is available in the top
3525
level. Do not print anything here. */
3526
return(LOCK_EXCEED_MAX_DEPTH);
3529
3481
if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) {
3531
3483
/* Another trx ahead has requested lock in an
3535
3487
ret = lock_deadlock_recursive(
3536
3488
start, lock_trx,
3537
3489
lock_trx->wait_lock, cost, depth + 1);
3539
3490
if (ret != 0) {
3545
/* Get the next record lock to check. */
3546
if (heap_no != ULINT_UNDEFINED) {
3551
lock = lock_rec_get_next_on_page(lock);
3552
} while (lock != NULL
3553
&& lock != wait_lock
3554
&& !lock_rec_get_nth_bit(lock, heap_no));
3556
if (lock == wait_lock) {
3560
3496
}/* end of the 'for (;;)'-loop */
3596
3532
ib_vector_push(trx->autoinc_locks, lock);
3598
lock = static_cast<lock_t *>(mem_heap_alloc(trx->lock_heap, sizeof(lock_t)));
3534
lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t));
3601
3537
UT_LIST_ADD_LAST(trx_locks, trx->trx_locks, lock);
3738
3674
/* Deadlock resolution chose another transaction as a victim,
3739
3675
and we accidentally got our lock granted! */
3741
return(DB_SUCCESS_LOCKED_REC);
3744
3680
trx->que_state = TRX_QUE_LOCK_WAIT;
3753
3689
/*********************************************************************//**
3754
3690
Checks if other transactions have an incompatible mode lock request in
3756
@return lock or NULL */
3759
3694
lock_table_other_has_incompatible(
3760
3695
/*==============================*/
3761
3696
trx_t* trx, /*!< in: transaction, or NULL if all
3777
3712
&& (!lock_mode_compatible(lock_get_mode(lock), mode))
3778
3713
&& (wait || !(lock_get_wait(lock)))) {
3783
3718
lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
3789
3724
/*********************************************************************//**
3946
3881
mutex_enter(&kernel_mutex);
3948
first_lock = lock_rec_get_first(block, heap_no);
3883
lock = lock_rec_get_first(block, heap_no);
3950
3885
/* Find the last lock with the same lock_mode and transaction
3951
3886
from the record. */
3953
for (lock = first_lock; lock != NULL;
3954
lock = lock_rec_get_next(heap_no, lock)) {
3888
while (lock != NULL) {
3955
3889
if (lock->trx == trx && lock_get_mode(lock) == lock_mode) {
3890
release_lock = lock;
3956
3891
ut_a(!lock_get_wait(lock));
3957
lock_rec_reset_nth_bit(lock, heap_no);
3962
mutex_exit(&kernel_mutex);
3963
ut_print_timestamp(stderr);
3965
" InnoDB: Error: unlock row could not"
3966
" find a %lu mode lock on the record\n",
3894
lock = lock_rec_get_next(heap_no, lock);
3897
/* If a record lock is found, release the record lock */
3899
if (UNIV_LIKELY(release_lock != NULL)) {
3900
lock_rec_reset_nth_bit(release_lock, heap_no);
3902
mutex_exit(&kernel_mutex);
3903
ut_print_timestamp(stderr);
3905
" InnoDB: Error: unlock row could not"
3906
" find a %lu mode lock on the record\n",
3972
3912
/* Check if we can now grant waiting lock requests */
3974
for (lock = first_lock; lock != NULL;
3975
lock = lock_rec_get_next(heap_no, lock)) {
3914
lock = lock_rec_get_first(block, heap_no);
3916
while (lock != NULL) {
3976
3917
if (lock_get_wait(lock)
3977
3918
&& !lock_rec_has_to_wait_in_queue(lock)) {
3979
3920
/* Grant the lock */
3980
3921
lock_grant(lock);
3924
lock = lock_rec_get_next(heap_no, lock);
3984
3927
mutex_exit(&kernel_mutex);
4014
3957
ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
4016
3959
if (lock_get_mode(lock) != LOCK_IS
4017
&& trx->undo_no != 0) {
3960
&& !ut_dulint_is_zero(trx->undo_no)) {
4019
3962
/* The trx may have modified the table. We
4020
3963
block the use of the MySQL query cache for
4213
4156
fputs("TABLE LOCK table ", file);
4214
4157
ut_print_name(file, lock->trx, TRUE,
4215
4158
lock->un_member.tab_lock.table->name);
4216
fprintf(file, " trx id " TRX_ID_FMT, lock->trx->id);
4159
fprintf(file, " trx id " TRX_ID_FMT,
4160
TRX_ID_PREP_PRINTF(lock->trx->id));
4218
4162
if (lock_get_mode(lock) == LOCK_S) {
4219
4163
fputs(" lock mode S", file);
4266
4210
(ulong) space, (ulong) page_no,
4267
4211
(ulong) lock_rec_get_n_bits(lock));
4268
4212
dict_index_name_print(file, lock->trx, lock->index);
4269
fprintf(file, " trx id " TRX_ID_FMT, lock->trx->id);
4213
fprintf(file, " trx id " TRX_ID_FMT,
4214
TRX_ID_PREP_PRINTF(lock->trx->id));
4271
4216
if (lock_get_mode(lock) == LOCK_S) {
4272
4217
fputs(" lock mode S", file);
4299
4244
block = buf_page_try_get(space, page_no, &mtr);
4301
for (i = 0; i < lock_rec_get_n_bits(lock); ++i) {
4303
if (!lock_rec_get_nth_bit(lock, i)) {
4307
fprintf(file, "Record lock, heap no %lu", (ulong) i);
4312
rec = page_find_rec_with_heap_no(
4313
buf_block_get_frame(block), i);
4315
offsets = rec_get_offsets(
4316
rec, lock->index, offsets,
4317
ULINT_UNDEFINED, &heap);
4320
rec_print_new(file, rec, offsets);
4247
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
4249
if (lock_rec_get_nth_bit(lock, i)) {
4252
= page_find_rec_with_heap_no(
4253
buf_block_get_frame(block), i);
4254
offsets = rec_get_offsets(
4255
rec, lock->index, offsets,
4256
ULINT_UNDEFINED, &heap);
4258
fprintf(file, "Record lock, heap no %lu ",
4260
rec_print_new(file, rec, offsets);
4265
for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
4266
fprintf(file, "Record lock, heap no %lu\n", (ulong) i);
4326
4270
mtr_commit(&mtr);
4367
4311
#endif /* PRINT_NUM_OF_LOCK_STRUCTS */
4369
4313
/*********************************************************************//**
4370
Prints info of locks for all transactions.
4371
@return FALSE if not able to obtain kernel mutex
4372
and exits without printing info */
4314
Prints info of locks for all transactions. */
4375
4317
lock_print_info_summary(
4376
4318
/*====================*/
4377
FILE* file, /*!< in: file where to print */
4378
ibool nowait) /*!< in: whether to wait for the kernel mutex */
4319
FILE* file) /*!< in: file where to print */
4380
/* if nowait is FALSE, wait on the kernel mutex,
4381
otherwise return immediately if fail to obtain the
4384
lock_mutex_enter_kernel();
4385
} else if (mutex_enter_nowait(&kernel_mutex)) {
4386
fputs("FAIL TO OBTAIN KERNEL MUTEX, "
4387
"SKIP LOCK INFO PRINTING\n", file);
4321
/* We must protect the MySQL thd->query field with a MySQL mutex, and
4322
because the MySQL mutex must be reserved before the kernel_mutex of
4323
InnoDB, we call innobase_mysql_prepare_print_arbitrary_thd() here. */
4325
innobase_mysql_prepare_print_arbitrary_thd();
4326
lock_mutex_enter_kernel();
4391
4328
if (lock_deadlock_found) {
4392
4329
fputs("------------------------\n"
4401
4338
"------------\n", file);
4403
4340
fprintf(file, "Trx id counter " TRX_ID_FMT "\n",
4404
trx_sys->max_trx_id);
4341
TRX_ID_PREP_PRINTF(trx_sys->max_trx_id));
4407
4344
"Purge done for trx's n:o < " TRX_ID_FMT
4408
4345
" undo n:o < " TRX_ID_FMT "\n",
4409
purge_sys->purge_trx_no,
4410
purge_sys->purge_undo_no);
4346
TRX_ID_PREP_PRINTF(purge_sys->purge_trx_no),
4347
TRX_ID_PREP_PRINTF(purge_sys->purge_undo_no));
4413
4350
"History list length %lu\n",
4418
4355
"Total number of lock structs in row lock hash table %lu\n",
4419
4356
(ulong) lock_get_n_rec_locks());
4420
4357
#endif /* PRINT_NUM_OF_LOCK_STRUCTS */
4424
4360
/*********************************************************************//**
4484
4421
"Trx read view will not see trx with"
4485
4422
" id >= " TRX_ID_FMT
4486
4423
", sees < " TRX_ID_FMT "\n",
4487
trx->read_view->low_limit_id,
4488
trx->read_view->up_limit_id);
4425
trx->read_view->low_limit_id),
4427
trx->read_view->up_limit_id));
4491
4430
if (trx->que_state == TRX_QUE_LOCK_WAIT) {
4697
4638
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
4698
4639
block, heap_no, impl_trx));
4703
4643
/* The kernel mutex may get released temporarily in the
4708
4648
(fil_space_t::latch), the following check WILL break
4709
4649
latching order and may cause a deadlock of threads. */
4711
/* NOTE: This is a bogus check that would fail in the
4712
following case: Our transaction is updating a
4713
row. After it has updated the clustered index record,
4714
it goes to a secondary index record and finds someone
4715
else holding an explicit S- or X-lock on that
4716
secondary index record, presumably from a locking
4717
read. Our transaction cannot update the secondary
4718
index immediately, but places a waiting X-lock request
4719
on the secondary index record. There is nothing
4720
illegal in this. The assertion is simply too strong. */
4722
/* From the locking point of view, each secondary
4723
index is a separate table. A lock that is held on
4724
secondary index rec does not give any rights to modify
4725
or read the clustered index rec. Therefore, we can
4726
think of the sec index as a separate 'table' from the
4727
clust index 'table'. Conversely, a transaction that
4728
has acquired a lock on and modified a clustered index
4729
record may need to wait for a lock on the
4730
corresponding record in a secondary index. */
4732
4651
impl_trx = lock_sec_rec_some_has_impl_off_kernel(
4733
4652
rec, index, offsets);
4739
4658
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
4740
4659
block, heap_no, impl_trx));
4745
4663
lock = lock_rec_get_first(block, heap_no);
4837
4755
|| lock->trx->conc_state == TRX_PREPARED
4838
4756
|| lock->trx->conc_state == TRX_COMMITTED_IN_MEMORY);
4840
# ifdef UNIV_SYNC_DEBUG
4841
/* Only validate the record queues when this thread is not
4842
holding a space->latch. Deadlocks are possible due to
4843
latching order violation when UNIV_DEBUG is defined while
4844
UNIV_SYNC_DEBUG is not. */
4845
if (!sync_thread_levels_contains(SYNC_FSP))
4846
# endif /* UNIV_SYNC_DEBUG */
4847
4758
for (i = nth_bit; i < lock_rec_get_n_bits(lock); i++) {
4849
4760
if (i == 1 || lock_rec_get_nth_bit(lock, i)) {
4854
4765
offsets = rec_get_offsets(rec, index, offsets,
4855
4766
ULINT_UNDEFINED, &heap);
4857
4768
fprintf(stderr,
4858
4769
"Validating %lu %lu\n",
4859
4770
(ulong) space, (ulong) page_no);
4861
4772
lock_mutex_exit_kernel();
4863
4774
/* If this thread is holding the file space
4929
4840
for (i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) {
4842
limit = ut_dulint_zero;
4934
4845
lock = HASH_GET_FIRST(lock_sys->rec_hash, i);
4937
ib_uint64_t space_page;
4938
4848
ut_a(trx_in_trx_list(lock->trx));
4940
4850
space = lock->un_member.rec_lock.space;
4941
4851
page_no = lock->un_member.rec_lock.page_no;
4943
space_page = ut_ull_create(space, page_no);
4945
if (space_page >= limit) {
4854
ut_dulint_create(space, page_no),
5052
4962
on the successor, which produced an unnecessary deadlock. */
5054
4964
if (lock_rec_other_has_conflicting(
5055
static_cast<lock_mode>(LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION),
4965
LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,
5056
4966
block, next_rec_heap_no, trx)) {
5058
4968
/* Note that we may get DB_SUCCESS also here! */
5067
4977
lock_mutex_exit_kernel();
5070
case DB_SUCCESS_LOCKED_REC:
5074
if (dict_index_is_clust(index)) {
4979
if ((err == DB_SUCCESS) && !dict_index_is_clust(index)) {
5077
4980
/* Update the page max trx id field */
5078
4981
page_update_max_trx_id(block,
5079
4982
buf_block_get_page_zip(block),
5267
5166
#endif /* UNIV_DEBUG */
5269
if (err == DB_SUCCESS || err == DB_SUCCESS_LOCKED_REC) {
5168
if (err == DB_SUCCESS) {
5270
5169
/* Update the page max trx id field */
5271
/* It might not be necessary to do this if
5272
err == DB_SUCCESS (no new lock created),
5273
but it should not cost too much performance. */
5274
5170
page_update_max_trx_id(block,
5275
5171
buf_block_get_page_zip(block),
5276
5172
thr_get_trx(thr)->id, mtr);
5283
5178
/*********************************************************************//**
5284
Like lock_clust_rec_read_check_and_lock(), but reads a
5179
Like the counterpart for a clustered index below, but now we read a
5285
5180
secondary index record.
5286
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
5287
or DB_QUE_THR_SUSPENDED */
5181
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
5290
5184
lock_sec_rec_read_check_and_lock(
5291
5185
/*=============================*/
5292
5186
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
5334
5228
if the max trx id for the page >= min trx id for the trx list or a
5335
5229
database recovery is running. */
5337
if ((page_get_max_trx_id(block->frame) >= trx_list_get_min_trx_id()
5231
if (((ut_dulint_cmp(page_get_max_trx_id(block->frame),
5232
trx_list_get_min_trx_id()) >= 0)
5338
5233
|| recv_recovery_is_on())
5339
5234
&& !page_rec_is_supremum(rec)) {
5362
5253
puts the transaction and the query thread to the lock wait state and inserts a
5363
5254
waiting request for a record lock to the lock queue. Sets the requested mode
5364
5255
lock on the record.
5365
@return DB_SUCCESS, DB_SUCCESS_LOCKED_REC, DB_LOCK_WAIT, DB_DEADLOCK,
5366
or DB_QUE_THR_SUSPENDED */
5256
@return DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
5369
5259
lock_clust_rec_read_check_and_lock(
5370
5260
/*===============================*/
5371
5261
ulint flags, /*!< in: if BTR_NO_LOCKING_FLAG
5458
5348
mem_heap_t* tmp_heap = NULL;
5459
5349
ulint offsets_[REC_OFFS_NORMAL_SIZE];
5460
5350
ulint* offsets = offsets_;
5462
5352
rec_offs_init(offsets_);
5464
5354
offsets = rec_get_offsets(rec, index, offsets,
5465
5355
ULINT_UNDEFINED, &tmp_heap);
5466
err = lock_clust_rec_read_check_and_lock(flags, block, rec, index,
5356
ret = lock_clust_rec_read_check_and_lock(flags, block, rec, index,
5467
5357
offsets, mode, gap_mode, thr);
5468
5358
if (tmp_heap) {
5469
5359
mem_heap_free(tmp_heap);
5472
if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
5479
5364
/*******************************************************************//**
5493
5378
/* The lock to be release must be the last lock acquired. */
5494
5379
last = ib_vector_size(autoinc_locks) - 1;
5495
lock = static_cast<lock_t *>(ib_vector_get(autoinc_locks, last));
5380
lock = ib_vector_get(autoinc_locks, last);
5497
5382
/* Should have only AUTOINC locks in the vector. */
5498
5383
ut_a(lock_get_mode(lock) == LOCK_AUTO_INC);
5561
5446
Gets the id of the transaction owning a lock.
5562
5447
@return transaction id */
5565
5450
lock_get_trx_id(
5566
5451
/*============*/
5567
5452
const lock_t* lock) /*!< in: lock */
5569
return(lock->trx->id);
5454
return(trx_get_id(lock->trx));
5572
5457
/*******************************************************************//**