~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/innobase/lock/lock0lock.c

  • Committer: Brian Aker
  • Date: 2010-10-28 17:12:01 UTC
  • mfrom: (1887.1.3 merge)
  • Revision ID: brian@tangent.org-20101028171201-baj6l1bnntn1s4ad
Merge in POTFILES changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*****************************************************************************
2
2
 
3
 
Copyright (C) 1996, 2010, Innobase Oy. All Rights Reserved.
 
3
Copyright (c) 1996, 2009, Innobase Oy. All Rights Reserved.
4
4
 
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
378
377
 
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
396
 
deadlock!
397
 
LOCK_EXCEED_MAX_DEPTH if the lock search exceeds max steps or max depth. */
 
395
deadlock! */
398
396
static
399
397
ulint
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 */
411
409
 
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 */
415
413
UNIV_INLINE
416
414
ibool
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 */
468
466
 
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));
483
482
 
484
483
                is_ok = FALSE;
485
484
        }
553
552
        }
554
553
 
555
554
        max_trx_id = page_get_max_trx_id(page_align(rec));
556
 
        ut_ad(max_trx_id);
 
555
        ut_ad(!ut_dulint_is_zero(max_trx_id));
557
556
 
558
 
        return(max_trx_id < view->up_limit_id);
 
557
        return(ut_dulint_cmp(max_trx_id, view->up_limit_id) < 0);
559
558
}
560
559
 
561
560
/*********************************************************************//**
566
565
/*============*/
567
566
        ulint   n_cells)        /*!< in: number of slots in lock hash table */
568
567
{
569
 
        lock_sys = static_cast<lock_sys_t *>(mem_alloc(sizeof(lock_sys_t)));
 
568
        lock_sys = mem_alloc(sizeof(lock_sys_t));
570
569
 
571
570
        lock_sys->rec_hash = hash_create(n_cells);
572
571
 
615
614
{
616
615
        ut_ad(lock);
617
616
 
618
 
        return static_cast<lock_mode>(lock->type_mode & LOCK_MODE_MASK);
 
617
        return(lock->type_mode & LOCK_MODE_MASK);
619
618
}
620
619
 
621
620
/*********************************************************************//**
918
917
        ut_ad(lock_get_type_low(lock2) == LOCK_REC);
919
918
 
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))) {
923
922
 
924
923
                /* We have somewhat complex rules when gap type record locks
1113
1112
        page_no = lock->un_member.rec_lock.page_no;
1114
1113
 
1115
1114
        for (;;) {
1116
 
                lock = static_cast<lock_t *>(HASH_GET_NEXT(hash, lock));
 
1115
                lock = HASH_GET_NEXT(hash, lock);
1117
1116
 
1118
1117
                if (!lock) {
1119
1118
 
1145
1144
 
1146
1145
        ut_ad(mutex_own(&kernel_mutex));
1147
1146
 
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));
1150
1149
        while (lock) {
1151
1150
                if ((lock->un_member.rec_lock.space == space)
1152
1151
                    && (lock->un_member.rec_lock.page_no == page_no)) {
1154
1153
                        break;
1155
1154
                }
1156
1155
 
1157
 
                lock = static_cast<lock_t *>(HASH_GET_NEXT(hash, lock));
 
1156
                lock = HASH_GET_NEXT(hash, lock);
1158
1157
        }
1159
1158
 
1160
1159
        return(lock);
1204
1203
 
1205
1204
        hash = buf_block_get_lock_hash_val(block);
1206
1205
 
1207
 
        lock = static_cast<lock_t *>(HASH_GET_FIRST(lock_sys->rec_hash, hash));
 
1206
        lock = HASH_GET_FIRST(lock_sys->rec_hash, hash);
1208
1207
 
1209
1208
        while (lock) {
1210
1209
                if ((lock->un_member.rec_lock.space == space)
1213
1212
                        break;
1214
1213
                }
1215
1214
 
1216
 
                lock = static_cast<lock_t *>(HASH_GET_NEXT(hash, lock));
 
1215
                lock = HASH_GET_NEXT(hash, lock);
1217
1216
        }
1218
1217
 
1219
1218
        return(lock);
1221
1220
 
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 */
1225
1224
UNIV_INLINE
1226
1225
lock_t*
1227
1226
lock_rec_get_next(
1303
1302
 
1304
1303
        size = sizeof(lock_t) + lock_rec_get_n_bits(lock) / 8;
1305
1304
 
1306
 
        return static_cast<lock_t *>(mem_heap_dup(heap, lock, size));
 
1305
        return(mem_heap_dup(heap, lock, size));
1307
1306
}
1308
1307
 
1309
1308
/*********************************************************************//**
1418
1417
        while (lock) {
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. */
1593
1592
 
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()) {
1596
1596
 
1597
1597
                return(NULL);
1620
1620
ulint
1621
1621
lock_number_of_rows_locked(
1622
1622
/*=======================*/
1623
 
        const trx_t*    trx)    /*!< in: transaction */
 
1623
        trx_t*  trx)    /*!< in: transaction */
