什么时候可以将 mysql 默认隔离机制改为读已提交

69 天前
 byerer

新业务需要在事务中使用乐观锁,在 RR 下需要回滚重试整个事务,而 rc 只需要重试某一个更新,有必要改成 rc 吗,如何判断业务在满足什么条件下可以不依赖 rr ,是不是只要不依赖可重复读就行

2855 次点击
所在节点    MySQL
10 条回复
leopod1995
69 天前
RR 场景相当于在一个 transaction 中可以对一条读 sql 多次调用返回一致的结果,原理就是在一个 transaction 中生成了 snapshot 。一般不用 RC 的原因就是在一个事务中会重复调用同一条 sql 。

如果能保证一个 transaction 中没有重复 sql 的情况下,是可以替换的。
cubecube
69 天前
@leopod1995 根本不需要保证,随时都能改,oracle 默认是 rc ,用 oracle 的系统都好好的不是。rr 纯粹为了刷存在感。
Dorathea
69 天前
你都用乐观锁了, 那 RC 会比 RR 更合适吧, 毕竟你都觉得数据大概率不会冲突了
barnetime
69 天前
Georgedoe
69 天前
性能有瓶颈的时候吧 , 没瓶颈改了也没啥收益
857681664
69 天前
如果业务在一个事务中允许一个读出来的数据被其他事务更改,且不影响正常业务的逻辑就行。话说如果只是乐观锁,完全可以不用考虑 rr 还是 rc ,直接用 update 语句判断执行结果是不是更好。
iseki
68 天前
你不在乎多个请求查出的数据之间存在不一致的时候
iPisces77
68 天前
mysql 整体就是给 RR 设计的,其他数据库都是 RC,所以你改了也没啥影响
byerer
68 天前
@857681664 rr 情况下,在一个事务中,重试乐观锁的时候读不到最新数据呀,得先回滚事务
kanepan19
19 天前
@byerer

// @Transactional(rollbackFor = Exception.class,isolation = Isolation.READ_COMMITTED)
public void addBalanceByVersion(Long id, BigDecimal amount) {
//乐观锁 没有 for update
long systemTime = System.currentTimeMillis();
boolean flag = false;
while (System.currentTimeMillis() - systemTime < waitTime) {
flag = updateBalanceCheckVersion(id, amount);
if (flag) {
break;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
if (!flag) {
throw new BizException("加款超时,稍后再试");
}

}

要么不用事务,要么就加上 isolation = Isolation.READ_COMMITTED
都用事务了 老老实实的 select for update 或者 update xx set balance = balance - amount . 如果要记录流水还是 行锁。

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

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

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

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

© 2021 V2EX