【问题标题】:Uncaught exception 'PDOException' with message 'There is no active transaction'?带有消息“没有活动事务”的未捕获异常“PDOException”?
【发布时间】:2012-02-23 18:08:15
【问题描述】:

这是我用来插入记录的代码。每当出现插入错误时,即使我已经回滚,订阅者表自动增加数仍然会增加?问题是什么? 我只是希望发生错误时不添加自动增量编号。非常感谢您的帮助。

$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$conn->setAttribute(PDO::ATTR_AUTOCOMMIT, FALSE);
$conn->beginTransaction();
try {

    $email = $_POST['Email'];
    $FirstName = $_POST['FirstName'];
    $LastName = $_POST['LastName'];


    $query="INSERT INTO subscriber (Email,FirstName,LastName,CreateDate) VALUES (?,?,?,CURDATE())";
    $stmt = $conn->prepare($query);


    $stmt->bindParam(1, $email , PDO::PARAM_STR);
    $stmt->bindParam(2, $FirstName, PDO::PARAM_STR);
    $stmt->bindParam(3, $LastName, PDO::PARAM_STR);
    $stmt->execute();
    $conn->commit();

}
catch(PDOException $e)
    {
    $conn->rollBack();
    die ($e->getMessage()."<a href='addSub.php'>Back</a>");
    }

$conn->beginTransaction();
try {
    $userID = $_SESSION['username'];
    $query="INSERT INTO list_sub (SubID,ListID) VALUES ('',$_SESSION[ListID])";
    $stmt = $conn->prepare($query);
    $stmt->execute();
    $conn->commit();

}
catch(PDOException $e)
    {
    $conn->rollBack();
    die ($e->getMessage()."<a href='addSub.php'>Back</a>");
    }

$conn = null;}

【问题讨论】:

    标签: php mysql pdo


    【解决方案1】:

    PDO 的自动提交可能已启用,当您尝试回滚时它会导致问题,因为它已经提交。您可以使用PDO::ATTR_AUTOCOMMIT 禁用此行为:

    $conn->setAttribute(PDO::ATTR_AUTOCOMMIT, FALSE);
    

    【讨论】:

    • 谢谢我把它放在 $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); ,可以吗?
    • @user782104:是的,应该没问题。请记住,禁用此设置后,您必须手动提交每个查询。
    【解决方案2】:

    如果不知道代码中的行号,很难知道,但是您在第一个 try-catch 块的末尾提交了事务,然后在第二次尝试中继续进行而不启动新事务-catch 块。

    在第二个 try-catch 块的开头添加 $conn-&gt;beginTransaction();

    编辑 - 您提到“我只想在发生错误时不添加自动增量编号”。您不应依赖自动递增功能来生成“无间隙”的数字序列。

    【讨论】:

    • 它不会再次显示该错误消息,但是,它不会回滚。每当出现错误时,订阅者表仍然会增加自动递增数
    • 它应该自动递增 - 这是预期的行为。
    • 这意味着我必须在我的 php 代码中使用一些 sql 语句,例如 'set table auto-inc number = x -1' 来回滚它?谢谢~
    • 正确 - 您必须明确设置它。
    • 如果在交易过程中,其他人也在开始交易,您会发生什么。你回滚,他们继续。他们的自动递增列应该如何处理?
    【解决方案3】:

    在 apache(或者可能是其他执行连接池的机制)下运行时,您可能需要检查并确保您没有使用持久连接。

    这是因为当连接池生效时,您不能保证对 -&gt;commit() 的调用最终会在您调用 -&gt;beginTransaction() 的同一连接上结束。

    这种情况体现在您使用多个数据库句柄执行多个查询的情况下,并且只有一个系列的查询属于一个事务,您已尽职尽责地将其绑定到特定的数据库句柄(变量)。但是,在您下方,池连接管理器可能会在任何可用连接中发送您的查询,只要您没有通过禁用其中一个句柄的持久性来指定“独占”使用。

    在我的例子中,我正在执行一个包含一系列步骤的事务。由于代码由完成事务中特定任务的函数组成,一些函数会衍生出一个单独的数据库连接来执行一些相关的查询(例如,验证表行中标识的资产的所有权)。在 apache 环境中运行,我会收到此错误“没有活动事务”,此外,rollBack() 调用似乎无效——即使他调用 commit 报告了错误,更改也已提交。

    我花了一段时间将其缩小到持久连接。关闭我正在为其执行事务的句柄上的连接池使事情按我预期的方式工作。

    【讨论】:

      猜你喜欢
      • 2012-07-08
      • 2014-11-15
      • 1970-01-01
      • 2014-01-23
      • 2014-07-14
      • 2014-03-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多