1624
1624
{
1625
1625
        lock_t* lock;
1626
1626
        ulint   n_records = 0;
1694
1694
        n_bits = page_dir_get_n_heap(page) + LOCK_PAGE_BITMAP_MARGIN;
1695
1695
        n_bytes = 1 + n_bits / 8;
1696
1696
 
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);
1698
1698
 
1699
1699
        UT_LIST_ADD_LAST(trx_locks, trx->trx_locks, lock);
1700
1700
 
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 */
1735
1735
static
1736
 
enum db_err
 
1736
ulint
1737
1737
lock_rec_enqueue_waiting(
1738
1738
/*=====================*/
1739
1739
        ulint                   type_mode,/*!< in: lock mode this
1805
1805
 
1806
1806
        if (trx->wait_lock == NULL) {
1807
1807
 
1808
 
                return(DB_SUCCESS_LOCKED_REC);
 
1808
                return(DB_SUCCESS);
1809
1809
        }
1810
1810
 
1811
1811
        trx->que_state = TRX_QUE_LOCK_WAIT;
1816
1816
 
1817
1817
#ifdef UNIV_DEBUG
1818
1818
        if (lock_print_waits) {
1819
 
                fprintf(stderr, "Lock wait for trx " TRX_ID_FMT " in index ",
1820
 
                        trx->id);
 
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);
1822
1822
        }
1823
1823
#endif /* UNIV_DEBUG */
1921
1921
        return(lock_rec_create(type_mode, block, heap_no, index, trx));
1922
1922
}
1923
1923
 
1924
 
/** Record locking request status */
1925
 
enum lock_rec_req_status {
1926
 
        /** Failed to acquire a lock */
1927
 
        LOCK_REC_FAIL,
1928
 
        /** Succeeded in acquiring a lock (implicit or already acquired) */
1929
 
        LOCK_REC_SUCCESS,
1930
 
        /** Explicitly created a new lock */
1931
 
        LOCK_REC_SUCCESS_CREATED
1932
 
};
1933
 
 
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 */
1942
1932
UNIV_INLINE
1943
 
enum lock_rec_req_status
 
1933
ibool
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);
1980
1970
                }
1981
1971
 
1982
 
                return(LOCK_REC_SUCCESS_CREATED);
 
1972
                return(TRUE);
1983
1973
        }
1984
1974
 
1985
1975
        if (lock_rec_get_next_on_page(lock)) {
1986
1976
 
1987
 
                return(LOCK_REC_FAIL);
 
1977
                return(FALSE);
1988
1978
        }
1989
1979
 
1990
1980
        if (lock->trx != trx
1991
1981
            || lock->type_mode != (mode | LOCK_REC)
1992
1982
            || lock_rec_get_n_bits(lock) <= heap_no) {
1993
1983
 
1994
 
                return(LOCK_REC_FAIL);
 
1984
                return(FALSE);
1995
1985
        }
1996
1986
 
1997
1987
        if (!impl) {
2000
1990
 
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);
2004
1993
                }
2005
1994
        }
2006
1995
 
2007
 
        return(LOCK_REC_SUCCESS);
 
1996
        return(TRUE);
2008
1997
}
2009
1998
 
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 */
2017
2005
static
2018
 
enum db_err
 
2006
ulint
2019
2007
lock_rec_lock_slow(
2020
2008
/*===============*/
2021
2009
        ibool                   impl,   /*!< in: if TRUE, no lock is set
2032
2020
        que_thr_t*              thr)    /*!< in: query thread */
2033
2021
{
2034
2022
        trx_t*  trx;
 
2023
        ulint   err;
2035
2024
 
2036
2025
        ut_ad(mutex_own(&kernel_mutex));
2037
2026
        ut_ad((LOCK_MODE_MASK & mode) != LOCK_S
2050
2039
                /* The trx already has a strong enough lock on rec: do
2051
2040
                nothing */
2052
2041
 
2053
 
        } else if (lock_rec_other_has_conflicting(static_cast<lock_mode>(mode), block, heap_no, trx)) {
 
2042
                err = DB_SUCCESS;
 
2043
        } else if (lock_rec_other_has_conflicting(mode, block, heap_no, trx)) {
2054
2044
 
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. */
2058
2048
 
2059
 
                return(lock_rec_enqueue_waiting(mode, block, heap_no,
2060
 
                                                index, thr));
2061
 
        } else if (!impl) {
2062
 
                /* Set the requested lock on the record */
2063
 
 
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,
 
2050
                                               index, thr);
 
2051
        } else {
 
2052
                if (!impl) {
 
2053
                        /* Set the requested lock on the record */
 
2054
 
 
2055
                        lock_rec_add_to_queue(LOCK_REC | mode, block,
 
2056
                                              heap_no, index, trx);
 
2057
                }
 
2058
 
 
2059
                err = DB_SUCCESS;
2067
2060
        }
2068
2061
 
2069
 
        return(DB_SUCCESS);
 
2062
        return(err);
2070
2063
}
2071
2064
 
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 */
2080
2072
static
2081
 
