“添加重试逻辑后处理活动事务错误以避免 PHP PDO 中的死锁”

问题描述 投票:0回答:1
问题: 我在应用程序的数据库事务中遇到了死锁错误。为了解决这个问题,我添加了重试逻辑,成功解决了死锁问题。然而,现在我面临着一个新问题,我希望得到一些关于如何处理它的指导。

在添加重试逻辑之前,我经常遇到死锁错误。实现重试逻辑后,不再出现死锁错误。但是,我现在遇到了不同的错误:.

已经有活跃交易;

这是我的应用程序的设置方式:

    我有一个 connection.php 文件,它与我的 MySQL 数据库建立 PDO 连接。
  1. 我在应用程序的多个部分使用此 PDO 连接,例如脚本和查询。
  2. 在我的一个脚本中,prepare.php,我运行一个循环来执行其他几个 PHP 脚本,scripts_{$i}.php。
  3. 在每个scripts_{$i}.php脚本中,我执行SQL插入操作。
  4. 要准备插入数据,这些脚本每个可能需要 1-3 秒。
  5. 我在插入过程中添加了重试逻辑来处理死锁错误。
这是代码的简化版本:

// This is connection.php file $pdo_conn = new PDO('mysql:host='localhost';dbname=my_db', "username", "password",array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8" , PDO::ATTR_PERSISTENT => true)); $pdo_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // This is connection.php file $pdo_conn = new PDO('mysql:host='.$this->host.';dbname=bde_zeiten', $this->user_name,$this->password,array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8", PDO::ATTR_PERSISTENT => true)); $pdo_conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // This is prepare.php script; which is responsible to run insertion.php for ($i=0; $i < 40; $i++) { shell_exec("/usr/bin/php scripts_{$i}.php"); } // This is my data insertion.php script; To prepare the data, this script needs 1-3 seconds $insert_query = substr($insert_query, 0, -1); $retryAttempts = 3; $retryDelay = 100000; // Microseconds (0.1 seconds) for ($attempt = 1; $attempt <= $retryAttempts; $attempt++) { try { $pdo_conn->beginTransaction(); $stmt = $pdo_conn->prepare($insert_query); $stmt->execute(); $pdo_conn->commit(); break; } catch (PDOException $e) { if (($e->getCode() == "1213" || $e->getCode() == "40001") && $attempt <= $retryAttempts) { echo "Inside the retry logic" . PHP_EOL; usleep($retryDelay); continue; } else { echo $e->getMessage(); $pdo_conn->rollback(); break; } }
}

php mysql database pdo
1个回答
0
投票
tl;dr:您需要在异常处理中的 IF 语句的两种情况下添加回滚

为什么会出现这种情况?

使用

$pdo_conn->beginTransaction();

 即可打开交易。

在代码中,

$pdo_conn->commit();

将所有查询发送到数据库进行处理,正如您已经看到的,有许多不同的原因导致进程中断,从而导致不同的异常。

根据异常情况,有人可能不想关闭交易,而是添加其他内容! (例如,未满足某种数据库约束,并且存在默认行为)

因此,您的问题是,您无法打开另一个事务,该事务可深入到:执行

$pdo_conn->beginTransaction();

 两次而不进行回滚或成功提交。

您可能想改变对交易的理解。交易更像是一个“交互包”。一旦你添加了一些东西,它不会直接影响数据库。所以你的错误是在处理死锁的过程中,你从未关闭旧事务。

问题的解决方案是在其他错误情况下也进行回滚。

© www.soinside.com 2019 - 2024. All rights reserved.