gpt4 book ai didi

java - 避免 Oracle 死锁的正确设计?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:44:03 24 4
gpt4 key购买 nike

在谈到避免死锁时,通常的建议是始终以相同的顺序锁定资源。但是,对于内容丰富的 Oracle 数据库中的行锁,您将如何实现这一点?

要理解我的意思,请考虑以下示例。一个非常简单的 DAO 来处理银行账户:

@Component
public class AccountDao {

@Resource
private DataSource dataSource;

public void withdraw(String account, int amount) {
modifyBalance(account, -amount);
}

public void deposit(String account, int amount) {
modifyBalance(account, amount);
}

private void modifyBalance(String account, int amount) {
try {
Connection connection = DataSourceUtils.getConnection(dataSource);
PreparedStatement statement = connection
.prepareStatement("update account set balance = balance + ? where holder = ?");
statement.setInt(1, amount);
statement.setString(2, account);
statement.execute();
}
catch (SQLException e) {
throw new RuntimeException(e);
}
}
}

要在两个账户之间执行转账,有一些 InternalBankTransfer 类有转账方法:

    public void transfer(String from, String to, int amount) {
// start transaction
accountDao.withDraw(from, amount);
accountDao.deposit(to, amount);
// commit transaction
}

通常这工作正常。但是假设我们有两个人同时发起转账。假设安妮想转 100 美元给鲍勃,同时鲍勃想转 50 美元给安妮。所以在一个线程中 Anne 调用 transfer("Anne", "Bob", 100),而在另一个 Bob 调用 transfer("Bob", "Anne", 50) .这段代码容易死锁,如果执行顺序如下:

T1: accountDao.withDraw("Anne", 100);
T2: accountDao.withDraw("Bob", 50);
T1: accountDao.deposit("Bob", 100);
T2: accountDao.deposit("Anne", 50); // BAM! ORA-00060: deadlock detected while waiting for resource

我承认在开始看到实际应用程序中的死锁之前我根本没有考虑过这一点。我天真的观点是事务隔离自动处理了这个问题。甲骨文表示,这是由于应用程序设计不当造成的。但是在这种情况下什么是好的设计呢?我是否需要选择更新我计划更新的所有内容?如果这是一个涉及更新多个表的巨大事务怎么办?我应该设计成不可能出现死锁还是尽量减少死锁并接受 they are a fact of life?

最佳答案

我认为这是生活中的一个事实(而且只有在高并发和热点数据的情况下才会真正发生)。

如果您想实现锁定顺序,那么是的,您需要重写代码以按预定顺序锁定或更新帐户(首先是 Anne,然后是 Bob)。但这对于复杂的交易是不可行的。如果它只发生在少数热点行上,也许您可​​以只对这些行使用锁定排序(其余的保持原样)并通过它来解决。

或者使用更细粒度的锁,但这会破坏你的并发性。

在您的情况下,您可以重试中止的交易。如果它经常发生,那么您的应用程序设计似乎确实存在问题。

这里是 a link for a two-phase commit protocol用于银行账户转账。它来自 MongoDB wiki,即来自一开始甚至没有行锁和事务的人,但也可以在 RDBMS 上实现它以避免锁争用。那当然是一个相当激进的应用程序重新设计。我会先尝试其他所有方法(重试、粗锁、人为降低的并发级别、批处理)。

关于java - 避免 Oracle 死锁的正确设计?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7428578/

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