📄 lock0lock.c
字号:
bit_index = i % 8; b = (ulint)*((byte*)lock + sizeof(lock_t) + byte_index); return(ut_bit_get_nth(b, bit_index));} /*************************************************************************/#define lock_mutex_enter_kernel() mutex_enter(&kernel_mutex)#define lock_mutex_exit_kernel() mutex_exit(&kernel_mutex)/*************************************************************************Checks that a transaction id is sensible, i.e., not in the future. */iboollock_check_trx_id_sanity(/*=====================*/ /* out: TRUE if ok */ dulint trx_id, /* in: trx id */ rec_t* rec, /* in: user record */ dict_index_t* index, /* in: index */ const ulint* offsets, /* in: rec_get_offsets(rec, index) */ ibool has_kernel_mutex)/* in: TRUE if the caller owns the kernel mutex */{ ibool is_ok = TRUE; ut_ad(rec_offs_validate(rec, index, offsets)); if (!has_kernel_mutex) { mutex_enter(&kernel_mutex); } /* A sanity check: the trx_id in rec must be smaller than the global trx id counter */ if (ut_dulint_cmp(trx_id, trx_sys->max_trx_id) >= 0) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: transaction id associated" " with record\n", stderr); rec_print_new(stderr, rec, offsets); fputs("InnoDB: in ", stderr); dict_index_name_print(stderr, NULL, index); fprintf(stderr, "\n""InnoDB: is %lu %lu which is higher than the global trx id counter %lu %lu!\n""InnoDB: The table is corrupt. You have to do dump + drop + reimport.\n", (ulong) ut_dulint_get_high(trx_id), (ulong) ut_dulint_get_low(trx_id), (ulong) ut_dulint_get_high(trx_sys->max_trx_id), (ulong) ut_dulint_get_low(trx_sys->max_trx_id)); is_ok = FALSE; } if (!has_kernel_mutex) { mutex_exit(&kernel_mutex); } return(is_ok);}/*************************************************************************Checks that a record is seen in a consistent read. */iboollock_clust_rec_cons_read_sees(/*==========================*/ /* out: TRUE if sees, or FALSE if an earlier version of the record should be retrieved */ rec_t* rec, /* in: user record which should be read or passed over by a read cursor */ dict_index_t* index, /* in: clustered index */ const ulint* offsets,/* in: rec_get_offsets(rec, index) */ read_view_t* view) /* in: consistent read view */{ dulint trx_id; ut_ad(index->type & DICT_CLUSTERED); ut_ad(page_rec_is_user_rec(rec)); ut_ad(rec_offs_validate(rec, index, offsets)); /* NOTE that we call this function while holding the search system latch. To obey the latching order we must NOT reserve the kernel mutex here! */ trx_id = row_get_rec_trx_id(rec, index, offsets); return(read_view_sees_trx_id(view, trx_id));}/*************************************************************************Checks that a non-clustered index record is seen in a consistent read. */ulintlock_sec_rec_cons_read_sees(/*========================*/ /* out: TRUE if certainly sees, or FALSE if an earlier version of the clustered index record might be needed: NOTE that a non-clustered index page contains so little information on its modifications that also in the case FALSE, the present version of rec may be the right, but we must check this from the clustered index record */ rec_t* rec, /* in: user record which should be read or passed over by a read cursor */ dict_index_t* index, /* in: non-clustered index */ read_view_t* view) /* in: consistent read view */{ dulint max_trx_id; UT_NOT_USED(index); ut_ad(!(index->type & DICT_CLUSTERED)); ut_ad(page_rec_is_user_rec(rec)); /* NOTE that we might call this function while holding the search system latch. To obey the latching order we must NOT reserve the kernel mutex here! */ if (recv_recovery_is_on()) { return(FALSE); } max_trx_id = page_get_max_trx_id(buf_frame_align(rec)); if (ut_dulint_cmp(max_trx_id, view->up_limit_id) >= 0) { return(FALSE); } return(TRUE);}/*************************************************************************Creates the lock system at database start. */voidlock_sys_create(/*============*/ ulint n_cells) /* in: number of slots in lock hash table */{ lock_sys = mem_alloc(sizeof(lock_sys_t)); lock_sys->rec_hash = hash_create(n_cells); /* hash_create_mutexes(lock_sys->rec_hash, 2, SYNC_REC_LOCK); */ lock_latest_err_file = os_file_create_tmpfile(); ut_a(lock_latest_err_file);}/*************************************************************************Gets the size of a lock struct. */ulintlock_get_size(void)/*===============*/ /* out: size in bytes */{ return((ulint)sizeof(lock_t));}/*************************************************************************Gets the mode of a lock. */UNIV_INLINEulintlock_get_mode(/*==========*/ /* out: mode */ lock_t* lock) /* in: lock */{ ut_ad(lock); return(lock->type_mode & LOCK_MODE_MASK);}/*************************************************************************Gets the wait flag of a lock. */UNIV_INLINEiboollock_get_wait(/*==========*/ /* out: TRUE if waiting */ lock_t* lock) /* in: lock */{ ut_ad(lock); if (lock->type_mode & LOCK_WAIT) { return(TRUE); } return(FALSE);}/*************************************************************************Gets the source table of an ALTER TABLE transaction. The table must becovered by an IX or IS table lock. */dict_table_t*lock_get_src_table(/*===============*/ /* out: the source table of transaction, if it is covered by an IX or IS table lock; dest if there is no source table, and NULL if the transaction is locking more than two tables or an inconsistency is found */ trx_t* trx, /* in: transaction */ dict_table_t* dest, /* in: destination of ALTER TABLE */ ulint* mode) /* out: lock mode of the source table */{ dict_table_t* src; lock_t* lock; src = NULL; *mode = LOCK_NONE; for (lock = UT_LIST_GET_FIRST(trx->trx_locks); lock; lock = UT_LIST_GET_NEXT(trx_locks, lock)) { lock_table_t* tab_lock; ulint lock_mode; if (!(lock_get_type(lock) & LOCK_TABLE)) { /* We are only interested in table locks. */ continue; } tab_lock = &lock->un_member.tab_lock; if (dest == tab_lock->table) { /* We are not interested in the destination table. */ continue; } else if (!src) { /* This presumably is the source table. */ src = tab_lock->table; if (UT_LIST_GET_LEN(src->locks) != 1 || UT_LIST_GET_FIRST(src->locks) != lock) { /* We only support the case when there is only one lock on this table. */ return(NULL); } } else if (src != tab_lock->table) { /* The transaction is locking more than two tables (src and dest): abort */ return(NULL); } /* Check that the source table is locked by LOCK_IX or LOCK_IS. */ lock_mode = lock_get_mode(lock); switch (lock_mode) { case LOCK_IX: case LOCK_IS: if (*mode != LOCK_NONE && *mode != lock_mode) { /* There are multiple locks on src. */ return(NULL); } *mode = lock_mode; break; } } if (!src) { /* No source table lock found: flag the situation to caller */ src = dest; } return(src);}/*************************************************************************Determine if the given table is exclusively "owned" by the giventransaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INCon the table. */iboollock_is_table_exclusive(/*====================*/ /* out: TRUE if table is only locked by trx, with LOCK_IX, and possibly LOCK_AUTO_INC */ dict_table_t* table, /* in: table */ trx_t* trx) /* in: transaction */{ lock_t* lock; ibool ok = FALSE; ut_ad(table && trx); for (lock = UT_LIST_GET_FIRST(table->locks); lock; lock = UT_LIST_GET_NEXT(locks, &lock->un_member.tab_lock)) { if (lock->trx != trx) { /* A lock on the table is held by some other transaction. */ return(FALSE); } if (!(lock_get_type(lock) & LOCK_TABLE)) { /* We are interested in table locks only. */ continue; } switch (lock_get_mode(lock)) { case LOCK_IX: ok = TRUE; break; case LOCK_AUTO_INC: /* It is allowed for trx to hold an auto_increment lock. */ break; default: /* Other table locks than LOCK_IX are not allowed. */ return(FALSE); } } return(ok);}/*************************************************************************Sets the wait flag of a lock and the back pointer in trx to lock. */UNIV_INLINEvoidlock_set_lock_and_trx_wait(/*=======================*/ lock_t* lock, /* in: lock */ trx_t* trx) /* in: trx */{ ut_ad(lock); ut_ad(trx->wait_lock == NULL); trx->wait_lock = lock; lock->type_mode = lock->type_mode | LOCK_WAIT;}/**************************************************************************The back pointer to a waiting lock request in the transaction is set to NULLand the wait bit in lock type_mode is reset. */UNIV_INLINEvoidlock_reset_lock_and_trx_wait(/*=========================*/ lock_t* lock) /* in: record lock */{ ut_ad((lock->trx)->wait_lock == lock); ut_ad(lock_get_wait(lock)); /* Reset the back pointer in trx to this waiting lock request */ (lock->trx)->wait_lock = NULL; lock->type_mode = lock->type_mode & ~LOCK_WAIT;}/*************************************************************************Gets the gap flag of a record lock. */UNIV_INLINEiboollock_rec_get_gap(/*=============*/ /* out: TRUE if gap flag set */ lock_t* lock) /* in: record lock */{ ut_ad(lock); ut_ad(lock_get_type(lock) == LOCK_REC); if (lock->type_mode & LOCK_GAP) { return(TRUE); } return(FALSE);}/*************************************************************************Gets the LOCK_REC_NOT_GAP flag of a record lock. */UNIV_INLINEiboollock_rec_get_rec_not_gap(/*=====================*/ /* out: TRUE if LOCK_REC_NOT_GAP flag set */ lock_t* lock) /* in: record lock */{ ut_ad(lock); ut_ad(lock_get_type(lock) == LOCK_REC); if (lock->type_mode & LOCK_REC_NOT_GAP) { return(TRUE); } return(FALSE);}/*************************************************************************Gets the waiting insert flag of a record lock. */UNIV_INLINEiboollock_rec_get_insert_intention(/*==========================*/ /* out: TRUE if gap flag set */ lock_t* lock) /* in: record lock */{ ut_ad(lock); ut_ad(lock_get_type(lock) == LOCK_REC); if (lock->type_mode & LOCK_INSERT_INTENTION) { return(TRUE); } return(FALSE);}/*************************************************************************Calculates if lock mode 1 is stronger or equal to lock mode 2. */UNIV_INLINEiboollock_mode_stronger_or_eq(/*=====================*/ /* out: TRUE if mode1 stronger or equal to mode2 */ ulint mode1, /* in: lock mode */ ulint mode2) /* in: lock mode */{ ut_ad(mode1 == LOCK_X || mode1 == LOCK_S || mode1 == LOCK_IX || mode1 == LOCK_IS || mode1 == LOCK_AUTO_INC); ut_ad(mode2 == LOCK_X || mode2 == LOCK_S || mode2 == LOCK_IX || mode2 == LOCK_IS || mode2 == LOCK_AUTO_INC); if (mode1 == LOCK_X) { return(TRUE); } else if (mode1 == LOCK_AUTO_INC && mode2 == LOCK_AUTO_INC) { return(TRUE); } else if (mode1 == LOCK_S && (mode2 == LOCK_S || mode2 == LOCK_IS)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -