【问题标题】:How to use transaction when using trigger in YiiYii中使用触发器时如何使用事务
【发布时间】:2013-07-26 12:30:04
【问题描述】:

我的 MySQL 数据库中有 accountsmoney 表,所以如果有任何行增加资金,accounts.balance 应该更新,首先我通过 Active Record 和 Transaction 完成

$transaction = $connection->beginTransaction();
try {
    if ($createModel->save()) {
                $account = $createModel->accounts;
                $account->balance += $createModel->amount;
                if ($account->save())
                     $transaction->commit();

    }
} catch(Exception $e){
        $transaction->rollBack();
}

现在我将其更改为 $createModel->save() 并创建触发器以更新 accounts 表,

CREATE TRIGGER before_insert_money BEFORE INSERT ON money
    FOR EACH ROW
        BEGIN
                UPDATE accounts SET balance=balance+NEW.amount WHERE id=NEW.accounts_id;
        END;

触发器是否足以确保在不使用事务的情况下更新帐户表?如果您的答案是否定的,我该如何结合触发器、事务和 ActiveRecord?

【问题讨论】:

  • 你为什么要通过触发器来那个?交易出了什么问题?
  • 我觉得它更快,它帮助我拥有更薄的控制器。
  • 认为某事更快与测量它实际上更快是不同的。即使它稍微快一点,你仍然使用煎饼杀死黄蜂,你的解决方案可能有效,但它不是触发器的用途。

标签: mysql yii triggers transactions


【解决方案1】:

恕我直言,您的方法已经足够好了。尽管我建议对您当前的触发器实现进行 2 处更改(第一个很重要,第二个可以忽略):

  1. 您可能需要AFTER 而不是BEFORE 触发器。这意味着您想将UPDATE 转换为accounts,并确保成功完成INSERT 入金。 BEFORE 触发器通常用于更改正在插入或更改的行的值或阻止对该行的操作(例如,违反约束或发出 SIGNAL)。

  2. 由于您的触发器是单语句触发器,您可以放弃 BEGIN ... END 块。这样你就不需要更改DELIMITER

话虽如此,您的触发器可能看起来像

TRIGGER before_insert_money 
BEFORE INSERT ON money
FOR EACH ROW
  UPDATE accounts 
     SET balance = balance + NEW.amount 
   WHERE id = NEW.accounts_id;

剩下的问题您是否允许更新和删除您的资金记录?如果是,那么您必须实施互补的AFTER UPDATEAFTER DELETE 触发器以正确维护帐户余额。


现在,如果您不希望有大量数据,您也可以考虑创建一个视图或通过其他方式(单独的方法)通过简单的查询即时计算帐户余额。这样您就不需要维护账户价值、处理可能发生的差异,而且它始终是准确的。

【讨论】:

  • @Moein7tl 有帮助吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-02
  • 1970-01-01
相关资源
最近更新 更多