本文主要对 InnoDB 层的锁机制进行说明。
行级锁的基本概念
数据结构
注释:
- lock_t 是一个内存结构,内存从 trx_lock_t 上进行分配,也可以理解为在 trx 上进行分配
- lock_sys_t 是一个全局的数据结构,通过 hash_table_t 保存了所有分配的 lock_t
- 锁等待借助于 srv_slot_t 中的 os_event_t 来实现,lock_sys_t 中也保存了所有使用的 srv_slot_t
- trx_lock_t 的 blocking_trx 中保存了 trx 间的锁等待关系,标记当前 trx 在等待另外一个 trx 分配的锁
- trx_lock_t 的 wait_thr 字段标记了等待当前锁的线程
行级锁类型
1 2 3 4 5
| // 1. LOCK_REC_NOT_GAP : 记录锁
// 2. LOCK_GAP : 区间锁
// 3. LOCK_ORDINARY(Next-Key Lock) : 包含记录本身及记录之前的 GAP
|
源码分析
加行锁的入口包含 sel_set_rec_lock 和 row_ins_set_rec_lock,基本调用路径如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
| |--> sel_set_rec_lock | |--> btr_pcur_get_block | | | |--> lock_clust_rec_read_check_and_lock | | |--> page_rec_get_heap_no | | |--> lock_rec_convert_impl_to_expl | | | |--> lock_clust_rec_some_has_impl | | | |--> trx_rw_is_active | | | |--> lock_rec_convert_impl_to_expl_for_trx | | | | |--> lock_rec_add_to_queue | | | | | |--> rec_lock.create | | | | | | |--> lock_alloc | | | | | | |--> lock_add | | | | | |--> lock_rec_lock | | | |--> lock_rec_lock_fast | | | | |--> lock_rec_get_first_on_page | | | | | | | |--> lock_rec_lock_slow | | | | |--> lock_rec_has_expl | | | | |--> lock_rec_other_has_conflicting | | | | | |--> lock_rec_has_to_wait | | | | | | | | | |--> rec_lock.add_to_waitq | | | | | |--> create | | | | | |--> lock_create_wait_for_edge | | | | | |--> set_wait_state | | | | | | |--> que_thr_stop | | | | | | | | | |--> lock_rec_add_to_queue | | | |--> lock_sec_rec_read_check_and_lock | | |--> page_rec_get_heap_no | | |--> lock_rec_convert_impl_to_expl | | |--> lock_rec_lock
|--> row_ins_set_rec_lock | |--> lock_clust_rec_read_check_and_lock | | | |--> lock_sec_rec_read_check_and_lock
|--> lock_clust_rec_modify_check_and_lock | |--> lock_rec_convert_impl_to_expl | | | |--> lock_rec_lock
|
锁等待判断:
1
| |--> lock_rec_has_to_wait
|
锁等待处理入口:
1 2 3 4 5 6
| |--> lock_wait_suspend_thread | |--> trx_lock_wait_timeout_get | | | |--> lock_wait_table_reserve_slot | |--> os_event_wait(slot->event) | |--> lock_wait_table_release_slot
|
锁释放入口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| |--> trx_commit_in_memory | |--> trx_release_impl_and_expl_locks | | |--> lock_trx_release_locks | | | |--> lock_release | | | | |--> lock_rec_dequeue_from_page | | | | | |--> lock_rec_discard | | | | | |--> lock_rec_grant | | | | | | |--> lock_grant_or_update_wait_for_edge_if_waiting | | | | | | | |--> lock_grant_or_update_wait_for_edge | | | | | | | | |--> lock_has_to_wait_in_queue | | | | | | | | |--> lock_grant | | | | | | | | | |--> lock_reset_wait_and_release_thread_if_suspended | | | | | | | | | | |--> lock_reset_lock_and_trx_wait | | | | | | | | | | |--> lock_wait_release_thread_if_suspended | | | | | | | | | | | |--> que_thr_end_lock_wait | | | | | | | | | | | |--> os_event_set(thr->slot->event) | | | | | | | | |--> lock_update_wait_for_edge | | | | | | | | | | | | | |--> lock_grant_cats | | | | | | | | | |--> lock_table_dequeue
|
参考文献
InnoDB 事务锁系统简介:http://mysql.taobao.org/monthly/2016/01/01/
InnoDB 锁子系统浅析:http://mysql.taobao.org/monthly/2017/12/02/
InnoDB 行锁分析:http://mysql.taobao.org/monthly/2018/05/04/
https://time.geekbang.org/column/article/75659