MySQL锁系列(一)之锁的种类和概念

背景



锁是MySQL里面最难理解的知识,但是又无处不在。
一开始接触锁的时候,感觉被各种锁类型和名词弄得晕头转向,就别说其他了。
本文是通过DBA的视角(非InnoDB内核开发)来分析和窥探锁的奥秘,并解决实际工作当中遇到的问题

锁的种类&概念

想要啃掉这块最难的大骨头,必须先画一个框架,先了解其全貌,才能逐个击破

  • Shared and Exclusive Locks
* Shared lock: 共享锁,官方描述:permits the transaction that holds the lock to read a row

eg:select * from xx where a=1 lock in share mode

* Exclusive Locks:排他锁: permits the transaction that holds the lock to update or delete a row

eg: select * from xx where a=1 for update
  • Intention Locks
1. 这个锁是加在table上的,表示要对下一个层级(记录)进行加锁
2. Intention shared (IS):Transaction T intends to set S locks on individual rows in table t
3. Intention exclusive (IX):  Transaction T intends to set X locks on those rows
4. 在数据库层看到的结果是这样的:
    TABLE LOCK table `lc_3`.`a` trx id 133588125 lock mode IX
  • Record Locks
1. 在数据库层看到的结果是这样的:
    RECORD LOCKS space id 281 page no 3 n bits 72 index PRIMARY of table `lc_3`.`a` trx id 133588125 lock_mode X locks rec but not gap

2. 该锁是加在索引上的(从上面的index PRIMARY of table `lc_3`.`a` 就能看出来)

3. 记录锁可以有两种类型:lock_mode X locks rec but not gap  && lock_mode S locks rec but not gap

  • Gap Locks
1. 在数据库层看到的结果是这样的:
    RECORD LOCKS space id 281 page no 5 n bits 72 index idx_c of table `lc_3`.`a` trx id 133588125 lock_mode X locks gap before rec

2. Gap锁是用来防止insert的

3. Gap锁,中文名间隙锁,锁住的不是记录,而是范围,比如:(negative infinity, 10),(10, 11)区间,这里都是开区间哦

  • Next-Key Locks
1. 在数据库层看到的结果是这样的:
    RECORD LOCKS space id 281 page no 5 n bits 72 index idx_c of table `lc_3`.`a` trx id 133588125 lock_mode X

2. Next-Key Locks = Gap Locks + Record Locks 的结合, 不仅仅锁住记录,还会锁住间隙,比如: (negative infinity, 10】,(10, 11】区间,这些右边都是闭区间哦

  • Insert Intention Locks
1. 在数据库层看到的结果是这样的:
    RECORD LOCKS space id 279 page no 3 n bits 72 index PRIMARY of table `lc_3`.`t1` trx id 133587907 lock_mode X insert intention waiting

2. Insert Intention Locks 可以理解为特殊的Gap锁的一种,用以提升并发写入的性能

  • AUTO-INC Locks
1. 在数据库层看到的结果是这样的:
    TABLE LOCK table xx trx id 7498948 lock mode AUTO-INC waiting

2. 属于表级别的锁

3. 自增锁的详细情况可以之前的一篇文章:
    http://keithlan.github.io/2017/03/03/auto_increment_lock/
  • 显示锁 vs 隐示锁
* 显示锁(explicit lock)
    显示的加锁,在show engine innoDB status 中能够看到  ,会在内存中产生对象,占用内存
    eg: select ... for update , select ... lock in share mode

* 隐示锁(implicit lock)
    implicit lock 是在索引中对记录逻辑的加锁,但是实际上不产生锁对象,不占用内存空间

* 哪些语句会产生implicit lock 呢?
   eg: insert into xx values(xx)
   eg: update xx set t=t+1 where id = 1 ; 会对辅助索引加implicit lock

* implicit lock 在什么情况下会转换成 explicit lock
  eg: 只有implicit lock 产生冲突的时候,会自动转换成explicit lock,这样做的好处就是降低锁的开销
  eg: 比如:我插入了一条记录10,本身这个记录加上implicit lock,如果这时候有人再去更新这条10的记录,那么就会自动转换成explicit lock

* 数据库怎么知道implicit lock的存在呢?如何实现锁的转化呢?
  1. 对于聚集索引上面的记录,有db_trx_id,如果该事务id在活跃事务列表中,那么说明还没有提交,那么implicit则存在
  2. 对于非聚集索引:由于上面没有事务id,那么可以通过上面的主键id,再通过主键id上面的事务id来判断,不过算法要非常复杂,这里不做介绍
  • metadata lock
1. 这是Server 层实现的锁,跟引擎层无关
2. 当你执行select的时候,如果这时候有ddl语句,那么ddl会被阻塞,因为select语句拥有metadata lock,防止元数据被改掉

  • 锁迁移
1. 锁迁移,又名锁继承
2. 什么是锁迁移呢?
    a) 满足的场景条件:
    b)我锁住的记录是一条已经被标记为删除的记录,但是还没有被puge
    c) 然后这条被标记为删除的记录,被purge掉了
    d) 那么上面的锁自然而然就继承给了下一条记录,我们称之为锁迁移
  • 锁升级
