【问题标题】:Committing transaction outside of stored procedure在存储过程之外提交事务
【发布时间】:2015-01-28 20:03:41
【问题描述】:

在执行 1 个或多个存储过程时,您可以在过程周​​围而不是在其内部放置事务吗?

$db->beginTransaction();

$db->exec("call my_procedure()");
$db->exec("call my_second_procedure()");

$db->commit();

执行上述操作 (pdo) 时,事务是在两次调用后提交,还是在每次调用运行后自动提交,从而使 beginTransaction()commit() 无用?

【问题讨论】:

    标签: php mysql stored-procedures transactions


    【解决方案1】:

    是的,你可以。

    只要没有任何程序在内部执行COMMITROLLBACKSTART TRANSACTION,并且只要没有任何程序(或您的代码)执行任何statements that cause an implicit commit,就可以正常工作。

    当您正在运行事务时,自动提交无效,即使SELECT @@autocommit; 仍会显示“1”,这仅表示您的 会话 在事务未执行时处于自动提交模式'不活跃。

    【讨论】:

    • 我希望这可行,因为根据文档,它在技术上似乎是可行的。但是,我会敦促测试以查看您的数据库在出现故障时是否一致。例如,对多个表执行INSERTS,使用从 PHP PDO 调用的多个存储过程(它们本身可能嵌入了PREPAREEXECUTEDEALLOCATE PREPARE 语句),实际上可能根本不起作用。但是,测试是我的重点。测试。
    • @AnthonyRutledge 原始问题的一个问题是$db->exec() 显然在数据库抛出错误时实际上并没有抛出异常;显然你必须手动检查PDO::errorInfo()。因此,代码“有效”但不安全,因为如果其中一个 procs 抛出错误,它只会继续滚动......但这个想法是有效的。我有一个名为 mysql.require_transaction() 的 proc,我从其他 proc 内部调用它,如果他们发现自己在没有活动事务的线程上运行,无论出于何种原因,都会导致它们提前失败。
    • 我使用 PDO 准备好的语句来调用我的存储过程。另外,我将 PDO 错误模式设置为ERRORMODE_EXCEPTION。然后,我在try/catch 块内开始我的交易。
    • 那很好。但是,除非 PDO 不厌其烦地检测并避免让你这样做(有线协议上有一个可以测试的标志位,但库似乎从未使用它),否则 MySQL 不抛出仍然是有问题的如果您在不在事务中时回滚,则会出现错误,并且在事务中启动事务被 MySQL 视为等同于发出COMMIT AND CHAIN,静默提交前一个事务并启动一个新事务。这两个都是多年前根深蒂固的设计错误,可能根深蒂固,无法修复。
    • @sqlbot 事务嵌套的东西在手册里。这不是什么新鲜事。暂时忘记exec() 方法。我在 try/catch 块内使用 PDO 和 PDO::prepare()PDO::execute() 等的方式...有效。
    【解决方案2】:

    我会说,“这取决于”:-)

    首先,如果您使用的是不支持事务的 MyISAM,PDO::beginTransaction() 仍然返回 true,但没有事务开始。

    http://php.net/manual/en/pdo.transactions.php

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-10
      • 2019-10-02
      • 2010-10-11
      • 2011-09-09
      • 2020-02-24
      • 2014-04-07
      • 1970-01-01
      相关资源
      最近更新 更多