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存储引擎(三):锁及事务模型

[2] SELECT FOR UPDATE作用字段提问

MySQL的select for update用法的更多相关文章

  1. mysql锁SELECT FOR UPDATE【转】

    MySQL 使用SELECT ... FOR UPDATE 做事务写入前的确认 以MySQL 的InnoDB 为例,预设的Tansaction isolation level 为REPEATABLE ...

  2. MySQL 使用SELECT ... FOR UPDATE 做事务写入前的确认(转)

    Select…For Update语句的语法与select语句相同,只是在select语句的后面加FOR UPDATE [NOWAIT]子句. 该语句用来锁定特定的行(如果有where子句,就是满足w ...

  3. MySQL中select * for update锁表的范围

    MySQL中select * for update锁表的问题 由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例 ...

  4. MySQL中select * for update锁表的问题

    MySQL中select * for update锁表的问题 由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例 ...

  5. MySql事务select for update及数据的一致性处理讲解

    MySQL中的事务,默认是自动提交的,即autocommit = 1: 但是这样的话,在某些情形中就会出现问题:比如: 如果你想一次性插入了1000条数据,mysql会commit1000次的, 如果 ...

  6. 数据库:Mysql中“select ... for update”排他锁分析

    Mysql InnoDB 排他锁 用法: select … for update; 例如:select * from goods where id = 1 for update; 排他锁的申请前提:没 ...

  7. Mysql中“select ... for update”排他锁(转)

    原帖地址 https://blog.csdn.net/claram/article/details/54023216 Mysql InnoDB 排他锁 用法: select … for update; ...

  8. MySQL的SELECT ...for update

    最近的项目中,因为涉及到Mysql数据中乐观锁和悲观锁的使用,所以结合项目和网上的知识点对乐观锁和悲观锁的知识进行总结. 悲观锁介绍 悲观锁是对数据被的修改持悲观态度(认为数据在被修改的时候一定会存在 ...

  9. MySQL中select * for update锁表的问题(转)

    由于InnoDB预设是Row-Level Lock,所以只有「明确」的指定主键,MySQL才会执行Row lock (只锁住被选取的资料例) ,否则MySQL将会执行Table Lock (将整个资料 ...

  10. mysql中select distinct的用法

    在使用mysql时,有时需要查询出某个字段不重复的记录,虽然mysql提供有distinct这个关键字来过滤掉多余的重复记录只保留一条,但 往往只用它来返回不重复记录的条数,而不是用它来返回不重记录的 ...

随机推荐

  1. parted创建磁盘分区并创建LVM(Linux合并多块大于2T的磁盘并合并到一个分区)

    文章转载自:https://blog.csdn.net/likemebee/article/details/85630808

  2. 解决zeal离线文档下载慢问题

    zeal简介 编程过程中难免会遇到不会用的关键字和方法,对我而言,在windows下,我使用Zeal这个软件进行离线文档查询. 问题 但是,在软件中下载DocSet(文档)会出现下载慢,或者下载不了的 ...

  3. filebeat中增加其他参数用来区分不同的日志来源示例

    filebeat.yml配置文件参数 在source里加入了一个fields叫做"appach: true". filebeat.inputs: - type: log enabl ...

  4. logstash 读取MySQL数据到elasticsearch 相差8小时解决办法

    logstash和elasticsearch是按照UTC时间的,kibana却是按照正常你所在的时区显示的,是因为kibana中可以配置时区信息. 具体看这个: logstash 的配置文件添加 fi ...

  5. TTD 专题 (第一篇):C# 那些短命线程都在干什么?

    一:背景 1.讲故事 在分析的众多dump中,经常会遇到各种奇葩的问题,仅通过dump这种快照形式还是有很多问题搞不定,而通过 perfview 这种粒度又太粗,很难找到问题之所在,真的很头疼,比如本 ...

  6. 微软出品自动化神器Playwright(Playwright+Java)系列(四) 之 浏览器操作

    写在前面 今天是国庆节的最后一天,明天又要上班了,真的是感觉好像才开始放假一样,还是因为失恋没缓过来吗? 我的国庆七天 第1天,当了近半天的司机,陪家人去各大超市去购物,下午在家躺····· 第2-5 ...

  7. 220403 考试爆炸记 (T1T2)

    T1 最大约数和 先放一下我考时的代码.(没想到能A过洛谷的数据,可能是洛谷的数据有点弱) #include<bits/stdc++.h> using namespace std; int ...

  8. HDU1561 The more, The Better(树形背包)

    通过这道题对树形背包理解更深一步...... 有几个地方需要注意: 1.本题数据结构为森林,需增加一个超根作为根节点,M+=1(后面解释). 2.本题有拓扑序的限制,通过vector建成的一棵树中,必 ...

  9. vue2双向绑定原理:深入响应式原理defineProperty、watcher、get、set

    响应式是什么?Vue 最独特的特性之一- 就是我们在页面开发时,修改data值的时候,数据.视图页面需要变化的地方变化. 主要使用到哪些方法? 用 Object.defineProperty给watc ...

  10. 简单将Springboot项目部署到linux服务器上

    1.使用springboot的jar包方式 直接使用maven工具按照步骤点击就可以直接打包 2.到target目录下找到 jar包 3.将jar包放到linux的任意文件夹下(此项目是之前的kafk ...