mysql insert 相關的鎖函數lock_rec_insert_check_and_lock 源碼

/*============ RECORD LOCK CHECKS FOR ROW OPERATIONS ====================*/

/*********************************************************************//**
Checks if locks of other transactions prevent an immediate insert of
a record. If they do, first tests if the query thread should anyway
be suspended for some reason; if not, then puts the transaction and
the query thread to the lock wait state and inserts a waiting request
for a gap x-lock to the lock queue.
@return    DB_SUCCESS, DB_LOCK_WAIT, DB_DEADLOCK, or DB_QUE_THR_SUSPENDED */
UNIV_INTERN
ulint
lock_rec_insert_check_and_lock(
/*===========================*/
    ulint        flags,    /*!< in: if BTR_NO_LOCKING_FLAG bit is
                set, does nothing */
    const rec_t*    rec,    /*!< in: record after which to insert */
    buf_block_t*    block,    /*!< in/out: buffer block of rec */
    dict_index_t*    index,    /*!< in: index */
    que_thr_t*    thr,    /*!< in: query thread */
    mtr_t*        mtr,    /*!< in/out: mini-transaction */
    ibool*        inherit)/*!< out: set to TRUE if the new
                inserted record maybe should inherit
                LOCK_GAP type locks from the successor
                record */
{
    const rec_t*    next_rec;
    trx_t*        trx;
    lock_t*        lock;
    ulint        err;
    ulint        next_rec_heap_no;

    ut_ad(block->frame == page_align(rec));

    if (flags & BTR_NO_LOCKING_FLAG) {

        return(DB_SUCCESS);
    }

    trx = thr_get_trx(thr);
    next_rec = page_rec_get_next_const(rec);
    next_rec_heap_no = page_rec_get_heap_no(next_rec);

    lock_mutex_enter_kernel();

    /* When inserting a record into an index, the table must be at
    least IX-locked or we must be building an index, in which case
    the table must be at least S-locked. */
    ut_ad(lock_table_has(trx, index->table, LOCK_IX)
          || (*index->name == TEMP_INDEX_PREFIX
          && lock_table_has(trx, index->table, LOCK_S)));

    lock = lock_rec_get_first(block, next_rec_heap_no);

    if (UNIV_LIKELY(lock == NULL)) {
        /* We optimize CPU time usage in the simplest case */

        lock_mutex_exit_kernel();

        if (!dict_index_is_clust(index)) {
            /* Update the page max trx id field */
            page_update_max_trx_id(block,
                           buf_block_get_page_zip(block),
                           trx->id, mtr);
        }

        *inherit = FALSE;

        return(DB_SUCCESS);
    }

    *inherit = TRUE;

    /* If another transaction has an explicit lock request which locks
    the gap, waiting or granted, on the successor, the insert has to wait.

    An exception is the case where the lock by the another transaction
    is a gap type lock which it placed to wait for its turn to insert. We
    do not consider that kind of a lock conflicting with our insert. This
    eliminates an unnecessary deadlock which resulted when 2 transactions
    had to wait for their insert. Both had waiting gap type lock requests
    on the successor, which produced an unnecessary deadlock. */

    if (lock_rec_other_has_conflicting(
            LOCK_X | LOCK_GAP | LOCK_INSERT_INTENTION,
            block, next_rec_heap_no, trx)) {

        /* Note that we may get DB_SUCCESS also here! */
        err = lock_rec_enqueue_waiting(LOCK_X | LOCK_GAP
                           | LOCK_INSERT_INTENTION,
                           block, next_rec_heap_no,
                           index, thr);
    } else {
        err = DB_SUCCESS;
    }

    lock_mutex_exit_kernel();

    switch (err) {
    case DB_SUCCESS_LOCKED_REC:
        err = DB_SUCCESS;
        /* fall through */
    case DB_SUCCESS:
        if (dict_index_is_clust(index)) {
            break;
        }
        /* Update the page max trx id field */
        page_update_max_trx_id(block,
                       buf_block_get_page_zip(block),
                       trx->id, mtr);
    }

#ifdef UNIV_DEBUG
    {
        mem_heap_t*    heap        = NULL;
        ulint        offsets_[REC_OFFS_NORMAL_SIZE];
        const ulint*    offsets;
        rec_offs_init(offsets_);

        offsets = rec_get_offsets(next_rec, index, offsets_,
                      ULINT_UNDEFINED, &heap);
        ut_ad(lock_rec_queue_validate(block,
                          next_rec, index, offsets));
        if (UNIV_LIKELY_NULL(heap)) {
            mem_heap_free(heap);
        }
    }
#endif /* UNIV_DEBUG */


發佈了193 篇原創文章 · 獲贊 30 · 訪問量 49萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章