锁升级指的是:一条全表更新的语句,那么数据库就会对所有记录进行加锁,那么可能造成锁开销非常大,可能升级为页锁,或者表锁。
MySQL 没有锁升级

  • 锁分裂
1. InnoDB的实现加锁,其实是在页上面做的,没有办法直接对记录加锁
2. 一个页被读取到内存,然后会产生锁对象,锁对象里面会有位图信息来表示哪些heapno被锁住,heapno表示的就是堆的序列号,可以认为就是定位到某一条记录
3. 大家又知道,由于B+tree的存在,当insert的时候,会产生页的分裂动作
4. 如果页分裂了,那么原来对页上面的加锁位图信息也就变了,为了保持这种变化和锁信息,锁对象也会分裂,由于继续维护分裂后页的锁信息
  • 锁合并
锁的合并,和锁的分裂,其实原理是一样的,参考上面即可。

至于锁合并和锁分裂的算法,比较复杂,这里就不介绍了
  • latch vs lock
* latch
  mutex
  rw-lock
  临界资源用完释放
  不支持死锁检测
  以上是应用程序中的锁,不是数据库的锁

* lock
  当事务结束后,释放
  支持死锁检测
  数据库中的锁

锁的兼容矩阵

  • X vs S
兼容性 X S
X N N
S N Y
  • IS,IX,S,X
兼容性 IS IX S X
IS Y Y Y N
IX Y Y N N
S Y N Y N
X N N N N
  • AI,IS,IX,S,X
兼容性 AI IS IX S X
AI N Y Y N N
IS Y Y Y Y N
IX Y Y Y N N
S N Y N Y N
X N N N N N

参考资料

1. https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html
2. MySQL技术内幕:InnoDB 存储引擎
3. MySQL内核:InnoDB 存储引擎

时间: 2024-12-09 21:58:31

MySQL锁系列(一)之锁的种类和概念的相关文章

MySQL锁系列(二)之 锁解读

背景 锁系列第一期的时候介绍的锁,我们要如何去解读呢? 在哪里能够看到这些锁? 锁信息解读 工欲善其事必先利其器show engine innodb status 关于锁的信息是最详细的 案例一(有索引的情况) 前期准备 dba:lc_3> dba:lc_3> dba:lc_3> show create table a; +-------+---------------------------------------------------------------------------

MySQL锁系列(七)之 锁算法详解

