前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >mysql 系列:锁和它的运用

mysql 系列:锁和它的运用

原创
作者头像
lincoln
修改2021-08-31 10:45:40
2610
修改2021-08-31 10:45:40
举报
文章被收录于专栏:后端后端

前言

数据库是一个允许多用户、多会话、多线程访问的系统。为了在并发访问中能保证数据的一致性和完整性,一般会使用事务来做控制,外加锁来作为辅助手段。所以今天整理了一下锁的相关知识,看看它在事务里是怎么配合使用的。

锁的分类

我们先来看下锁的分类及其作用有哪一些,以便能更好的分析运用场景。

乐观/悲观锁

乐观锁:在读取数据时会假设各个事务互不影响,它们会处理好属于自己的那部分数据。如果在更新数据时,发现有其他事务修改了属于自己的数据,则会回滚之前的一切操作。

悲观锁:采取了先获取锁再访问的保守策略,如果已经有其他事务获取了锁,则必须等待锁释放才能继续。

共享/排它锁

共享锁:又称读锁,当前事务在读取时,允许其他事务并发读取,但不允许其他事务上排它锁,必须等自己释放了才能继续。

排它锁:又称写锁,在写锁占有时,如果其他事务想上读写锁,则得排队等待。

表锁/行锁

表锁:在操作数据时,直接将整张表锁住,操作粒度很大,很容易让其他事务在等待,但不会产生死锁。

行锁:针对的是行记录的并发控制,锁粒度很细,能支持高并发,但是不排除会有死锁情况产生。在 mysql 里行锁依赖索引实现,如果没有索引存在,则会直接进行表锁

其中,行锁还细分出了下面几种锁:

记录锁:只锁住某一条记录。当对唯一索引(包括主键)进行精确查询时,会使用记录锁。

间隙锁:当使用范围查询时,会对符合条件的区间数据上锁。在涉及到普通索引(即不是唯一索引)的查询时,都会使用间隙锁。

Next-key 锁:临建锁,可以理解为 记录锁 + 间隙锁。当对唯一索引进行范围查找或对唯一索引进行查找但结果不存在时(可以理解为锁住不存在的记录),会使用临建锁。

上面的间隙锁、临建锁有效的防止了事务幻读情况产生,避免了在查找期间有数据新增或删除。

意向锁

意向锁是属于表锁的一种,它仅仅表示一种操作意向。当我们使用粒度比较小的行锁时,在检测是否有锁时,需要一行一行的检查,效率较低。

有了意向锁之后,则不需一行一行的排查,只需检测对应的意向锁即可。

意向锁有意向共享锁,以及意向排它锁。mysql 规定事务在上共享/排它锁时,必须能先获取到兼容的意向锁,否则必须等待锁的释放。

例如当前数据上已有意向共享锁,如果此时其他事务想上排它锁,则是不兼容的,必须等待释放。关于意向锁和共享/排它锁的兼容性表如下:

意向共享锁

意向排它锁

共享锁

兼容

互斥

排它锁

互斥

互斥

MVCC

MVCC 并不属于锁操作里的东西,但是它是事务隔离级别里会运用到的技术,并且由于它有类似快照数据的功能,所以使用 MVCC 时能很大程度的减少锁的使用,减少了并发冲突。具体可以看看这篇文章:MVCC

事务里锁的运用

在之前的文章事务解释里我们谈到了事务的隔离性,而事务的隔离性离不开锁的运用,所以现在就让我们来看看具体的使用吧。

可重复读

可重复读使用的是 MVCC 快照,所以在读取数据时大多数时候不需要使用锁。

但使用了 UPDATE, DELETE,或 SELECT with FOR UPDATE(排它锁) 或 FOR SHARE(共享锁),则会根据下面的情况来使用锁:

  • 在唯一索引上精确查找某条记录时,使用记录锁
  • 对于其他的搜索,InnoDB 将会锁定扫描到的索引范围,使用间隙锁或临建锁来防止幻读的产生

读提交

也是使用 MVCC 机制来读取数据,不过在使用 UPDATE, DELETE,或 SELECT with FOR UPDATE(排它锁) 或 FOR SHARE(共享锁)时和上面的机制不一样,当存储引擎将筛选到的记录交给 mysql server 层后,会对不相干的数据进行解锁,所以不会涉及间隙锁或临建锁。

它们只会在做外键约束检查和重复键检查时使用到。

由于间隙锁的禁用,可能会出现幻读现象。

未提交读

在 mysql 的 innodb 存储引擎里做 SELECT操作不会做任何锁动作,如果是 myisam 存储引擎,则会上共享锁。

如果使用UPDATE, DELETE,或 SELECT with FOR UPDATE(排它锁) 或 FOR SHARE(共享锁)则和读提交一样的原则。

可序列化读

可序列化读在使用 select 时,一般会自动的转化为 SELECT ...

FOR SHARE(共享锁) ,以保证读写序列化。

总结

本文介绍了锁的分类以及锁在事务里的使用,大多数时候 mysql 的事务都是会自动进行锁动作,并不需要我们干涉。

所以当我们在使用 SELECT with FOR UPDATE(排它锁) 或 FOR SHARE(共享锁)等显示上锁语句时要特别注意性能损耗,有可能产生间隙锁、临建锁导致不相干的记录也会被阻塞等待


感兴趣的朋友可以搜一搜公众号「 阅新技术 」,关注更多的推送文章。

可以的话,就顺便点个赞、留个言、分享下,感谢各位支持!

阅新技术,阅读更多的新知识。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
  • 锁的分类
    • 乐观/悲观锁
      • 共享/排它锁
        • 表锁/行锁
          • 意向锁
            • MVCC
            • 事务里锁的运用
              • 可重复读
                • 读提交
                  • 未提交读
                    • 可序列化读
                    • 总结
                    相关产品与服务
                    云数据库 SQL Server
                    腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档