0
点赞
收藏
分享

微信扫一扫

mysql 表锁/行锁/意向锁

alonwang 2022-01-09 阅读 183

文章目录

锁的分类

表锁&行锁

根据锁定的范围大小来分

  • 表锁 lock tables 表名 READ/WRITE
  • 行锁 select * from 表名 where id=1 for update/share

悲观锁&乐观锁

  • 悲观锁
    悲观锁,认为只有加锁,才能保证数据的一致性,实现有共享锁 (S)、排它锁(X)
  • 乐观锁
    通过版本号的形式来实现,每次更新去检查下版本号,是否和之前的值相同,如果不同,则证明已经有更新操作发生,重试操作

意向锁

先说意向锁要解决的问题,解决行锁和表锁一起使用的场景
场景

事务A事务B
start transaction
select * from user where id=1 for update
start transaction
lock tables user read

现在来看事务B要成功加共享锁要有两个条件

  • user 表没有排它锁
  • user 里面的所有行没有排它锁

看第二个问题,所有行有没有加锁,只有遍历所有行有没有排它锁,这种试效率太低,有没有更好的办法?

思考下
我们在加行锁的时候,能不能加一个其它的标记,证明已经有行锁了,于是代表这个作用的锁就产生了

  • 意向共享锁 IS
  • 意向排它锁 IX

意向锁特点

  • 内部实现,不能外部操作
  • 意向锁的级别是表锁
  • 意向锁申请场景 执行for update/for share 会来申请意向锁
  • 意向锁与行锁没有冲突,只会和表锁有冲突

表锁兼容性

在这里插入图片描述
如果锁与现有锁兼容,则将锁授予请求事务,但如果与现有锁冲突则不会。事务等待直到释放冲突的现有锁

意向排它锁示例

查看记录

  • 第二行显示加了一个排它锁(X)
  • 每一行显示加了一个意向排它锁(IX)

在这里插入图片描述

意向共享锁示例

意向共享锁的含义,在得到表中行共享锁前,必须得到意向共享锁(IS),理解可以测试用例1

  • 第二行显示加了共享锁(S)
  • 第一行显示加了意向共享锁(IS)

在这里插入图片描述

测试用例

用例1
事务A事务B事务C事务D事务E
start transactionstart transactionstart transactionstart transactionstart transaction
select * from user where id=1 for update
select * from user where id=2 for updatelock tables user readselect * from user where id=1 for updatelock tables user write

分析

  1. 事务A加了意向排它锁,排它锁
  2. 事务B申请行排它锁,这里只用看记录id=2上有没有排它锁,没有申请成功
  3. 事务C,检测到事务A已经有了意向排它锁,要加的表级别的共享锁,查看表不兼容,加锁失败
  4. 事务D,检测到事务A已经有了id=1的排它锁,加锁失败
  5. 事务E,检测到事务A已经有了意向排它锁,要加的表级别的排它锁,查看表不兼容,加锁失败
用例2
事务A事务B事务C事务D事务E
start transactionstart transactionstart transactionstart transactionstart transaction
select * from user where id=1 for share
select * from user where id=2 for updatelock tables user readselect * from user where id=1 for sharelock tables user write

分析

  1. 事务A加了意向共享锁,共享锁
  2. 事务B申请行排它锁,这里只用看记录id=2上有没有排它锁,没有申请成功
  3. 事务C,检测到事务A已经有了意向共享锁,要加的表级别的共享锁,查看表兼容,加锁成功
  4. 事务D,检测到事务A有了id=1的共享锁,加锁成功
  5. 事务E,检测到事务A已经有了意向共享锁,要加的表级别的排它锁,查看表不兼容,加锁不成功
举报

相关推荐

mysql的意向锁

0 条评论