繁体   English   中英

找出数据库死锁

[英]Figure out database deadlock

我正在尝试编写springboot代码以根据DEBIT / CREDIT交易更新钱包余额 我有两张桌子,也就是。 钱包交易 我正在运行一个测试套件,该套件运行100个并行事务(50借方和50贷方)。 约有50%的交易失败并出现以下错误,并且钱包 表中的钱包余额与交易 表中存储的交易不匹配

com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:尝试获取锁时发现死锁; 尝试重新启动事务

我无法找出以下1)为什么死锁2)为什么钱包余额与成功存储的交易数量不匹配。 我将MySQL InnoDB用于数据库

@Transactional(isolation = Isolation.SERIALIZABLE)
  public Transaction saveTransaction(String walletId, Txn txn) {
    Optional<Wallet> byId = walletRepo.findById(Integer.parseInt(walletId));
    if (!byId.isPresent()) {
      throw new WalletNotFoundException();
    }
    Wallet wallet = byId.get();
    Transaction transaction = new Transaction();
    transaction.setAmount(txn.getAmount());
    transaction.setType(txn.getType());
    transaction.setWallet(wallet);
    BigDecimal balance = applyTransactionToWallet(txn, wallet.getBalance());
    Transaction save = transactionRepo.save(transaction);
    wallet.setBalance(balance);
    return save;
  }

  public Optional<Wallet> getWallet(String walletId) {
    Optional<Wallet> byId = walletRepo.findById(Integer.parseInt(walletId));
    return byId;
  }

  private BigDecimal applyTransactionToWallet(Txn txn, BigDecimal amount) {
    if (txn.getType() == TransactionType.CREDIT) {
      return amount.add(txn.getAmount());
    }
    return amount.subtract(txn.getAmount());
  }

我通过在下面的行中使用findByIdInWriteMode而不是findById修复了死锁。

 Optional<Wallet> byId = walletRepo.findById(Integer.parseInt(walletId));

我将回购更改为

@Repository
public interface WalletRepo extends JpaRepository<Wallet, Integer> {
  @Query(value = "FROM Wallet W where W.walletId = :id")
  @Lock(LockModeType.PESSIMISTIC_WRITE)
  Optional<Wallet> findByIdInWriteMode(@Param("id") Integer id);
}

如果您希望100%的即时一致性,则可以探索功能锁定概念,将涉及一项交易的钱包保留在功能锁定表中。 因此,开始时的每笔交易都会检查钱包中是否有任何功能锁,如果有,请等到它可以得到功能锁为止,否则将其插入功能锁中并继续进行交易。 在功能锁表中添加条目应该是原子的,并具有自己的提交。 在交易结束时,删除锁定条目。

如果您正在寻找最终的一致性(具有延迟的一致性),则可以考虑使事务更新排队,并且守护程序可以一个接一个地处理排队的项目,再次使用功能锁定概念来避免多个守护程序为同一个钱包处理事务。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM