在 postgresql 中实现“帐户”事务

Den*_*ard 6 postgresql

我正在研究可以在 Postgresql 9.5 中实现的简单帐户功能的不同方式。我希望能够以最大的“可重复读取”作为事务隔离级别来做到这一点。之所以应该是“可重复读”隔离级别,是因为我们检测到了高级别的冲突“可序列化”隔离级别,即使在 10 秒内使用 10 次左右的重试策略,由于冲突的数量,它仍然失败。

  • 存钱
  • 提款
  • 如果用户余额小于零(用户金额总和),则无法提款
  • 余额永远不能低于零(用户的金额总和)

它应该处理多个连接和多个用户,并且同一用户可以在不同的连接中发起存款和取款。

我目前唯一的解决方案是执行以下操作:

对于存款:

  1. 允许直接存款作为插入。

对于提款:

  1. 在继续之前检查余额> 取款金额。
  2. 插入状态为已启动的取款交易。
  3. 如果处于状态(已启动、已完成)的用户的交易总和小于零,则更新提款交易状态失败。
  4. 如果状态已启动,则更新提款交易状态已完成。

欢迎任何材料或示例。

Eva*_*oll 4

  • 存款好主意:允许直接存入资金作为插入物。
  • 提款的坏主意:在继续之前检查余额>提款金额。
    • 考虑进行 CHECK(余额 >= 0),然后允许事务失败。

我不确定其余的人。你提到了所有这些状态的东西,但这有什么关系呢?

BEGIN;
UPDATE accounts
  SET balance = balance - 100
  WHERE name = 'Bob';
UPDATE accounts
  SET balance = balance + 100
  WHERE name = 'Sally';
END;
Run Code Online (Sandbox Code Playgroud)
  • 如果账户余额在扣除后低于 0,那么它就会失败。
  • 如果通过,您将看到 Bob 的交易余额减少。
  • 向 Sally 的帐户添加 100 是轻而易举的事,但现在您也可以锁定它了。

默认事务级别允许幻读,但这不是问题。第一个语句是一个UPDATE. 它要么有效,要么无效。如果有效,UPDATE则获得ROW EXCLUSIVE锁定。UPDATE在事务提交之前,其他人不会对该记录进行操作。