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 ...
随机推荐
- Nginx - 根据IP分配不同的访问后端
1. 需求分析 为了在线上环境提供测试分支,规定将某IP转发到测试程序地址.如果是 ngx 直接对外,采用 real_ip 就能够做限制,但是最前端确实一个7层是负载均衡就需要研究一番了. 2. 实践 ...
- 【linux基础】如何配置ubuntu系统为静态IP地址
前言 连接远程server重启的时候发现IP发生变化,影响远程连接,此时,需要将server配置为静态IP. 系统环境 ubuntu16.04 操作过程 1. 设置IP和DNS command sud ...
- python 中的eval与exec
eval类似exec,是使用python编译器运行表达式和语句两者区别在于:eval是编译表达式并返回值(如: eval("'hello'*2") 结果是 hellohello)e ...
- STL之空间配置器allocator
摘要 C++STL的空间配置器将内存的分配.释放,对象的构造.析构都分开执行,内存分配由alloc::allocate()负责,内存的释放由alloc::deallocate()负责:对象的构造由:: ...
- 033 SSM综合练习09--数据后台管理系统--基于AOP的日志处理
1.数据库与表结构 (1)日志表信息描述sysLog (2)Sql语句 CREATE TABLE sysLog ( id ) DEFAULT SYS_GUID () PRIMARY KEY, visi ...
- asp.net中的html標籤runat=server時的映射
asp.net中的html控制項runat=server時的映射 1.標準xhtml標籤:http://blog.csdn.net/TangZhongxin/archive/2009/07/31/43 ...
- Centos 7搭建Gitlab服务器超详细
一. 安装并配置必要的依赖关系在CentOS系统上安装所需的依赖:ssh,防火墙,postfix(用于邮件通知) ,wget,以下这些命令也会打开系统防火墙中的HTTP和SSH端口访问. 1.安装ss ...
- MyISAM 和 InnoDB 索引的区别
阅读目录 一 MyISAM索引实现 二 InnoDB索引实现 三 InnoDB索引和MyISAM索引的区别 回到顶部 一 MyISAM索引实现 1. 主键索引 MyISAM引擎使用B+树作为索引结 ...
- poj1458公共子序列 C语言
/*Common SubsequenceTime Limit: 1000MS Memory Limit: 10000KTotal Submissions: 56416 Accepted: 23516D ...
- c++ pipe实现父子进程通信
1.父子进程通信pipe编程流程 -创建管道 -设置进程的输出到管道 -创建进程 -关闭管道写句柄 -读管道读句柄,把数据读到一个buffer里 2.注意事项 -读管道数据的时候,一定要关闭写句柄: ...