enum db_err
 
2073
ulint
2082
2074
lock_rec_lock(
2083
2075
/*==========*/
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 */
2096
2088
{
 
2089
        ulint   err;
 
2090
 
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);
2107
2101
 
2108
 
        /* We try a simplified and faster subroutine for the most
2109
 
        common cases */
2110
 
        switch (lock_rec_lock_fast(impl, mode, block, heap_no, index, thr)) {
2111
 
        case LOCK_REC_SUCCESS:
2112
 
                return(DB_SUCCESS);
2113
 
        case LOCK_REC_SUCCESS_CREATED:
2114
 
                return(DB_SUCCESS_LOCKED_REC);
2115
 
        case LOCK_REC_FAIL:
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)) {
 
2103
 
 
2104
                /* We try a simplified and faster subroutine for the most
 
2105
                common cases */
 
2106
 
 
2107
                err = DB_SUCCESS;
 
2108
        } else {
 
2109
                err = lock_rec_lock_slow(impl, mode, block,
 
2110
                                         heap_no, index, thr);
2118
2111
        }
2119
2112
 
2120
 
        ut_error;
2121
 
        return(DB_ERROR);
 
2113
        return(err);
2122
2114
}
2123
2115
 
2124
2116
/*********************************************************************//**
2189
2181
 
2190
2182
#ifdef UNIV_DEBUG
2191
2183
        if (lock_print_waits) {
2192
 
                fprintf(stderr, "Lock wait for trx " TRX_ID_FMT " ends\n",
2193
 
                        lock->trx->id);
 
2184
                fprintf(stderr, "Lock wait for trx %lu ends\n",
 
2185
                        (ulong) ut_dulint_get_low(lock->trx->id));
2194
2186
        }
2195
2187
#endif /* UNIV_DEBUG */
2196
2188
 
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)) {
2409
2401
 
2410
2402
                        lock_rec_add_to_queue(LOCK_REC | LOCK_GAP
3263
3255
        lock_t* lock,   /*!< in: lock the transaction is requesting */
3264
3256
        trx_t*  trx)    /*!< in: transaction */
3265
3257
{
 
3258
        dict_table_t*   table;
 
3259
        dict_index_t*   index;
3266
3260
        trx_t*          mark_trx;
3267
3261
        ulint           ret;
3268
3262
        ulint           cost    = 0;
3284
3278
 
3285
3279
        ret = lock_deadlock_recursive(trx, trx, lock, &cost, 0);
3286
3280
 
3287
 
        switch (ret) {
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 */
 
3284
 
3291
3285
                goto retry;
3292
 
 
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);
3299
 
 
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);
3304
 
 
3305
 
                fputs("\n*** TRANSACTION:\n", lock_latest_err_file);
3306
 
                      trx_print(lock_latest_err_file, trx, 3000);
3307
 
 
3308
 
                fputs("*** WAITING FOR THIS LOCK TO BE GRANTED:\n",
3309
 
                      lock_latest_err_file);
3310
 
 
3311
 
                if (lock_get_type(lock) == LOCK_REC) {
3312
 
                        lock_rec_print(lock_latest_err_file, lock);
 
3286
        }
 
3287
 
 
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;
 
3291
                        index = NULL;
3313
3292
                } else {
3314
 
                        lock_table_print(lock_latest_err_file, lock);
 
3293
                        index = lock->index;
 
3294
                        table = index->table;
3315
3295
                }
3316
 
                break;
3317
 
 
3318
 
        case LOCK_VICTIM_IS_START:
 
3296
 
 
3297
                lock_deadlock_found = TRUE;
 
3298
 
3319
3299
                fputs("*** WE ROLL BACK TRANSACTION (2)\n",
3320
3300
                      lock_latest_err_file);
3321
 
                break;
3322
3301
 
3323
 
        default:
3324
 
                /* No deadlock detected*/
3325
 
                return(FALSE);
 
3302
                return(TRUE);
3326
3303
        }
3327
3304
 
3328
 
        lock_deadlock_found = TRUE;
3329
 
 
3330
 
        return(TRUE);
 
3305
        return(FALSE);
