数据库系列:MySQL不同操作分别用什么锁?
数据库系列:MySQL慢查询分析和性能优化
数据库系列:MySQL索引优化总结(综合版)
数据库系列:高并发下的数据字段变更
数据库系列:覆盖索引和规避回表
数据库系列:数据库高可用及无损扩容
数据库系列:使用高区分度索引列提升性能
数据库系列:前缀索引和索引长度的取舍
数据库系列:MySQL引擎MyISAM和InnoDB的比较
数据库系列:InnoDB下实现高并发控制
数据库系列:事务的4种隔离级别
数据库系列:RR和RC下,快照读的区别
数据库系列:MySQL InnoDB锁机制介绍
1 回顾
我们之前讲了那么多,包括 数据库系列:InnoDB下实现高并发控制 和 数据库系列:MySQL InnoDB锁机制介绍。
总结一下,在MySQL的InnoDB存储引擎中,可以使用以下几种锁来保护并发操作:
- 共享锁(Shared Lock\S锁):
共享锁允许多个事务同时读取同一行数据,但不允许对其进行修改。如果一个事务获取了一行数据的共享锁,其他事务也可以同时获取同一行数据的共享锁,但是任何尝试获取该行数据排他锁(即进行修改操作)的事务都将被阻塞,直到共享锁被释放。
总之,共享锁不互斥,多个事务可以同时获取同一行数据的共享。我们简记为:读读并行。
# 加锁语句
SELECT ... FOR SHARE
- 排他锁(Exclusive Lock\X锁):
排他锁也称为写锁,它允许一个事务独占地对一行数据进行修改,其他事务无法同时获取该行的共享锁或排他锁。使用排他锁的事务可以确保在修改数据期间,没有其他事务能够读取或修改该行数据。
总之,排他锁互斥,同一行数据只能被一个事务获取排他锁,与其他任何锁互斥。我们简记为:写读、写写阻塞。
# 加锁语句
SELECT ... FOR UPDATE
- 意向锁(Intent Lock):
意向锁是一种低级别的锁,用于表示事务意图对某个数据范围进行锁定。它可以是共享锁或排他锁的意图表示。意向锁的作用是避免其他事务在范围级别上进行修改操作,而具体的行级锁定则由应用程序根据需求自行决定。
加锁语句:在执行UPDATE或DELETE语句之前,可以使用如下语句获取意向锁。
SELECT ... FOR UPDATE
# 或
SELECT ... FOR SHARE
- 悲观锁(Pessimistic Lock):
悲观锁假设最坏的情况,即在执行每个数据修改操作前都会先获取排他锁。这种锁的策略下,事务在修改数据时会先锁定该行数据,确保其他事务无法同时修改该行数据。乐观锁则假设最好的情况,即数据不会被其他事务同时修改,因此只在提交数据修改时才检查是否有冲突。
- 乐观锁(Optimistic Lock):
乐观锁在执行数据修改操作时不会先锁定数据,而是在提交修改时检查是否有冲突。如果检测到冲突,则事务会回滚并重新尝试。乐观锁适用于读多写少的应用场景,可以提高并发性能。
加锁语句:乐观锁没有特定的加锁语句,而是通过版本号机制来实现。在执行UPDATE或DELETE操作时,InnoDB会检查数据的版本号是否与最初读取到的版本号一致,如果不一致则表示有其他事务修改了该数据,此时会回滚事务并抛出异常。
需要注意的是,InnoDB还支持自动提交(AUTOCOMMIT)和显式提交(COMMIT)来控制事务的提交和回滚。在使用InnoDB时,可以通过调整隔离级别和并发控制参数来优化并发性能和数据一致性。
2 DML和Select具体使用什么锁
2.1 普通Select
- 我们之前说过了,普通查询为什么快,支持并发执行,不阻塞其他操作,主要是使用了快照读(snpashot read).
这个模式在 读未提交(Read Uncommitted/RU) 和 读已提交(Read Committed/RC)、可重复读(Repeated Read/RR) 隔离级别下都是有效的。
参考作者这篇:数据库系列:InnoDB下实现高并发控制
- 另外一种隔离级别:串行化(Serializable),也是我们之前说过的,在InnoDB中,串行化是最高隔离级别,普通select会升级为
select ... in share mode
。
参考作者这篇:数据库系列:事务的4种隔离级别
2.2 加锁的select
加锁的select,会使用排他锁(X锁)来保护数据,参照我们上面的介绍,主要有如下几种情况:
# 排他场景
selet ... for update
# 共享场景
select ... for share mode
这时候有如下情况:
- 在主键(primary key)和 唯一索引(unique index)上使用唯一的查询条件(unique search condition),会使用记录锁(record lock),即行锁
- 如果条件为记录区间,则会封锁记录之间的间隔,即使用间隙锁(gap lock)与临键锁(next-key lock)
参考作者这篇:数据库系列:MySQL InnoDB锁机制介绍
2.2.1 记录锁
以例为证:
# 表结构
table (Id PK, Name , Company);
# 表中包含四条记录
5, Gates, Microsoft
7, Bezos, Amazon
11, Jobs, Apple
14, Elison, Oracle
记录锁,它封锁索引记录,例如:
select * from table where id=5 for update;
它会在id=1的索引记录上加锁,以阻止其他事务插入,更新,删除id=1的这一行。
2.2.2 间隙锁/临键锁
区间范围的查询条件和索引条件,InnoDB会封锁被扫描的索引范围,并使用间隙锁与临键锁,避免索引范围区间插入记录
以例为证:
select * from table
where id between 7 and 13
for update;
这样的话,会封锁数据的区间,以防止其他事务 插入\修改\删除 id=8的记录。
2.3 Update/Delete 操作
- 和select加锁同理, 唯一索引(unique index)上使用唯一的查询条件(unique search condition),会使用记录锁(record lock),即行锁
举例:
# 只会锁住id=1的这一行
update table set name='Brand' where id=5;
区间范围情况,符合查询条件的索引记录范围,都会加排他临键锁(exclusive next-key lock),来封锁索引记录区间,来避免其他事务插入,更新,删除该区间内的索引记录。
如果update的是聚集索引(clustered index)记录,则对应的普通索引(secondary index)记录也会被隐式加锁,这是由InnoDB索引的实现机制决定的。
Innodb中最好是采用主键索引查询,这样只需要一次索引,如果使用辅助索引检索,涉及多一步的回表操作,比主键查询要耗时一些。
所以,InnoDB的普通索引,实际上会扫描两遍:
第1遍,由普通索引找到PK:检索到name='Ellison'的数据,获取id为14
第2遍,由PK找到行记录:即到主键索引中检索id为14的记录
对索引有兴趣的,可以参考作者的这几篇文章:
MySQL全面瓦解22:索引的介绍和原理分析
MySQL全面瓦解23:MySQL索引实现和使用
MySQL全面瓦解24:构建高性能索引(策略篇)
2.4 Insert 操作
Insert操作和Update/Delete操作不同,排它锁封锁的只是新插入的索引记录,而不会封锁记录之前的范围。
同理,会在插入区间加插入意向锁(insert intention lock),但这个并不会真正封锁区间,也不会阻止相同区间的不同KEY的写入。
3 总结
本文介绍了在MySQL的InnoDB存储引擎中,如何通过几种类型的锁来保护并发操作。
以及不同SQL语句使用锁的情况,这对于分析多个事务之间的并发与互斥,以及事务死锁,是非常有帮助的。
数据库系列:MySQL不同操作分别用什么锁?的更多相关文章
- javaweb链接到数据库(mysql)操作
准备:配置好数据库,下好mysql connect 第一步:将my connec文件和commons-dbutil(,jar)复制到webapp文件下WEB-INF的lib文件中,然后右键构建路径. ...
- python数据库(mysql)操作
http://fantefei.blog.51cto.com/2229719/1282443
- 【数据库】MySQL中的共享锁与排他锁
转载:http://www.hollischuang.com/archives/923 在MySQL中的行级锁,表级锁,页级锁中介绍过,行级锁是Mysql中锁定粒度最细的一种锁,行级锁能大大减少数据库 ...
- 数据库:Mysql中“select ... for update”排他锁分析
Mysql InnoDB 排他锁 用法: select … for update; 例如:select * from goods where id = 1 for update; 排他锁的申请前提:没 ...
- python操作mysql数据库系列-操作MySql数据库(二)
接口测试框架层级目录结构示意图: page目录下面的mysqlTest.py:存放的是mysql的操作代码 utils目录下面的helper.py:存放的是公共的配置方法 log目录log.md:存放 ...
- python操作数据库(Mysql)
原文地址:https://www.cnblogs.com/R-bear/p/7022231.html python DB-API介绍 1.python标准数据库接口为 python DB-API,py ...
- openresty开发系列28--openresty中操作mysql
openresty开发系列28--openresty中操作mysql Mysql客户端 应用中最常使用的就是数据库了,尤其mysql数据库,那openresty lua如何操作mysql呢? ...
- MySQL(三) 数据库表的查询操作【重要】
序言 1.MySQL表操作(创建表,查询表结构,更改表字段等), 2.MySQL的数据类型(CHAR.VARCHAR.BLOB,等), 本节比较重要,对数据表数据进行查询操作,其中可能大家不熟悉的就对 ...
- Swift3.0服务端开发(四) MySQL数据库的连接与操作
本篇博客我们来聊聊MySQL数据库的连接与操作.如果你本地没有MySQL数据库的话,需要你先安装MySQL数据库.在Mac OS中使用brew包管理器进行MySQL的安装是及其方便的.安装MySQL的 ...
- 2、ABPZero系列教程之拼多多卖家工具 更改数据库为Mysql
因为要部署项目到云服务器,不想在服务器上装SqlServer,所以需要把项目改为Mysql. 项目初始化 1.下载项目压缩包,前面文章已经说到,可以加群到群文件里下载.解压缩下载的项目源码,使用VS2 ...
随机推荐
- 《Pro Git》起步笔记
@ 目录 什么是版本控制 本地版本控制系统 集中化的版本控制 分布式的版本控制系统 Git简史 Git是什么 安装Git 在Linux上安装 在Windows上安装 初次运行Git前的配置 用户信息 ...
- 知识图谱(Knowledge Graph)- Neo4j 5.10.0 CentOS 安装
知识图谱(Knowledge Graph)- Neo4j 5.10.0 Docker 安装 知识图谱(Knowledge Graph)- Neo4j 5.10.0 CentOS 安装 https:// ...
- ignite
目录 简介 运行 制作vm文件系统 制作vm基础文件系统文件 创建contianerdClient 创建cniInstance 拉取基础镜像 创建基础文件系统文件 制作vm内核文件 Create vm ...
- ChatGPT赋能低代码开发:打造智能应用的双重引擎
摘要:本文摘自葡萄城低代码产品活字格的资深用户(格友超哥)所撰写的文章:<惊叹表现!活字格+ChatGPT:低代码开发智能应用的巨大潜力>. ChatGPT的functions函数使用方 ...
- Go 并发编程 - 并发安全(二)
什么是并发安全 并发情况下,多个线程或协程会同时操作同一个资源,例如变量.数据结构.文件等.如果不保证并发安全,就可能导致数据竞争.脏读.脏写.死锁.活锁.饥饿等一系列并发问题,产生重大的安全隐患,比 ...
- 《Linux基础》05. 定时任务调度 · 磁盘分区与挂载 · 网络配置
@ 目录 1:定时任务调度 1.1:crontab 1.2:at 2:磁盘分区与挂载 2.1:原理介绍 2.2:硬盘说明 2.3:磁盘目录情况查询 2.3.1:lsblk 2.3.2:df 2.3.3 ...
- 从零开始:Spring Security Oauth2 讲解及实战
OAuth2.0的四种授权模式: https://blog.csdn.net/weixin_30849403/article/details/101958273 1.授权服务配置: 配置一个授权服务, ...
- Mysql优化篇-索引优化与查询优化
1.索引失败案列 如果查询时没有使用索引,查询语句就会扫描表中所有记录,在数据量大的情况下,查询会很慢. (1)全值匹配 (2)最佳左前缀法则 mysql可以为多个字段创建索引,一个索引可以包括16个 ...
- Webpack性能优化 SplitChunksPlugin的使用详解
使用前景 在vue.react等使用webpack为项目打包工具的前端项目,在开发过程中,随着项目功能的逐渐增加,项目整体体积的不断增加,打包的时长和打包后部署的项目体积也在不停的增长,这样可能会导致 ...
- Selenium+dddocr轻松解决Web自动化验证码识别
大家好,我是狂师,今天给大家推荐一款验证码识别神器:dddocr. 1.介绍 dddocr是一个基于深度学习的OCR(Optical Character Recognition,光学字符识别)库,用于 ...