1

比方说,我有一个储蓄账户和一个支票账户。我的储蓄账户余额是 150 美元。我正在尝试将 100 美元从我的储蓄账户转移到支票账户,同时将 100 美元从我的储蓄账户转移到我朋友的账户。

将 100 美元从我的储蓄账户转移到我的支票账户的步骤:

1.1。读取(current_saving_balance)

1.2. 将 Saving_balance 减少 100

1.3. 将 100 添加到我的检查余额

将 100 美元从我的储蓄账户转移到我朋友的账户的步骤:

2.1。读取(current_saving_balance)

2.2. 将 Saving_balance 减少 100

2.3. 给我朋友的账户余额加 100

我想同时执行这些事务。如果他们在开始时都读取了 Saving_balance,则两者都可以将 Saving_balance 减少 100 美元,但是,他们中应该只有一个能够成功。这在银行系统中是如何处理的。

4

3 回答 3

0

下面是如何在 tSQL 中执行此操作,您的数据库可能在语法上有所不同。

BEGIN TRAN

UPDATE  accounts
SET balance = balance-100
WHERE   account='1'

UPDATE  accounts
SET balance = balance + 100
WHERE   account='2'

COMMIT TRAN

我建议您阅读这篇文章以更多地了解 DB 事务。

忽略评论中正在进行的整个可序列化隔离对话。它并没有真正解决您描述的问题。

于 2013-02-23T04:49:15.867 回答
0

不需要可序列化的隔离级别(但是确切的登录语义因数据库系统而异)。

  • 执行 select for update 作为第一条语句,然后执行其余事务。第一个执行 select for update 的事务将锁定该行,另一个事务将被阻塞,直到第一个事务提交(悲观锁定)
  • 确保执行更新语句时它仍然具有与读取时相同的值,否则重新执行

  • 不需要显式读取数据,一个简单的更新语句就足够了(但是需要有逻辑来检查账户中是否有足够的资金,这可以通过触发器来实现)。

于 2013-02-23T04:14:09.700 回答
0

您有两笔实际交易(1. 将 100 美元转入支票。2. 将 100 美元转给朋友),而您正在尝试在单个技术交易中进行交易(开始;...;提交)。我认为这是错误的方法。您的代码必须反映实际交易,即开始;... 1. 将 100 美元转入支票。;犯罪; 开始; ... 2. 将 100 美元转给朋友)。;犯罪; 有一些数据库功能,可以在每次交易前检查余额并决定是否保存。

于 2013-02-23T04:31:30.340 回答