3331
3306
}
3332
3307
 
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
3339
 
deadlock!
3340
 
LOCK_EXCEED_MAX_DEPTH if the lock search exceeds max steps or max depth. */
 
3314
deadlock! */
3341
3315
static
3342
3316
ulint
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 */
3354
3328
{
 
3329
        lock_t* lock;
 
3330
        ulint   bit_no          = ULINT_UNDEFINED;
 
3331
        trx_t*  lock_trx;
3355
3332
        ulint   ret;
3356
 
        lock_t* lock;
3357
 
        trx_t*  lock_trx;
3358
 
        ulint   heap_no         = ULINT_UNDEFINED;
3359
3333
 
3360
3334
        ut_a(trx);
3361
3335
        ut_a(start);
3371
3345
 
3372
3346
        *cost = *cost + 1;
3373
3347
 
 
3348
        lock = wait_lock;
 
3349
 
3374
3350
        if (lock_get_type_low(wait_lock) == LOCK_REC) {
3375
 
                ulint           space;
3376
 
                ulint           page_no;
3377
 
 
3378
 
                heap_no = lock_rec_find_set_bit(wait_lock);
3379
 
                ut_a(heap_no != ULINT_UNDEFINED);
3380
 
 
3381
 
                space = wait_lock->un_member.rec_lock.space;
3382
 
                page_no = wait_lock->un_member.rec_lock.page_no;
3383
 
 
3384
 
                lock = lock_rec_get_first_on_page_addr(space, page_no);
3385
 
 
3386
 
                /* Position the iterator on the first matching record lock. */
3387
 
                while (lock != NULL
3388
 
                       && lock != wait_lock
3389
 
                       && !lock_rec_get_nth_bit(lock, heap_no)) {
3390
 
 
3391
 
                        lock = lock_rec_get_next_on_page(lock);
3392
 
                }
3393
 
 
3394
 
                if (lock == wait_lock) {
3395
 
                        lock = NULL;
3396
 
                }
3397
 
 
3398
 
                ut_ad(lock == NULL || lock_rec_get_nth_bit(lock, heap_no));
3399
 
 
3400
 
        } else {
3401
 
                lock = wait_lock;
 
3351
 
 
3352
                bit_no = lock_rec_find_set_bit(wait_lock);
 
3353
 
 
3354
                ut_a(bit_no != ULINT_UNDEFINED);
3402
3355
        }
3403
3356
 
3404
3357
        /* Look at the locks ahead of wait_lock in the lock queue */
3405
3358
 
3406
3359
        for (;;) {
3407
 
                /* Get previous table lock. */
3408
 
                if (heap_no == ULINT_UNDEFINED) {
3409
 
 
3410
 
                        lock = UT_LIST_GET_PREV(
3411
 
                                un_member.tab_lock.locks, lock);
 
3360
                if (lock_get_type_low(lock) & LOCK_TABLE) {
 
3361
 
 
3362
                        lock = UT_LIST_GET_PREV(un_member.tab_lock.locks,
 
3363
                                                lock);
 
3364
                } else {
 
3365
                        ut_ad(lock_get_type_low(lock) == LOCK_REC);
 
3366
                        ut_a(bit_no != ULINT_UNDEFINED);
 
3367
 
 
3368
                        lock = (lock_t*) lock_rec_get_prev(lock, bit_no);
3412
3369
                }
3413
3370
 
3414
3371
                if (lock == NULL) {
3426
3383
 
3427
3384
                        lock_trx = lock->trx;
3428
3385
 
3429
 
                        if (lock_trx == start) {
 
3386
                        if (lock_trx == start || too_far) {
3430
3387
 
3431
3388
                                /* We came back to the recursion starting
3432
3389
                                point: a deadlock detected; or we have
3473
3430
                                }
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",
3477
3435
                                              stderr);
3478
3436
                                }
3479
3437
#endif /* UNIV_DEBUG */
3480
 
 
3481
 
                                if (trx_weight_ge(wait_lock->trx, start)) {
 
3438
                                if (too_far) {
 
3439
 
 
3440
                                        fputs("TOO DEEP OR LONG SEARCH"
 
3441
                                              " IN THE LOCK TABLE"
 
3442
                                              " WAITS-FOR GRAPH\n", ef);
 
3443
 
 
3444
                                        return(LOCK_VICTIM_IS_START);
 
3445
                                }
 
3446
 
 
3447
                                if (trx_weight_cmp(wait_lock->trx,
 
3448
                                                   start) >= 0) {
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);
3512
3479
                        }
3513
3480
 
3514
 
                        if (too_far) {
3515
 
 
3516
 
#ifdef UNIV_DEBUG
3517
 
                                if (lock_print_waits) {
3518
 
                                        fputs("Deadlock search exceeds"
3519
 
                                              " max steps or depth.\n",
3520
 
                                              stderr);
3521
 
                                }
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);
3527
 
                        }
3528
 
 
3529
3481
                        if (lock_trx->que_state == TRX_QUE_LOCK_WAIT) {
3530
3482
 
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);
3538
 
 
3539
3490
                                if (ret != 0) {
3540
3491
 
3541
3492
                                        return(ret);
3542
3493
                                }
3543
3494
                        }
3544
3495
                }
3545
 
                /* Get the next record lock to check. */
3546
 
                if (heap_no != ULINT_UNDEFINED) {
3547
 
 
3548
 
                        ut_a(lock != NULL);
3549
 
 
3550
 
                        do {
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));
3555
 
 
3556
 
                        if (lock == wait_lock) {
3557
 
                                lock = NULL;
3558
 
                        }
3559
 
                }
3560
3496
        }/* end of the 'for (;;)'-loop */
3561
3497
}
3562
3498
 
