写点什么

MYSQL 深入浅出系列 - 锁机制

作者:
  • 2024-07-04
    广东
  • 本文字数:1060 字

    阅读完需:约 3 分钟

一、锁粒度

  • 全局锁:锁整个库,一般在 mysqldum 备用的时候用,为保证数据一致性。但是引入 mvcc 后,可以做到不锁整个库就 mysqldum。

flush tables with read lock 添加全局锁

unlock tables 释放全局锁


  • 表锁:锁住整个表。触发场景:

alter table,

drop table ,

truncate table,

flush tables with read loc,

lock tables(显式的给表上锁)

myisam 引擎不支持事务,所以对表读操作会自动加上读锁,写操作自动加上写锁

适用场景:读多写少,并发不激烈的场景

表锁的风险:性能下降、并发差,死锁(锁多个表的时候)


  • 行锁:一般在事务中使用,如在事务外使用,则执行语句结束立即释放锁

共享锁(S 锁):

排他锁(X 锁):

select for update (加排他锁,悲观)

select ... lock in share mode 加 S 锁

insert\update\delete 操作的行都会添加一个 x 锁


行锁的风险:

1、死锁

2、锁升级:一个事务试图锁定的行过多,可能升级为表锁

3、锁等待

4、资源消耗:行锁要更多内存存储锁信息,而且需要更多 cpu 来处理锁请求和释放,如数据库中行越多,或者并发事物越多,会导致资源消息(锁是有成本的)

5、难以调式和排查:因为行锁粒度小

6、事务隔离级别:不同的隔离级别会影响锁的性能和行为


二、锁种类

乐观锁:根据版本号检查*更新,巧妙的实现

悲观锁:操作的时候加锁,适合写多读少的场景。

意向锁:为了平衡行锁和表锁之间产生的锁。如事物 A 对某一行加锁,然后事务 B 想申请表锁,这个时候如果没 IX(IS)意向锁的话,要逐一遍历行去检查有没行锁。所以意向锁是表锁,这个事务 B 此时判断事物 A 加上了意向锁,事务 B 就要等等了。(主要为了解决这一场景产生的),在加行锁的时候,mysql 会自动加上 IS 或者 IX

间隙锁:(事务隔离级别要 RR 才有该锁)

为了解决幻读,例如要查询年龄 10-20 区间的数据,它会在这个区间加锁,当另外一个事物想插入年龄=15 的数据时,会发生锁等待

临键锁:间隙锁 + 记录锁(记录所在的行锁)


三、间隙锁场景分析

在 RR 隔离级别下:

  • 没有索引:升级到表锁,锁全表

  • 有索引:



以上表格为例子:(age 是普通索引,id 为主键)

主键/唯一键,查询值存在的情况,只加记录锁。如 select * from stu where id = 7 for update,只会所在 id=7 行。因为有唯一约束,并发事务也不可能插入多行 id=7 的记录

主键/唯一键,查询值不存在的情况,加间隙锁。如 select * from stu where id = 8 for update,锁住间隙(7,17)

普通索引,查询值存在的情况,如 select * from stu where age = 5 for update,会锁住间隙[3,7)

普通索引,查询值不存在的情况,如 select * from stu where age = 4 for update,会锁住间隙[3,5)

发布于: 11 分钟前阅读数: 5
用户头像

关注

好记性不如烂笔头 2018-08-21 加入

还未添加个人简介

评论

发布
暂无评论
MYSQL 深入浅出系列 - 锁机制_锁_俊_InfoQ写作社区