函数lock_rec_enqueue_waiting

时间:2022-10-06 07:14:09

type_mode基础上 加上 LOCK_WAIT 表示等待状态

/*********************************************************************//**
Enqueues a waiting request for a lock which cannot be granted immediately.
Checks for deadlocks.
@return DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED, or
DB_SUCCESS_LOCKED_REC; DB_SUCCESS_LOCKED_REC means that
there was a deadlock, but another transaction was chosen as a victim,
and we got the lock immediately: no need to wait then */
static
enum db_err
lock_rec_enqueue_waiting(
/*=====================*/
    ulint            type_mode,/*!< in: lock mode this
                    transaction is requesting:
                    LOCK_S or LOCK_X, possibly
                    ORed with LOCK_GAP or
                    LOCK_REC_NOT_GAP, ORed with
                    LOCK_INSERT_INTENTION if this
                    waiting lock request is set
                    when performing an insert of
                    an index record */
    const buf_block_t*    block,    /*!< in: buffer block containing
                    the record */
    ulint            heap_no,/*!< in: heap number of the record */
    lock_t*            lock,    /*!< in: lock object; NULL if a new
                    one should be created. */
    dict_index_t*        index,    /*!< in: index of record */
    que_thr_t*        thr)    /*!< in: query thread */
{
    trx_t*    trx;

    ut_ad(mutex_own(&kernel_mutex));

    /* Test if there already is some other reason to suspend thread:
    we do not enqueue a lock request if the query thread should be
    stopped anyway */

    if (UNIV_UNLIKELY(que_thr_stop(thr))) {

        ut_error;

        return(DB_QUE_THR_SUSPENDED);
    }

    trx = thr_get_trx(thr);

    switch (trx_get_dict_operation(trx)) {
    case TRX_DICT_OP_NONE:
        break;
    case TRX_DICT_OP_TABLE:
    case TRX_DICT_OP_INDEX:
        ut_print_timestamp(stderr);
        fputs("  InnoDB: Error: a record lock wait happens"
              " in a dictionary operation!\n"
              "InnoDB: ", stderr);
        dict_index_name_print(stderr, trx, index);
        fputs(".\n"
              "InnoDB: Submit a detailed bug report"
              " to http://bugs.mysql.com\n",
              stderr);
        ut_ad();
    }

    if (lock == NULL) {
        /* Enqueue the lock request that will wait to be granted */
        lock = lock_rec_create(type_mode | LOCK_WAIT, block, heap_no, index, trx);
    } else {
        ut_ad(lock->type_mode & LOCK_WAIT);
        ut_ad(lock->type_mode & LOCK_CONV_BY_OTHER);

        lock->type_mode &= ~LOCK_CONV_BY_OTHER;
        lock_set_lock_and_trx_wait(lock, trx);
    }

    /* Check if a deadlock occurs: if yes, remove the lock request and
    return an error code */

    if (UNIV_UNLIKELY(lock_deadlock_occurs(lock, trx))) {

        lock_reset_lock_and_trx_wait(lock);
        lock_rec_reset_nth_bit(lock, heap_no);

        return(DB_DEADLOCK);
    }

    /* If there was a deadlock but we chose another transaction as a
    victim, it is possible that we already have the lock now granted! */

    if (trx->wait_lock == NULL) {

        return(DB_SUCCESS_LOCKED_REC);
    }

    trx->que_state = TRX_QUE_LOCK_WAIT;
    trx->was_chosen_as_deadlock_victim = FALSE;
    trx->wait_started = time(NULL);

    ut_a(que_thr_stop(thr));

#ifdef UNIV_DEBUG
    if (lock_print_waits) {
        fprintf(stderr, "Lock wait for trx " TRX_ID_FMT " in index ",
            (ullint) trx->id);
        ut_print_name(stderr, trx, FALSE, index->name);
    }
#endif /* UNIV_DEBUG */

    return(DB_LOCK_WAIT);
}