3595
3531
 
3596
3532
                ib_vector_push(trx->autoinc_locks, lock);
3597
3533
        } else {
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));
3599
3535
        }
3600
3536
 
3601
3537
        UT_LIST_ADD_LAST(trx_locks, trx->trx_locks, lock);
3656
3592
                    && !ib_vector_is_empty(trx->autoinc_locks)) {
3657
3593
                        lock_t* autoinc_lock;
3658
3594
 
3659
 
                        autoinc_lock = static_cast<lock_t *>(ib_vector_pop(trx->autoinc_locks));
 
3595
                        autoinc_lock = ib_vector_pop(trx->autoinc_locks);
3660
3596
                        ut_a(autoinc_lock == lock);
3661
3597
                }
3662
3598
 
3738
3674
                /* Deadlock resolution chose another transaction as a victim,
3739
3675
                and we accidentally got our lock granted! */
3740
3676
 
3741
 
                return(DB_SUCCESS_LOCKED_REC);
 
3677
                return(DB_SUCCESS);
3742
3678
        }
3743
3679
 
3744
3680
        trx->que_state = TRX_QUE_LOCK_WAIT;
3752
3688
 
3753
3689
/*********************************************************************//**
3754
3690
Checks if other transactions have an incompatible mode lock request in
3755
 
the lock queue.
3756
 
@return lock or NULL */
 
3691
the lock queue. */
3757
3692
UNIV_INLINE
3758
 
lock_t*
 
3693
ibool
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)))) {
3779
3714
 
3780
 
                        return(lock);
 
3715
                        return(TRUE);
3781
3716
                }
3782
3717
 
3783
3718
                lock = UT_LIST_GET_PREV(un_member.tab_lock.locks, lock);
3784
3719
        }
3785
3720
 
3786
 
        return(NULL);
 
3721
        return(FALSE);
3787
3722
}
3788
3723
 
3789
3724
/*********************************************************************//**
3807
3742
 
3808
3743
        if (flags & BTR_NO_LOCKING_FLAG) {
3809
3744
 
3810
 
                return(DB_SUCCESS_LOCKED_REC);
 
3745
                return(DB_SUCCESS);
3811
3746
        }
3812
3747
 
3813
3748
        ut_a(flags == 0);
3934
3869
        const rec_t*            rec,    /*!< in: record */
3935
3870
        enum lock_mode          lock_mode)/*!< in: LOCK_S or LOCK_X */
3936
3871
{
3937
 
        lock_t* first_lock;
3938
3872
        lock_t* lock;
 
3873
        lock_t* release_lock    = NULL;
3939
3874
        ulint   heap_no;
3940
3875
 
3941
3876
        ut_ad(trx && rec);
3945
3880
 
3946
3881
        mutex_enter(&kernel_mutex);
3947
3882
 
3948
 
        first_lock = lock_rec_get_first(block, heap_no);
 
3883
        lock = lock_rec_get_first(block, heap_no);
3949
3884
 
3950
3885
        /* Find the last lock with the same lock_mode and transaction
3951
3886
        from the record. */
3952
3887
 
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);
3958
 
                        goto released;
3959
3892
                }
3960
 
        }
3961
 
 
3962
 
        mutex_exit(&kernel_mutex);
3963
 
        ut_print_timestamp(stderr);
3964
 
        fprintf(stderr,
3965
 
                "  InnoDB: Error: unlock row could not"
3966
 
                " find a %lu mode lock on the record\n",
3967
 
                (ulong) lock_mode);
3968
 
 
3969
 
        return;
3970
 
 
3971
 
released:
 
3893
 
 
3894
                lock = lock_rec_get_next(heap_no, lock);
 
3895
        }
 
3896
 
 
3897
        /* If a record lock is found, release the record lock */
 
