使用 select ...for update 时,Mysql 可重复读取获取其他会话的提交

Posted

技术标签:

【中文标题】使用 select ...for update 时,Mysql 可重复读取获取其他会话的提交【英文标题】:Mysql repeatable read get other session's commit when use select ...for update 【发布时间】:2017-08-08 03:31:18 【问题描述】:

我的表的定义是

创建表auto_inc (

id int(11) NOT NULL AUTO_INCREMENT,

主键 (id)

) ENGINE=InnoDB 默认字符集=latin1

一开始有四行:

|身份证|

| 1 |

| 2 |

| 3 |

| 4 |

我打开了会话 1 并执行了

#session 1
set transaction isolation level REPEATABLE READ
start transaction;
select * from auto_inc

返回四行1,2,3,4。然后我打开另一个会话2并执行

#session 2
insert into auto_inc(`id`) values(null)

并插入成功。返回我执行的会话 1

#session 1
select * from auto_inc;#command 1
select * from auto_inc for update;#command 2

命令 1 返回四行 1,2,3,4。但是命令 2 返回 1,2,3,4,5。谁能给我一些线索,为什么命令 2 会看到会话 2 的插入? 提前致谢!

【问题讨论】:

因为“撤消区域”不允许共享锁定。因此,命令 2 检索新数据,忽略导致“幻读”的快照。 【参考方案1】:
    为什么会话 2 可以插入新数据?

在 REPEATABLE READ 下,第二个 SELECT 保证看到第一次选择时看到的行没有变化。并发事务可以添加新行,但不能删除或更改现有行。

https://***.com/a/4036063/3020810

    为什么session 1可以看到插入?

在 REPEATABLE READ 下,同一事务中的一致读取读取由第一次读取建立的快照。如果您想查看数据库的“最新”状态,请使用 READ COMMITTED 隔离级别或锁定读取,以及select ... for update 是锁定读取。

一致的非锁定读取:https://dev.mysql.com/doc/refman/5.6/en/innodb-consistent-read.html

【讨论】:

以上是关于使用 select ...for update 时,Mysql 可重复读取获取其他会话的提交的主要内容,如果未能解决你的问题,请参考以下文章

MySQL 之 SELECT FOR UPDATE

Oracle编辑数据时提示:这些查询结果不可更新,请使用ROWI或者SELECT……FOR UPDATE获得可更新结果

数据库中Select For update语句的解析

Django 的 select_for_update 方法是不是与 update 方法一起使用?

SELECT … FOR UPDATE 对不存在的行

MySQL的SELECT.FOR UPDATE究竟起啥作用