gpt4 book ai didi

java - 具有 READ COMMITTED 隔离级别的 SQL 并发 'select then update' 模式

转载 作者:行者123 更新时间:2023-12-02 04:58:58 25 4
gpt4 key购买 nike

我们有一个集群 Java 应用程序,在 mysql 5.5 数据库、InnoDb 引擎上运行。该应用程序使用 Spring,事务隔离级别设置为 SERIALIZABLE .

在一个可能并发执行的方法内部,无论是在一个节点的不同线程中还是在单独的节点中,都有一种典型的 SELECT-then-UPDATE 模式。这是伪代码:

old_status = null;
do {
old_status = SELECT status
FROM bookings
WHERE code=123;

affected_rows = UPDATE bookings
SET status=<new_status>
WHERE code=123 AND status=<old_status>;

} while (affected_rows == 0);

// Now we can do stuff with <old_status> value

字段code是PK; <old_status><new_status>总是不同。

SELECTUPDATE单独事务上运行。

这个效果非常好。我什至认为AND status=<old_status>检查WHERE UPDATE 的条款语句是不必要的,因为事务隔离级别是 SERIALIZABLE ,这意味着可以安全地发出 SELECT然后是 UPDATE不检查 status 的值字段。

所以,第一个问题:(1) 当事务隔离级别为 SERIALIZABLE 时,这一切都是不必要的,我可以吗? ?

现在发生的事情是,几天前,DBA 突然出现在我的工作场所,并带来了“证明”我们应该开始使用的论点和指标 READ_COMMITED事务隔离级别。由于他几乎从不离开他的地下墓穴,我立刻就知道他是认真的。他说如果我们把事务隔离级别从SERIALIZABLE改为至READ_COMMITED ,cpu 的使用率会下降 10%,查询运行速度会快很多,等等。简而言之,他有他的论点让我们切换到 READ_COMMITED事务隔离级别。

那么,第二个问题:(2)我们可以愉快地切换到READ_COMMITED吗?事务隔离级别,假设我们已经检查 status 的值WHERE 中的字段UPDATE 的条款句子通过AND status=<old_status>

我认为我们可以,但想先与社区核实一下。提前致谢!

注意:我无法使用 native 构造,例如 mysql 的 SELECT ... FOR UPDATE 等。

最佳答案

如果两者都在单独的事务中,您需要比较旧值。您所做的是乐观应用程序事务中的一种简单技术,称为比较和设置。所以是的,你可以自由选择。

关于读取已提交隔离级别,它在事务中唯一有趣。如果你只有一个选择或更新,如果我正确理解 Oracle 的实现,那么它根本不应该有任何区别。 Oracle 仅访问表中的单行一次,并且将重用已经获得的那些信息。但在某些情况下,它可能无法重用这些信息( session 缓存外的条款等)。

因此,这需要高度的理解,并且不应该在不考虑每笔交易对某些变化(我指的是所有潜在变化)的影响的情况下进行。因此,如果您希望正确完成此操作,您的成本可能会飙升。

我永远不会轻易改变隔离级别,特别是如果你没有为此设计的话。

关于java - 具有 READ COMMITTED 隔离级别的 SQL 并发 'select then update' 模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28481627/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com