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这个关键字来过滤掉多余的重复记录只保留一条,但 往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的 ...
随机推荐
- 使用kubectl命令删除某个目录下所有的yaml文件
kubectl delete -f .
- Elastic:Elasticsearch的分片管理策略
- Ubuntu转到root用户后用户名路径没有颜色
看到好多都直接把普通会用户的.bashrc配置复制到root家目录下,由于本人小白,很多.bashrc配置看不懂,也不敢随便修改.于是找到别的配置方法. 普通用户的os@a:~$和root用户的roo ...
- 基于Netty的TCP服务框架
19年写的一个基础的TCP服务框架,内置了一个简单IOC容器,当时的目标是一方面能作为组件供第三方集成实现TCP通讯相关功能,另一方面作为提供一种服务框架范式.所以框架核心点主要还是通过适度的封装,隐 ...
- VS中git概念解析与深度使用
基础概念 四个区 工作区(Working Area) 暂存区(Stage) 本地仓库(Local Repository) 远程仓库(Remote Repository) 五种状态 未修改(Origin ...
- 一篇文章让你搞懂Java中的静态代理和动态代理
什么是代理模式 代理模式是常用的java设计模式,在Java中我们通常会通过new一个对象再调用其对应的方法来访问我们需要的服务.代理模式则是通过创建代理类(proxy)的方式间接地来访问我们需要的服 ...
- JDK 8之前日期和时间的API
JDK 8之前日期和时间的API(1) System类中的currentTimeMillis():返回当前时间与1970年1月1日0时0分0秒之间以毫秒为单位的时间差.称为时间戳. java.util ...
- 4.MongoDB系列之索引(一)
1. 执行计划查看 db.getCollection('users').find({'username': 'shenjian'}).explain('executionStats') 结果查看,先大 ...
- 怎样在GitHub上建立仓库、以及怎样实现分支代码的合并。保姆级别的教程
GitHub官网地址:https://github.com/ 注意:前提是已经注册了GitHub 文章目录 第一步:创建一个新的仓库 第二步.创建一个分支 第三步.编辑和发布更改的内容 第四步.拉取请 ...
- 3.httprunner-extract/.env/Testcase
参数关联-extract 场景:上一个接口的返回值,传给下一个接口当请求参数 extract:提取变量 $变量名 :引用变量 假设我们有如下场景 用户A登录之后,返回值返回用户UID,我们需要查询该用 ...