MySQL - 锁

目录

01 全局锁

02 表锁

03 行锁

04 MySQL 加锁原理


01 全局锁

1. 全局锁的使用

  • 加锁:FTWRL:flush tables with read lock
  • 释放锁:unlock tables

2. 锁定范围:整个数据库

3. 使用场景:全库备份

4. 缺点:加了全局锁之后,全库处于只读状态,数据增删改、表结构的变更都无法进行,数据库数据量很大,全库逻辑备份会造成业务停滞

5. 不使用全局锁进行全库备份:只有存储引擎层 支持事务的可重复读隔离级别 的数据库(Innodb 支持,MyISAM 不支持事务)可以在进行备份之前开启事务来进行全库备份,开启事务时会生成一个 Read View,在整个事务执行期间都会使用这个 Read View,由于 MVCC(多版本并发控制) 的支持,如果其他事务更新了数据(新的 Read View)也不会影响到当前事务的 Read View

02 表锁

1. 表锁

  • 共享读锁:给指定表加了一个读锁(共享锁),可以进行读操作,但是会阻塞本线程以及其他线程对表的写操作

  • 独占写锁:加写锁,只有当前线程能对表进行读写操作,其他线程对表的读写操作都被阻塞

  • 执行命令:lock tables t_student read; lock tables t_student write; 释放表锁:unlock tables;

  • 缺点:表锁的粒度太大会影响并发性能,一般不使用,而是使用粒度更小的行级锁

  • 举个🌰:线程 A 执行 lock tables t1 read, t2 write,只有线程 A 可以对表 t1 进行读操作,对 t2 进行读写操作,不能写 t1,也不能读写其他表

2. 元数据锁(MDL)

  • 为了保证读写的正确性,防止一个线程在对表做 CRUD 时,其他线程修改了表的结构

  • 不需要显式添加,会在事务开始执行时 自动添加

  • MDL 读锁:对表做增删改查时添加

  • MDL 写锁:对表 结构 进行变更添加

  • 释放:事务执行期间会一直持有 MDL 锁,直到事务提交时才释放

3. 意向锁

  • 在对表 记录 加共享锁 / 独占锁时会先在表上加上表级别的意向共享锁 / 意向独占锁

  • 意向锁和行锁不冲突,意向锁之间也不冲突,意向锁只会和表级别的共享表锁和独占表锁发生冲突

  • 作用:快速判断表中是否有记录已经被加了独占锁,如果没有意向锁,在加表锁时需要 遍历整个表 的记录判断是否有记录被加了独占锁;如果有意向锁,判断是否有记录被加了独占锁 只需要判断该表是否被加了意向独占锁 即可

4. AUTO-INC 锁

  • 作用:保障主键自增,不是等事务提交了才释放而是 插入完一条数据之后就立即释放

  • 插入数据时,获取一个表级别的 AUTO_INC 锁,为被 AUTO_INCREMENT 修饰的字段赋值递增的值,等到插入语句完成之后再释放 AUTO_INC 锁,其他事务如果想要插入数据则会被阻塞,从而保证主键字段是顺序递增的

  • 缺点:在插入大量数据时,其他事务的插入语句会被阻塞,影响插入性能

  • 轻量级的锁:MySQL 5.1.22 版本开始,InnoDB 提供了一种 轻量级的锁 来实现自增,为主键字段设置一个递增的值之后就释放轻量级锁,而不是等到插入语句执行完成再释放

03 行锁

InnoDB 引擎是支持行级锁的,而 MyISAM 引擎并不支持行级锁

1. Record Lock:记录锁,只锁一条记录,S 锁和 X 锁互斥

2. Gap Lock:间隙锁,锁定一个范围但是不包含记录本身,S 锁和 X 锁兼容

3. Next-Key Lock:临键锁,记录锁和间隙锁的组合,锁定一个范围以及记录本身,S 锁和 X 锁互斥

4. 插入意向锁

  • 事务 A 加了一个 (3, 5) 的间隙锁,事务 B 想要插入 id=4 的记录会被阻塞,获取一个插入意向锁,将锁的状态设置为等待状态,知道事务 A 提交释放间隙锁,事务 B 才能进行插入(TODO 没理解的地方:事务 A 提交了之后会将插入意向锁的状态修改为正常状态吗;插入时是将因为检测到插入意向锁获取成功才能进行记录的插入吗 )

  • 一种特殊的间隙锁(间隙锁锁的是一个区间,而插入意向锁 锁的是一个点),和表级别的意向锁不一样,是行级别的锁

  • 两个事务不可能在同一个时间点,一个事务拥有某个区间的间隙锁,另一个事务拥有 该区间间隙 的插入意向锁(因为事务 A 拥有间隙锁时,事务 B 的插入意向锁状态是等待中,还没有获取成功,不算拥有,等到事务 A 释放了间隙锁,事务 B 才能获取到插入意向锁,但是区间重叠的间隙锁是可以被多个事务同时获取的)

ps:MySQL 加锁时,是先生成锁结构,然后设置锁的状态,如果锁的状态是等待状态并不代表成功获取到了锁,如果锁状态是 正常状态 才表示锁获取成功

04 MySQL 加锁原理

1. 哪些 MySQL 语句会加行级锁?

2. 各种查询语句怎么加锁?

3. 唯一索引等值查询

4. 唯一索引范围查询

5. 非唯一索引等值查询

6. 非唯一索引范围查询

7. 没有加索引的查询

唯一索引等值查询:

  • 当查询的记录是「存在」的,在索引树上定位到这一条记录后,将该记录的索引中的 next-key lock 会退化成「记录锁」

  • 当查询的记录是「不存在」的,在索引树找到第一条大于该查询记录的记录后,将该记录的索引中的 next-key lock 会退化成「间隙锁」

非唯一索引等值查询:

  • 当查询的记录「存在」时,由于不是唯一索引,所以肯定存在索引值相同的记录,于是非唯一索引等值查询的过程是一个扫描的过程,直到扫描到第一个不符合条件的二级索引记录就停止扫描,然后在扫描的过程中,对扫描到的二级索引记录加的是 next-key 锁,而对于第一个不符合条件的二级索引记录,该二级索引的 next-key 锁会退化成间隙锁。同时,在符合查询条件的记录的主键索引上加记录锁

  • 当查询的记录「不存在」时,扫描到第一条不符合条件的二级索引记录,该二级索引的 next-key 锁会退化成间隙锁。因为不存在满足查询条件的记录,所以不会对主键索引加锁

非唯一索引和主键索引的范围查询的加锁规则不同之处在于:

  • 唯一索引在满足一些条件的时候,索引的 next-key lock 退化为间隙锁或者记录锁。

  • 非唯一索引范围查询,索引的 next-key lock 不会退化为间隙锁和记录锁。

  • 19
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值