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存储引擎(三):锁及事务模型
最新文章
- ASP.Net MVC开发基础学习笔记:四、校验、AJAX与过滤器
- WriteFile实现下载
- archlinux locale-gen 命令出错
- Android apk 的安装过程
- 限额类费用报销单N+1原则
- 关于bootstrap--表格(table的各种样式)
- eclipse中默认的提示键
- Git 系列(五):三个 Git 图形化工具
- CSharp Oracle 登陆
- [翻译] 编写高性能 .NET 代码--第五章 通用编码与对象设计 -- 类 vs 结构体
- JSP 学习总结 03 核心组件 Servlet
- C#+EntityFramework编程方式详细之Model First
- IP通信基础课堂笔记----关于数链层
- RPC web service
- 【C#数据结构系列】栈和队列
- 转:PHPStorm+XDebug进行调试图文教程
- 机器学习初入门02 - Pandas的基本操作
- Python nose单元测试框架结合requests库进行web接口测试
- jquery自动填充输入框
- [MongoDB]------windos远程服务器部署连接
热门文章
- 采用docker方式安装ElastAlert,图形化配置告警规则----具体内容有删改,仅供查看
- centos7安装sonarqube-9.2.4
- Logstash:如何处理 Logstash pipeline 错误信息
- Linux make编译
- 定制开发 ERP 的优势有哪些?
- pthread_mutex_t &; pthread_cond_t 总结
- Rdt2.1 和 Rdt2.2的详细解释
- Docker | 容器互联互通
- LeetCode------移动零(5)【数组】
- AI带你省钱旅游!精准预测民宿房源价格!