lock in share mode 和 select for update
lock in share mode 和 select for update
同步发表于:http://blog.lanjingdejia.com/articles/2018/07/11/1531245873812.html
许多同学或应该都听过"select … lock in share mode" 和 “select … for update”,但是或多或少会有以下几个疑问:
- 这俩货是什么含义?
- 和普通的select有什么区别呢?
- 什么场景下用?用哪个?
含义
我们直接从mysql官网上看它们的定义:
SELECT … LOCK IN SHARE MODE
Sets a shared mode lock on any rows that are read. Other sessions can read the rows, but cannot modify them until your transaction commits. If any of these rows were changed by another transaction that has not yet committed, your query waits until that transaction ends and then uses the latest values.
翻译一下:在你正在读的行设置一个共享锁,其他session也可以读这些行,但是直到你读完这些行,事务提交释放锁之后,其他sesstion才能更改这些行。如果你要读取的行正在被其他session修改,那么读取会卡住,直到其他session修改完毕,读取才能继续,并且读到的是最新版本的数据。
SELECT … FOR UPDATE
For index records the search encounters, locks the rows and any associated index entries, the same as if you issued an UPDATE statement for those rows. Other transactions are blocked from updating those rows, from doing SELECT … LOCK IN SHARE MODE, or from reading the data in certain transaction isolation levels.
翻译一下:对于select的数据,会对这些行及其相关行加锁,效果和用update更新这些行时是一样的。其他对这些数据进行操作,无论是update也好,上面提到的SELECT … LOCK IN SHARE MODE也好,甚至在某些事务隔离级别下读取这些数据也好,所有这些操作都会被阻塞。
通俗一点
lock in share mode能保证读到的一定是最新的值,而且保证读的过程中不会被其他session修改。因为加的是共享锁,所以多个session同时lock in share mode时都可以读到数据。
select for update更严格一些,加的是排它锁(根据情况,有时还会加间隙锁),会阻塞住所有其他session对该数据的操作。
和普通的select的区别
mysql(InnoDB)的select有三种:
- 啥也不加的普通的select
- select … lock in share mode
- select … for update
上面提到的共享锁、排它锁等等,这些锁对普通的select是没有用的,普通的select是永远不会被阻塞的。下面举例说明。
普通select和lock in share mode的区别
- session A正在修改(update或者delete)某一行数据,如果这时session B进行普通的select,session B是不会被阻塞的,且读到的是session A修改之前的数据。如果这时session C进行select … lock in share mode,那么session C将会阻塞,直到session A所在的事务提交(或者回滚释)放锁之后,session C才会继续进行,且读到的使session A修改过后的数据。
- session A 正在进行普通的select,如果这时session B 进行update操作,那么session B不会被阻塞。但是如果session A进行的是select … lock in share mode,那么session B的update操作会被阻塞,直到session A提交之后,session B才能继续进行。
普通select和select for update的区别
区别同上
lock in share mode和select for update的区别
- session A正在 lock in share mode, 此时session B 进行lock in share mode 操作不会被阻塞,但是如果此时session C进行select for update的话,就会被阻塞。
- 如果session A 正在select for update,如果此时session B 进行lock in share mode, 那么session B会被阻塞,如果此时session C也进行select for update操作,那么session C也会被阻塞。
使用场景
select … lock in share mode的使用场景
引用mysql官网的例子,有两张表:parent表和child表,向child表插入数据时,要保证child的parent在parent表中存在,删除parent表时,会将parent以及该parent的child都删掉。一般的操作是先select,得到parentId,然后向child中插入一条数据(关联parentId),但是这样是有问题的,如果select之后,插入之前,另一个session将parent删掉了,那么向child表中插入的数据并不会受到影响,最终造成该child没有parent的状况。
根据上面提到的特性,select时用select … lock in share mode就能解决这个问题。其实select … lock in share mode 在平时用到的场景很少很少,用的比较多的还是select … for update。
select … for update的使用场景
账户表中有一个字段money,取出来后,将money更新(比如加上一个值)后再存进去。对于这个场景,如果两个session同时select,比如都取出来的是100,然后都加30, 都变成130,然后都update money,最终money的值是130,与预期的160不符。这个时候用select … for update 就能完美解决这个问题,这时因为两个session不能同时select … for update。
思考
上述select … for update的场景如果使用select … lock in share mode会怎样?
答案是,会很大概率造成死锁,造成死锁的原因是:session A和session B同时select lock in share mode, 这时都未提交事务,session A 继续执行update操作,此时因为session B事务还没提交,锁还没释放,所以session A的update操作会被阻塞,等待session B释放锁,同样的,session B此时也在等待session A提交事务释放锁,这就发生了死锁。
所以lock in share mode 使用时要仔细检查,确认该场景是否真的适用且不会发生死锁。
lock in share mode 和 select for update的更多相关文章
- 深入理解SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE
概念和区别 SELECT ... LOCK IN SHARE MODE走的是IS锁(意向共享锁),即在符合条件的rows上都加了共享锁,这样的话,其他session可以读取这些记录,也可以继续添加IS ...
- SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE locks在RR模式下可以看到最新的记录
14.5.2.4 Locking Reads 锁定读: 如果你查询数据然后插入或者修改相关数据在相同的事务里, 常规的SELECT 语句不能给予足够的保护. 其他事务可以修改或者删除你刚查询相同的记录 ...
- [MySQL] 行级锁SELECT ... LOCK IN SHARE MODE 和 SELECT ... FOR UPDATE
一.译文 翻译来自官方文档:Locking Reads If you query data and then insert or update related data within the same ...
- SELECT LOCK IN SHARE MODE and FOR UPDATE
Baronwrote nice article comparing locking hints in MySQL and SQL Server. In MySQL/Innodb LOCK IN SHA ...
- MySql事务select for update及数据的一致性处理讲解
MySQL中的事务,默认是自动提交的,即autocommit = 1: 但是这样的话,在某些情形中就会出现问题:比如: 如果你想一次性插入了1000条数据,mysql会commit1000次的, 如果 ...
- Select for update/lock in share mode 对事务并发性影响
select for update/lock in share mode 对事务并发性影响 事务并发性理解 事务并发性,粗略的理解就是单位时间内能够执行的事务数量,常见的单位是 TPS( transa ...
- 转 MYSQL SELECT ... FOR UPDATE and SELECT ... LOCK IN SHARE MODE Locking Reads
原文: http://dev.mysql.com/doc/refman/5.0/en/innodb-locking-reads.html In some circumstances, a consis ...
- Mysql加锁过程详解(4)-select for update/lock in share mode 对事务并发性影响
Mysql加锁过程详解(1)-基本知识 Mysql加锁过程详解(2)-关于mysql 幻读理解 Mysql加锁过程详解(3)-关于mysql 幻读理解 Mysql加锁过程详解(4)-select fo ...
- 浅谈select for update 和select lock in share mode的区别
有些情况下为了保证数据逻辑的一致性,需要对SELECT的操作加锁.InnoDB存储引擎对于SELECT语句支持两种一致性的锁定读(locking read)操作. . SELECT …… FOR UP ...
随机推荐
- EasyDSS高性能RTMP、HLS(m3u8)、HTTP-FLV、RTSP流媒体服务器功能简介---视频直播、直播鉴权(如何完美将EasyDSS过渡到新版)
作为RTMP流媒体服务器,接受RTMP推流.进行实时的直播流分发是EasyDSS流媒体服务自身一大核心功能.写本篇博文的一个目的是向大家介绍EasyDSS新版的直播间.匿名直播.和虚拟直播的功能, 另 ...
- 通过下载git包来安装git
Git是一个开源的分布式版本控制系统,可以有效.高速的处理从很小到非常大的项目版本管理.而国外的GitHub和国内的Coding都是项目的托管平台.但是在使用Git工具的时候,第一步要学会如何安装gi ...
- DDD分层架构的三种模式
引言 在讨论DDD分层架构的模式之前,我们先一起回顾一下DDD和分层架构的相关知识. DDD DDD(Domain Driven Design,领域驱动设计)作为一种软件开发方法,它可以帮助我们设计高 ...
- [转帖]插曲:大白话带你认识Kafka
插曲:大白话带你认识Kafka 2019-11-18 21:58:27 从事Java 阅读数 2更多 分类专栏: java Kafaka 版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA ...
- 工厂方法(FactoryMethod)模式
之前说了简单工厂设计模式如果增加一个新的运算的时候需要:增加一个具体的实现类,工厂类中增加一个case分支.也就是说我们不但对扩展开发了,也对修改开放了,违背了开闭原则.当然如果工厂类采用反射的话不存 ...
- Resouce Pool的理解
本篇文章从现象到本质再到具象去理解 , 从理论到实战再到源码回顾去深化. 1.在开发中,无处不在的池. eg 网络通信连接池: HttpClient连接池 HttpClient通过PoolingHtt ...
- Python进阶:并发编程之Asyncio
什么是Asyncio 多线程有诸多优点且应用广泛,但也存在一定的局限性: 比如,多线程运行过程容易被打断,因此有可能出现 race condition 的情况:再如,线程切换本身存在一定的损耗,线程数 ...
- Go 关键字Select
select select 是Go语言中常用的一个关键字,Linux再也早也引入了这个函数,用来实现非阻塞的一种方式,一个select语句用来选择哪个case中的发送或接收操作可以被立即执行.它类似于 ...
- S02_CH12_ AXI_Lite 总线详解
S02_CH12_ AXI_Lite 总线详解 12.1前言 ZYNQ拥有ARM+FPGA这个神奇的架构,那么ARM和FPGA究竟是如何进行通信的呢?本章通过剖析AXI总线源码,来一探其中的秘密. 1 ...
- AESUtil
AESUtil package cn.ucaner.alpaca.common.util; import sun.misc.BASE64Decoder; import sun.misc.BASE64E ...