【问题标题】:Transaction doesn't fail even if one of operations fails即使其中一项操作失败,事务也不会失败
【发布时间】:2017-12-06 15:32:28
【问题描述】:

所以我在玩交易,我试图从一个转移到另一个中减去资金。从图片中可以看出,第一次更新查询不成功……不像第二次,它执行成功。现在,我所期待的是,当我提交时,我不会看到任何更改。但事实并非如此。另外,我使用了START TRANSACTION(它隐式地将autocommit 设置为0),而不是BEGIN 命令。

这是这个的输出:

我在这里缺少什么?

【问题讨论】:

  • 第一次查询非常成功,只是没有更新记录。
  • @HoneyBadger 哦,我明白了。那么,如果这被认为是成功的,如果特定账户上没有足够的资金,如何回滚交易呢?
  • 我没听懂,你的例子中的两个更新似乎彼此无关,那么如果第一个不更新任何记录,你为什么要回滚呢?
  • @HoneyBadger 它们并非无关。我只是在 MySQL 中玩事务,所以一切似乎都有些混乱。不过,它们是相关的。我正在将资金从一个账户转移到另一个账户。所以,我从 Fred 的账户中取出 50 美元,然后将它们寄给 Bob 的账户。当然,如果 Fred 的账户上没有足够的资金,我想回滚一切......
  • 我认为 Gordon 给了你一个很好的指导。通常,如果出现资金不足的情况,您会希望它带有红色的大感叹号。这就是为什么我会在应用程序中这样做,而不是让数据库安静地处理它。

标签: mysql sql transactions commit acid


【解决方案1】:

我不明白你的困惑。您的两次更新都成功了。第一个碰巧没有影响任何行,所以只有第二个真正改变了数据。

您提交了事务,所以所有更改都会生效。

如果您想测试事务,请回滚事务。然后,当您查看数据时,您会发现没有任何变化。

【讨论】:

  • 嗯...我明白了。那么,如果我想限制从没有资金的账户中扣除资金,我将不得不使用某种 CHECK 约束?我的意思是,如果没有足够的资金,我该如何让交易失败?
  • @Whirlwind 。 . .写一个存储过程,使用if逻辑。在事务中,检查第一个是否影响任何行。如果没有,则回滚事务。 (嗯,没有变化,所以回滚/提交做同样的事情。)
  • @Whirlwind 。 . .检查约束在 MySQL 中对您没有帮助,因为数据库不强制执行它们。
  • 是的,谢谢。我知道这一点。这就是为什么,我说过“某种 CHECK 约束”......我的意思是某种替换。
【解决方案2】:

您的任何操作都没有失败。

  1. 在第一次更新中,条件不满足,因此没有任何 行已更新。
  2. 在第二个中,一条记录满足条件,因此更新了一条记录。

【讨论】:

    【解决方案3】:

    作为对Gordon's answer 和他提到的存储过程的补充,我将为未来的读者和完整性添加一个答案,因为我真正的问题是如果不满足某些条件如何回滚事务:

    DELIMITER //
    
    CREATE PROCEDURE transfer(IN sender INT, IN receiver INT)
    
    BEGIN
    
      START TRANSACTION;
    
       SET @senderBalance = (SELECT balance FROM bank_acc WHERE acctnum =  sender LIMIT 1);
       select @senderBalance;
    
        IF (@senderBalance < 50) THEN
          ROLLBACK;
        ELSE
    
        update bank_acc set balance = balance - 50 where acctnum = sender;
        update bank_acc set balance = balance + 50 where acctnum = receiver;
    
          COMMIT;
        END IF;
    END//
    
    
    DELIMITER ;
    

    以后,你可以这样使用它:

    call transfer(@sender := 20, @receiver := 10);
    

    【讨论】:

    • @GordonLinoff 如果您发现有问题,请随时评论或编辑此帖子。但这对我有用。
    猜你喜欢
    • 2018-12-13
    • 2016-06-23
    • 2016-10-12
    • 2018-12-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-21
    相关资源
    最近更新 更多