Database 如何使数据库事务原子化(所有部分都完成或没有)?

Database 如何使数据库事务原子化(所有部分都完成或没有)?,database,transactions,Database,Transactions,比如说,我有一个储蓄账户和一个支票账户。我的储蓄账户余额是150美元。我想把100美元从我的储蓄账户转到支票账户,也把100美元从我的储蓄账户转到我朋友的账户 将100美元从我的储蓄账户转到我的支票账户的步骤: 1.1。读取(当前保存余额) 1.2。将储蓄余额减少100 1.3。我的支票余额加100 将100美元从我的储蓄账户转移到朋友账户的步骤: 2.1。读取(当前保存余额) 2.2。将储蓄余额减少100 2.3。在我朋友的帐户余额上加100 我想同时执行这些事务。如果它们都在开始时读取了sa

比如说,我有一个储蓄账户和一个支票账户。我的储蓄账户余额是150美元。我想把100美元从我的储蓄账户转到支票账户,也把100美元从我的储蓄账户转到我朋友的账户

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

1.1。读取(当前保存余额)

1.2。将储蓄余额减少100

1.3。我的支票余额加100

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

2.1。读取(当前保存余额)

2.2。将储蓄余额减少100

2.3。在我朋友的帐户余额上加100


我想同时执行这些事务。如果它们都在开始时读取了saving_balance,那么它们都可以将saving_balance减少100$,但是,只有一个能够成功。在银行系统中如何处理这一问题。

不需要序列化隔离级别(但是,不同数据库系统的确切loggin语义非常不同)

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

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


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

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

      BEGIN TRAN
      
      UPDATE  accounts
      SET balance = balance-100
      WHERE   account='1'
      
      UPDATE  accounts
      SET balance = balance + 100
      WHERE   account='2'
      
      COMMIT TRAN
      
      我建议您多阅读以了解数据库事务


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

      使用“可序列化”隔离级别。您需要指定您的数据库平台。每个事务的实现方式不同。