[关闭]
@xiaohaizi 2020-04-30T05:49:42.000000Z 字数 3415 阅读 841

InnoDB加锁规则

公众号文章online


In a search where at most one record in the index may match, we can use a LOCK_REC_NOT_GAP type record lock when locking a non-delete-marked matching record.

Note that in a unique secondary index there may be different delete-marked versions of a record where only the primary key values differ: thus in a secondary index we must use next-key locks when locking delete-marked records.

判断是不是unique_search:

  1. if (match_mode == ROW_SEL_EXACT
  2. && dict_index_is_unique(index)
  3. && dtuple_get_n_fields(search_tuple)
  4. == dict_index_get_n_unique(index)
  5. && (dict_index_is_clust(index)
  6. || !dtuple_contains_null(search_tuple))) {
  7. unique_search = TRUE;
  8. }

set_also_gap_locks的设置

  1. if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
  2. && prebuilt->select_lock_type != LOCK_NONE
  3. && trx->mysql_thd != NULL
  4. && thd_is_select(trx->mysql_thd)) {
  5. /* It is a plain locking SELECT and the isolation
  6. level is low: do not lock gaps */
  7. set_also_gap_locks = FALSE;
  8. }

ORDER BY DESC加gap锁

  1. if (!moves_up
  2. && !page_rec_is_supremum(rec)
  3. && set_also_gap_locks
  4. && !(srv_locks_unsafe_for_binlog
  5. || trx->isolation_level <= TRX_ISO_READ_COMMITTED)
  6. && prebuilt->select_lock_type != LOCK_NONE
  7. && !dict_index_is_spatial(index)) {
  8. /* Try to place a gap lock on the next index record
  9. to prevent phantoms in ORDER BY ... DESC queries */
  10. const rec_t* next_rec = page_rec_get_next_const(rec);
  11. offsets = rec_get_offsets(next_rec, index, offsets,
  12. ULINT_UNDEFINED, &heap);
  13. err = sel_set_rec_lock(pcur,
  14. next_rec, index, offsets,
  15. prebuilt->select_lock_type,
  16. LOCK_GAP, thr, &mtr);
  17. switch (err) {
  18. case DB_SUCCESS_LOCKED_REC:
  19. err = DB_SUCCESS;
  20. case DB_SUCCESS:
  21. break;
  22. default:
  23. goto lock_wait_or_error;
  24. }
  25. }
  26. }

ROW_SEL_EXACT情况的加锁

  1. if (set_also_gap_locks
  2. && !(srv_locks_unsafe_for_binlog
  3. || trx->isolation_level
  4. <= TRX_ISO_READ_COMMITTED)
  5. && prebuilt->select_lock_type != LOCK_NONE
  6. && !dict_index_is_spatial(index)) {
  7. /* Try to place a gap lock on the index
  8. record only if innodb_locks_unsafe_for_binlog
  9. option is not set or this session is not
  10. using a READ COMMITTED isolation level. */
  11. err = sel_set_rec_lock(
  12. pcur,
  13. rec, index, offsets,
  14. prebuilt->select_lock_type, LOCK_GAP,
  15. thr, &mtr);
  16. switch (err) {
  17. case DB_SUCCESS_LOCKED_REC:
  18. case DB_SUCCESS:
  19. break;
  20. default:
  21. goto lock_wait_or_error;
  22. }
  23. }

普通搜索情况

  1. /* Try to place a lock on the index record; note that delete
  2. marked records are a special case in a unique search. If there
  3. is a non-delete marked record, then it is enough to lock its
  4. existence with LOCK_REC_NOT_GAP. */
  5. /* If innodb_locks_unsafe_for_binlog option is used
  6. or this session is using a READ COMMITED isolation
  7. level we lock only the record, i.e., next-key locking is
  8. not used. */
  9. if (!set_also_gap_locks
  10. || srv_locks_unsafe_for_binlog
  11. || trx->isolation_level <= TRX_ISO_READ_COMMITTED
  12. || (unique_search && !rec_get_deleted_flag(rec, comp))
  13. || dict_index_is_spatial(index)) {
  14. goto no_gap_lock;
  15. } else {
  16. lock_type = LOCK_ORDINARY;
  17. }

主键>=的情况

  1. /* If we are doing a 'greater or equal than a primary key
  2. value' search from a clustered index, and we find a record
  3. that has that exact primary key value, then there is no need
  4. to lock the gap before the record, because no insert in the
  5. gap can be in our search range. That is, no phantom row can
  6. appear that way.
  7. An example: if col1 is the primary key, the search is WHERE
  8. col1 >= 100, and we find a record where col1 = 100, then no
  9. need to lock the gap before that record. */
  10. if (index == clust_index
  11. && mode == PAGE_CUR_GE
  12. && direction == 0
  13. && dtuple_get_n_fields_cmp(search_tuple)
  14. == dict_index_get_n_unique(index)
  15. && 0 == cmp_dtuple_rec(search_tuple, rec, offsets)) {
  16. no_gap_lock:
  17. lock_type = LOCK_REC_NOT_GAP;
  18. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注