3898
 
 
3899
        if (UNIV_LIKELY(release_lock != NULL)) {
 
3900
                lock_rec_reset_nth_bit(release_lock, heap_no);
 
3901
        } else {
 
3902
                mutex_exit(&kernel_mutex);
 
3903
                ut_print_timestamp(stderr);
 
3904
                fprintf(stderr,
 
3905
                        "  InnoDB: Error: unlock row could not"
 
3906
                        " find a %lu mode lock on the record\n",
 
3907
                        (ulong) lock_mode);
 
3908
 
 
3909
                return;
 
3910
        }
 
3911
 
3972
3912
        /* Check if we can now grant waiting lock requests */
3973
3913
 
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);
 
3915
 
 
3916
        while (lock != NULL) {
3976
3917
                if (lock_get_wait(lock)
3977
3918
                    && !lock_rec_has_to_wait_in_queue(lock)) {
3978
3919
 
3979
3920
                        /* Grant the lock */
3980
3921
                        lock_grant(lock);
3981
3922
                }
 
3923
 
 
3924
                lock = lock_rec_get_next(heap_no, lock);
3982
3925
        }
3983
3926
 
3984
3927
        mutex_exit(&kernel_mutex);
4014
3957
                        ut_ad(lock_get_type_low(lock) & LOCK_TABLE);
4015
3958
 
4016
3959
                        if (lock_get_mode(lock) != LOCK_IS
4017
 
                            && trx->undo_no != 0) {
 
3960
                            && !ut_dulint_is_zero(trx->undo_no)) {
4018
3961
 
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));
4217
4161
 
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));
4270
4215
 
4271
4216
        if (lock_get_mode(lock) == LOCK_S) {
4272
4217
                fputs(" lock mode S", file);
4298
4243
 
4299
4244
        block = buf_page_try_get(space, page_no, &mtr);
4300
4245
 
4301
 
        for (i = 0; i < lock_rec_get_n_bits(lock); ++i) {
4302
 
 
4303
 
                if (!lock_rec_get_nth_bit(lock, i)) {
4304
 
                        continue;
4305
 
                }
4306
 
 
4307
 
                fprintf(file, "Record lock, heap no %lu", (ulong) i);
4308
 
 
4309
 
                if (block) {
4310
 
                        const rec_t*    rec;
4311
 
 
4312
 
                        rec = page_find_rec_with_heap_no(
4313
 
                                buf_block_get_frame(block), i);
4314
 
 
4315
 
                        offsets = rec_get_offsets(
4316
 
                                rec, lock->index, offsets,
4317
 
                                ULINT_UNDEFINED, &heap);
4318
 
 
4319
 
                        putc(' ', file);
4320
 
                        rec_print_new(file, rec, offsets);
4321
 
                }
4322
 
 
4323
 
                putc('\n', file);
 
4246
        if (block) {
 
4247
                for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
 
4248
 
 
4249
                        if (lock_rec_get_nth_bit(lock, i)) {
 
4250
 
 
4251
                                const rec_t*    rec
 
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);
 
4257
 
 
4258
                                fprintf(file, "Record lock, heap no %lu ",
 
4259
                                        (ulong) i);
 
4260
                                rec_print_new(file, rec, offsets);
 
4261
                                putc('\n', file);
 
4262
                        }
 
4263
                }
 
4264
        } else {
 
4265
                for (i = 0; i < lock_rec_get_n_bits(lock); i++) {
 
4266
                        fprintf(file, "Record lock, heap no %lu\n", (ulong) i);
 
4267
                }
4324
4268
        }
4325
4269
 
4326
4270
        mtr_commit(&mtr);
4367
4311
#endif /* PRINT_NUM_OF_LOCK_STRUCTS */
4368
4312
 
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. */
4373
4315
UNIV_INTERN
4374
 
ibool
 
4316
void
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 */
4379
4320
{
4380
 
        /* if nowait is FALSE, wait on the kernel mutex,
4381
 
        otherwise return immediately if fail to obtain the
4382
 
        mutex. */
4383
 
        if (!nowait) {
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);
4388
 
                return(FALSE);
4389
 
        }
 
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. */
 
4324
 
 
4325
        innobase_mysql_prepare_print_arbitrary_thd();
 
4326
        lock_mutex_enter_kernel();
4390
4327
 
4391
4328
        if (lock_deadlock_found) {
4392
4329
                fputs("------------------------\n"
4401
4338
              "------------\n", file);
4402
4339
 
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));
4405
4342
 
4406
4343
        fprintf(file,
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));
4411
4348
 
4412
4349
        fprintf(file,
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 */
4421
 
        return(TRUE);
4422
4358
}
4423
4359
 
