在添加重试逻辑之前,我经常遇到死锁错误。实现重试逻辑后,不再出现死锁错误。但是,我现在遇到了不同的错误:.
已经有活跃交易;这是我的应用程序的设置方式:
// 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;
}
}
}
为什么会出现这种情况?
使用
$pdo_conn->beginTransaction();
即可打开交易。在代码中,
$pdo_conn->commit();
将所有查询发送到数据库进行处理,正如您已经看到的,有许多不同的原因导致进程中断,从而导致不同的异常。根据异常情况,有人可能不想关闭交易,而是添加其他内容! (例如,未满足某种数据库约束,并且存在默认行为)
因此,您的问题是,您无法打开另一个事务,该事务可深入到:执行
$pdo_conn->beginTransaction();
两次而不进行回滚或成功提交。您可能想改变对交易的理解。交易更像是一个“交互包”。一旦你添加了一些东西,它不会直接影响数据库。所以你的错误是在处理死锁的过程中,你从未关闭旧事务。
问题的解决方案是在其他错误情况下也进行回滚。