能学到什么 隔离级别和锁的关系 重点讲解在RR隔离级别下的加锁算法逻辑 重点罗列了比较典型的几种加锁逻辑案例 对insert的加锁逻辑进行了深度剖析 实战中剖析加锁的全过程 InnoDB为什么要这样加锁 隔离级别和算法 repeatable-read 1. 使用的是next-key locking 2. next-key lock = record lock + Gap lock read-committed 1. 使用的是 record lock 2. 当然特殊情况下( purge + uni

MySQL中的事务和锁简单用法测试

一直以来,对于MySQL中的事务和锁的内容是浅尝辄止,没有花时间了解过,在一次看同事排查的故障中有个问题引起了我的兴趣,虽然过去了很久,但是现在简单总结一下还是有一些收获. 首先我们初始化数据,事务的隔离级别还是MySQL默认的RR,存储引擎为InnoDB > create table test(id int,name varchar(30)); > insert into test values(1,'aa'); 开启一个会话,开启事务.会话1: [test]>start transa

MySQL · 引擎特性 · InnoDB 事务锁简介

InnoDB 事务锁系统简介 前言 本文的目的是对InnoDB的事务锁模块做个简单的介绍,使读者对这块有初步的认识.本文先介绍行级锁和表级锁的相关概念,再介绍其内部的一些实现:最后以两个有趣的案例结束本文. 本文所有的代码和示例都是基于当前最新的MySQL5.7.10版本. 行级锁 InnoDB支持到行级别粒度的并发控制,本小节我们分析下几种常见的行级锁类型,以及在哪些情况下会使用到这些类型的锁. LOCK_REC_NOT_GAP 锁带上这个FLAG时,表示这个锁对象只是单纯的锁在记录上,不会锁

MySQL · 引擎特性 · InnoDB 事务锁系统简介

前言 本文的目的是对 InnoDB 的事务锁模块做个简单的介绍,使读者对这块有初步的认识.本文先介绍行级锁和表级锁的相关概念,再介绍其内部的一些实现:最后以两个有趣的案例结束本文. 本文所有的代码和示例都是基于当前最新的 MySQL5.7.10 版本. 行级锁 InnoDB 支持到行级别粒度的并发控制,本小节我们分析下几种常见的行级锁类型,以及在哪些情况下会使用到这些类型的锁. LOCK_REC_NOT_GAP 锁带上这个 FLAG 时,表示这个锁对象只是单纯的锁在记录上,不会锁记录之前的 GA

MySQL行级锁、表级锁、页级锁详细介绍_Mysql

页级:引擎 BDB.表级:引擎 MyISAM , 理解为锁住整个表,可以同时读,写不行行级:引擎 INNODB , 单独的一行记录加锁 表级,直接锁定整张表,在你锁定期间,其它进程无法对该表进行写操作.如果你是写锁,则其它进程则读也不允许行级,,仅对指定的记录进行加锁,这样其它进程还是可以对同一个表中的其它记录进行操作.页级,表级锁速度快,但冲突多,行级冲突少,但速度慢.所以取了折衷的页级,一次锁定相邻的一组记录. MySQL 5.1支持对MyISAM和MEMORY表进行表级锁定,对BDB表进行

MySQL中InnoDB的间隙锁问题_Mysql

 在为一个客户排除死锁问题时我遇到了一个有趣的包括InnoDB间隙锁的情形.对于一个WHERE子句不匹配任何行的非插入的写操作中,我预期事务应该不会有锁,但我错了.让我们看一下这张表及示例UPDATE.   mysql> SHOW CREATE TABLE preferences \G *************************** 1. row *************************** Table: preferences Create Table: CREATE TAB

MySQL中的行级锁、表级锁、页级锁_Mysql

在计算机科学中,锁是在执行多线程时用于强行限制资源访问的同步机制,即用于在并发控制中保证对互斥要求的满足. 在DBMS中,可以按照锁的粒度把数据库锁分为行级锁(INNODB引擎).表级锁(MYISAM引擎)和页级锁(BDB引擎 ). 一.行级锁 行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁.行级锁能大大减少数据库操作的冲突.其加锁粒度最小,但加锁的开销也最大.行级锁分为共享锁 和 排他锁. 特点 开销大,加锁慢:会出现死锁:锁定粒度最小,发生锁冲突的概率最低,并发度也

【锁】Oracle锁系列

[锁]Oracle锁系列 1  BLOG文档结构图           2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① 锁的概念.分类.及其模拟 ② 查询锁的视图及视图之间的关联 ③ 锁的参数(DML_LOCKS.DDL_LOCK_TIMEOUT) ④ FOR UPDATE及FOR UPDATE OF系列 ⑤ 带ONLINE和不带ONLINE创建索引的锁情况(是否阻塞DML操作) ⑥ 包或存