4424
4360
/*********************************************************************//**
4469
4405
 
4470
4406
        if (trx == NULL) {
4471
4407
                lock_mutex_exit_kernel();
 
4408
                innobase_mysql_end_print_arbitrary_thd();
4472
4409
 
4473
4410
                ut_ad(lock_validate());
4474
4411
 
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);
 
4424
                                TRX_ID_PREP_PRINTF(
 
4425
                                        trx->read_view->low_limit_id),
 
4426
                                TRX_ID_PREP_PRINTF(
 
4427
                                        trx->read_view->up_limit_id));
4489
4428
                }
4490
4429
 
4491
4430
                if (trx->que_state == TRX_QUE_LOCK_WAIT) {
4550
4489
                        }
4551
4490
 
4552
4491
                        lock_mutex_exit_kernel();
 
4492
                        innobase_mysql_end_print_arbitrary_thd();
4553
4493
 
4554
4494
                        mtr_start(&mtr);
4555
4495
 
4560
4500
 
4561
4501
                        load_page_first = FALSE;
4562
4502
 
 
4503
                        innobase_mysql_prepare_print_arbitrary_thd();
4563
4504
                        lock_mutex_enter_kernel();
4564
4505
 
4565
4506
                        goto loop;
4697
4638
                        ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
4698
4639
                                               block, heap_no, impl_trx));
4699
4640
                }
4700
 
#if 0
4701
4641
        } else {
4702
4642
 
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. */
4710
4650
 
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. */
4721
 
 
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. */
4731
 
 
4732
4651
                impl_trx = lock_sec_rec_some_has_impl_off_kernel(
4733
4652
                        rec, index, offsets);
4734
4653
 
4739
4658
                        ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
4740
4659
                                               block, heap_no, impl_trx));
4741
4660
                }
4742
 
#endif
4743
4661
        }
4744
4662
 
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);
4839
4757
 
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++) {
4848
4759
 
4849
4760
                if (i == 1 || lock_rec_get_nth_bit(lock, i)) {
4853
4764
                        ut_a(rec);
4854
4765
                        offsets = rec_get_offsets(rec, index, offsets,
4855
4766
                                                  ULINT_UNDEFINED, &heap);
4856
 
#if 0
 
4767
 
4857
4768
                        fprintf(stderr,
4858
4769
                                "Validating %lu %lu\n",
4859
4770
                                (ulong) space, (ulong) page_no);
4860
 
#endif
 
4771
 
4861
4772
                        lock_mutex_exit_kernel();
4862
4773
 
4863
4774
                        /* If this thread is holding the file space
4899
4810
lock_validate(void)
4900
4811
/*===============*/
4901
4812
{
4902
 
        lock_t*         lock;
4903
 
        trx_t*          trx;
4904
 
        ib_uint64_t     limit;
4905
 
        ulint           space;
4906
 
        ulint           page_no;
4907
 
        ulint           i;
 
4813
        lock_t* lock;
 
4814
        trx_t*  trx;
 
4815
        dulint  limit;
 
4816
        ulint   space;
 
4817
        ulint   page_no;
 
4818
        ulint   i;
4908
4819
 
4909
4820
        lock_mutex_enter_kernel();
4910
4821
 
4928
4839
 
4929
4840
        for (i = 0; i < hash_get_n_cells(lock_sys->rec_hash); i++) {
4930
4841
 
4931
 
                limit = 0;
 
4842
                limit = ut_dulint_zero;
4932
4843
 
4933
4844
                for (;;) {
4934
4845
                        lock = HASH_GET_FIRST(lock_sys->rec_hash, i);
4935
4846
 
4936
4847
                        while (lock) {
4937
 
                                ib_uint64_t     space_page;
4938
4848
                                ut_a(trx_in_trx_list(lock->trx));
4939
4849
 
4940
4850
                                space = lock->un_member.rec_lock.space;
4941
4851
                                page_no = lock->un_member.rec_lock.page_no;
4942
4852
 
4943
 
                                space_page = ut_ull_create(space, page_no);
4944
 
 
4945
 
                                if (space_page >= limit) {
 
4853
                                if (ut_dulint_cmp(
 
4854
                                            ut_dulint_create(space, page_no),
 
4855
                                            limit) >= 0) {
4946
4856
                                        break;
4947
4857
                                }
4948
4858
 
4960
4870
 
4961
4871
                        lock_mutex_enter_kernel();
4962
4872
 
4963
 
                        limit = ut_ull_create(space, page_no + 1);
 
4873
                        limit = ut_dulint_create(space, page_no + 1);
4964
4874
                }
4965
4875
        }
4966
4876
 
5052
4962
        on the successor, which produced an unnecessary deadlock. */
5053
4963
 
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)) {
5057
4967
 
5058
4968
                /* Note that we may get DB_SUCCESS also here! */
5066
4976
 
5067
4977
        lock_mutex_exit_kernel();
5068
4978
 
5069
 
        switch (err) {
5070
 
        case DB_SUCCESS_LOCKED_REC:
5071
 
                err = DB_SUCCESS;
5072
 
                /* fall through */
5073
 
        case DB_SUCCESS:
5074
 
                if (dict_index_is_clust(index)) {
5075
 
                        break;
5076
 
                }
 
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),
5196
5099
 
5197
5100
        ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
5198
5101
 
5199
 
        if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
5200
 
                err = DB_SUCCESS;
5201
 
        }
5202
 
 
5203
5102
        return(err);
5204
5103
}
5205
5104
 
5266
5165
        }
5267
5166
#endif /* UNIV_DEBUG */
5268
5167
 
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);
5277
 
                err = DB_SUCCESS;
