数据库事务隔离级别问题

241 天前
 leichnX
可能我这个问题提的有点儿肤浅,大佬们别嘲笑。我有个疑问,可重读级别下,读的数据可能是个假的,是个老版本的,这到底有啥作用。
2385 次点击
所在节点    数据库
31 条回复
leichnX
241 天前
@watzds 这个例子很赞,确实有这么一些场景,套个可重读的隔离级别上去就可以少考虑不少事儿了,减小写代码的复杂度。
leichnX
241 天前
@git00ll 这两次查询查两张表,可重读会帮忙把它们时间间隙卡的很短吗,以前还真没了解过这个。它会和 Java 多线程一样使得两个查询之间线程不会中断吗?
git00ll
241 天前
@leichnX 不是时间间隙卡的很短。 当事物内进行第一条 sql 查询的时候就会生成一个快照版本号,并且对所有的表生效。相当于给所有的表生成了快照。 所以能够保证后续的查询(无论哪张表)都是那一瞬间的快照值,因此能够保证读一致性。
leichnX
241 天前
@git00ll 仔细想想感觉不对啊,比如手动执行 sql 的时候,先启动事务,在执行第一条查询查表 1 ,等五秒再执行第二条查询查表 2 ,这中间别人要是插了数据进表 2 去,肯定是会查出来的,什么隔离级别也会查到插进去的新数据。
git00ll
241 天前
@leichnX 针对数据插入就是 “幻读” 问题了,“可重复读” 指的是数据更新。

并且 Mysql RR 级别是能解决快照读的幻读问题的, 如你描述两次查询中间被插入符合条件的数据并不会被查出来。
leichnX
241 天前
@git00ll 又测了一下,你说的是对的,我开始拿 SERIALIZABLE 测了一遍,结果和我说的一样,我想当然的以为可重读也是会读到新插数据或改的数据。然而可重读读到的还真是旧数据,这很牛逼,很重要。

事务 A
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN

SELECT *
FROM 表 1 ;

转过去执行事务 B

SELECT *
FROM 表 2 ; //发现读到的是旧数据
commit;

事务 B
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN
UPDATE 表 2
SET Name='22'
leichnX
241 天前
@watzds 明白了,和 20 说的是一回事,在需要获取跨表一致性数据的时候,这个可重读级别很重要。
luoqeng
241 天前
vczyh
241 天前
可复重读隔离级别内在含义是可以保证一致性,当你第一次执行 select 语句的时候就决定了接下来你能读到什么数据,这些数据跟其他事务是否修改没有关系。
orzwalker111
241 天前
mvcc 保证了 rr 下可重复读,mvcc 是 undo log 链和 readview 视图实现的,这个视图是在事务开启后执行第一个快照读时,基于 [整个库] 生成的快照。也就是说这个快照中的“账单、明细这两个表数据已经不会变了“
10 楼所举的例子很合适,不要局限于”单张表在一个事务中的多次查询“这种场景
leichnX
239 天前
@orzwalker111 不要局限于”单张表在一个事务中的多次查询“这种场景 这句话说的太对了,然而从学校到社会,可重读这个问题大多数人都是拿单张表说事儿,太容易让人困惑了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1026735

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX