MySQL的select for update用法
MySQL中的select for update大家应该都有所接触,但什么时候该去使用,以及有哪些需要注意的地方会有很多不清楚的地方,我把我如何使用和查询到的文档在此记录。
作用
select本身是一个查询语句,查询语句是不会产生冲突的一种行为,一般情况下是没有锁的,用select for update 会让select语句产生一个排它锁(X), 这个锁和update的效果一样,会使两个事务无法同时更新一条记录。
什么时候使用
我认为的错误的用法
在网上看到一篇文章, 里面讲到用select for update来产生一个悲观锁,保证库存的一致性,其他update在更新的时候本身就有悲观锁,不会让另外一个事务更新,如果按照他的写法update goods set stock = stock - 1 where id = 1;是没必要先去查询的
我认为的正确的用法(1)
有时我们确实需要先将数据查询出来,然后再去更新,但我们不想的是,我刚查询完结果没还更新,这时被其他事务更新了,例如上面的例子,如果我想先查询库存,确认库存是否足够,如果足够就去更新,不够就返回一个错误
begin;
select * from goods where id = 1;
// 检查库存足够代码
update goods set stock = stock - 1 where id = 1;
commit;
如果不用for update的情况下,在检查库存时,被其他事务更新了库存,就会产生库存不足,但是当前事务以为充足的情况发生, 所以使用for update先锁住这条记录,其他事务不能去更改这条记录直到当前事务提交
我认为的正确的用法(2)
在我们实际业务中,一个订单要扣除多个补剂的库存,这时要用事务保证一个订单多个补剂同时扣除成功或者同时失败,可能会出现这样的情况,M订单需要补剂a,b,c三种补剂,N订单需要c,e,a三种补剂,这时两个事务同时执行,M事务扣除ab库存,N事务库存c,e库存,因为update会产生排它锁阻止其他事务更新当前事务已经更新的记录,所以这会产生死锁,M在等待获取c的锁,N在等待获取a的锁,在订单比较多的情况下,这种冲突很容易出现,我的解决方法是当M需要a,b,c三种补剂时,使用select for update锁定三条记录,此时N订单select for update获取不到c的锁直到M订单事务提交
2022.03.29 Update: 经过很长一段时间工作之后,我发现我认为的正确用法(2)是错误的,这个和select for update没有关系,关键是要对共享资源进行排序,例如:有a-z共26中补剂,M订单需要a、d、e,N订单需要d、h、z,这这种情况中,谁先拿到冲突的资源谁会先执行完,因为冲突的资源后面的资源肯定不是冲突的,也就是说只使用事务+多个update也可以实现
至于其他的用法可以我后面遇到会再总结进去
注意事项
- select for update会根据where条件来锁多条记录, 根据where条件的字段是不是索引来决定锁定表还是锁定行,同时根据是聚簇索引还是二级索引和查询条件(范围查询还是精确查询)来决定锁定特定的行还是一个范围内的行
- 当锁定范围的行时会有gap lock和next-key来防止插入新的行参考StackOverFlow
SELECT * FROM information_schema.innodb_trx \G使用该语句可以查询某个事务锁了几个表,锁了几个行
参考
[1] MySQL InnoDB存储引擎(三):锁及事务模型
MySQL的select for update用法的更多相关文章
- mysql锁SELECT FOR UPDATE【转】
MySQL 使用SELECT ... FOR UPDATE 做事务写入前的确认 以MySQL 的InnoDB 为例,预设的Tansaction isolation level 为REPEATABLE ...
- MySQL 使用SELECT ... FOR UPDATE 做事务写入前的确认(转)
Select…For Update语句的语法与select语句相同,只是在select语句的后面加FOR UPDATE [NOWAIT]子句. 该语句用来锁定特定的行(如果有where子句,就是满足w ...
- MySQL中select * for update锁表的范围
MySQL中select * for update锁表的问题 由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例 ...
- MySQL中select * for update锁表的问题
MySQL中select * for update锁表的问题 由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例 ...
- MySql事务select for update及数据的一致性处理讲解
MySQL中的事务,默认是自动提交的,即autocommit = 1: 但是这样的话,在某些情形中就会出现问题:比如: 如果你想一次性插入了1000条数据,mysql会commit1000次的, 如果 ...
- 数据库:Mysql中“select ... for update”排他锁分析
Mysql InnoDB 排他锁 用法: select … for update; 例如:select * from goods where id = 1 for update; 排他锁的申请前提:没 ...
- Mysql中“select ... for update”排他锁(转)
原帖地址 https://blog.csdn.net/claram/article/details/54023216 Mysql InnoDB 排他锁 用法: select … for update; ...
- MySQL的SELECT ...for update
最近的项目中,因为涉及到Mysql数据中乐观锁和悲观锁的使用,所以结合项目和网上的知识点对乐观锁和悲观锁的知识进行总结. 悲观锁介绍 悲观锁是对数据被的修改持悲观态度(认为数据在被修改的时候一定会存在 ...
- MySQL中select * for update锁表的问题(转)
由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例) ,否则MySQL将会执行Table Lock (将整个资料 ...
- mysql中select distinct的用法
在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条,但 往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的 ...
随机推荐
- Pod的dns记录怎么组成的
Pod的dns记录怎么组成的 <Pod Name>.<service name>.<namespace name>.svc.cluster.local Pod的Na ...
- Beats processors
文章转载自:https://elasticstack.blog.csdn.net/article/details/111321105 我们通常的做法是使用 Elasticsearch 的 ingest ...
- PAT (Advanced Level) Practice 1001 A+B Format 分数 20
Calculate a+b and output the sum in standard format -- that is, the digits must be separated into gr ...
- NSIS皮肤插件:vcl-styles-plugins
vcl-styles-plugins简介 NSISVCLStyles plugin (dll)是一款应用于nsis安装程序的皮肤插件,插件大小约为1.6MB,实际应用在安装程序中压缩后约为550 ...
- Gson的使用与理解
当今社会下,前后端分离,不同系统的信息交互,消息队列的数据传递,微服务的不同服务之间的数据处理,越来越多地方用到了序列化.序列化作为不同系统不同服务之间的数据桥梁.那么方便快捷的序列化工具还是必要的. ...
- Linux基础_1_简介
Linux是什么 一款优秀的操作系统软件,特性是一切皆文件:一切设备皆文件!一切设备的设置皆修改配置文件!一切服务的搭建皆修改配置文件!(庞大的树形结构文件系统) 根据FHS标准,Linux目录有以下 ...
- .NET 6学习笔记(4)——如何在.NET 6的Desktop App中使用Windows Runtime API
Windows Runtime API是当初某软为了区别Win32 API,力挺UWP而创建的另一套Windows 10专用的API集合.后来因为一些原因,UWP没火.为了不埋没很有价值的Window ...
- 《吐血整理》高级系列教程-吃透Fiddler抓包教程(30)-Fiddler如何抓取Android7.0以上的Https包-番外篇
1.简介 通过宏哥前边几篇文章的讲解和介绍想必大家都知道android7.0以上,有android的机制不在信任用户证书,导致https协议无法抓包.除非把证书装在系统信任的证书里,此时手机需要roo ...
- 2.httprunner-yaml用例结构
前言: httprunner3.x版本弱化了api层的概念 直接在testcase中写request请求 如果是单个请求,也可以直接写成一个testcase 每个testcase必须具有两个类属性:c ...
- vuex和浏览器【sessionStorage,localStorage ..】 得区别
1.Vuex的主要作用是用来共享和管理数据,那为什么不直接使用浏览器缓存呢?2.Vuex和浏览器缓存策略的根本区别是什么?3.Vuex,state仓库中的数据流是单向同步的,那为什么可以在action ...