5278
5173
        }
5279
5174
 
5280
5175
        return(err);
5281
5176
}
5282
5177
 
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 */
5288
5182
UNIV_INTERN
5289
 
enum db_err
 
5183
ulint
5290
5184
lock_sec_rec_read_check_and_lock(
5291
5185
/*=============================*/
5292
5186
        ulint                   flags,  /*!< in: if BTR_NO_LOCKING_FLAG
5307
5201
                                        LOCK_REC_NOT_GAP */
5308
5202
        que_thr_t*              thr)    /*!< in: query thread */
5309
5203
{
5310
 
        enum db_err     err;
5311
 
        ulint           heap_no;
 
5204
        ulint   err;
 
5205
        ulint   heap_no;
5312
5206
 
5313
5207
        ut_ad(!dict_index_is_clust(index));
5314
5208
        ut_ad(block->frame == page_align(rec));
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. */
5336
5230
 
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)) {
5340
5235
 
5348
5243
 
5349
5244
        ut_ad(lock_rec_queue_validate(block, rec, index, offsets));
5350
5245
 
5351
 
        if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
5352
 
                err = DB_SUCCESS;
5353
 
        }
5354
 
 
5355
5246
        return(err);
5356
5247
}
5357
5248
 
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 */
5367
5257
UNIV_INTERN
5368
 
enum db_err
 
5258
ulint
5369
5259
lock_clust_rec_read_check_and_lock(
5370
5260
/*===============================*/
5371
5261
        ulint                   flags,  /*!< in: if BTR_NO_LOCKING_FLAG
5386
5276
                                        LOCK_REC_NOT_GAP */
5387
5277
        que_thr_t*              thr)    /*!< in: query thread */
5388
5278
{
5389
 
        enum db_err     err;
5390
 
        ulint           heap_no;
 
5279
        ulint   err;
 
5280
        ulint   heap_no;
5391
5281
 
5392
5282
        ut_ad(dict_index_is_clust(index));
5393
5283
        ut_ad(block->frame == page_align(rec));
5458
5348
        mem_heap_t*     tmp_heap        = NULL;
5459
5349
        ulint           offsets_[REC_OFFS_NORMAL_SIZE];
5460
5350
        ulint*          offsets         = offsets_;
5461
 
        ulint           err;
 
5351
        ulint           ret;
5462
5352
        rec_offs_init(offsets_);
5463
5353
 
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);
5470
5360
        }
5471
 
 
5472
 
        if (UNIV_UNLIKELY(err == DB_SUCCESS_LOCKED_REC)) {
5473
 
                err = DB_SUCCESS;
5474
 
        }
5475
 
 
5476
 
        return(err);
 
5361
        return(ret);
5477
5362
}
5478
5363
 
5479
5364
/*******************************************************************//**
5492
5377
 
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);
5496
5381
 
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 */
5563
5448
UNIV_INTERN
5564
 
trx_id_t
 
5449
ullint
5565
5450
lock_get_trx_id(
5566
5451
/*============*/
5567
5452
        const lock_t*   lock)   /*!< in: lock */
5568
5453
{
5569
 
        return(lock->trx->id);
 
5454
        return(trx_get_id(lock->trx));
5570
5455
}
5571
5456
 
5572
5457
/*******************************************************************//**
5660
5545
Gets the id of the table on which the lock is.
5661
5546
@return id of the table */
5662
5547
UNIV_INTERN
5663
 
table_id_t
 
5548
ullint
5664
5549
lock_get_table_id(
5665
5550
/*==============*/
5666
5551
        const lock_t*   lock)   /*!< in: lock */
5669
5554
 
5670
5555
        table = lock_get_table(lock);
5671
5556
 
5672
 
        return(table->id);
 
5557
        return((ullint)ut_conv_dulint_to_longlong(table->id));
5673
5558
}
5674
5559
 
5675
5560
/*******************************************************************//**