当我与pdo的连接很长时,执行事务插入操作,我手动断开连接或mysql自动断开连接一段时间,我重新获取连接执行事务将继续执行最后一个操作,导致数据被插入数据库
mysql5.7
$pdoOptions = [
\PDO::ATTR_TIMEOUT => 30,
\PDO::ATTR_PERSISTENT => true,
];
$dsn = "mysql:host=mysql;port=3306;dbname=test;charset=utf8";
$connection = new \PDO($dsn, 'root', 'root', $pdoOptions);
try{
$connection->beginTransaction();
$smtm = $connection->prepare("INSERT INTO classic(class_name)VALUES(:name)");
$smtm->bindValue(':name','111');
$smtm->execute();
throw new \Exception('Manual exception throwing');
$connection->commit();
}catch (\Throwable $e){
echo ('Received exception information thrown:' . $e->getMessage());
echo "\n";
try{
$connection->rollBack();
}catch (\Throwable $e2){
echo ('Exception fired by rollback:' . $e->getMessage());
echo "\n";
}
}
$connection = null;
echo 'connection Set to null, the current pdo link is broken';
echo "\n";
$connection = new \PDO($dsn, 'root', 'root', $pdoOptions);
echo 'Set to null and get the new link again to determine whether it is in the transaction:' .($connection->inTransaction()?'是':'否');
echo "\n";
$connection->beginTransaction();
echo 'BeginTransaction to start a transaction';
echo "\n";
try{
echo('New link transaction open status:'.($connection->inTransaction()?'yes':'no'));
echo "\n";
$smtm = $connection->prepare("INSERT INTO classic(class_name)VALUES(:name)");
echo ('Current linked transaction status after connection->prepare() execution:'.($connection->inTransaction()?'yes':'no'));
echo "\n";
$smtm->bindValue(':name','222');
// echo $smtm->queryString;
$smtm->execute();
echo 'After the new link is obtained, an exception is thrown and the second execution fails to roll it back';
echo "\n";
throw new \Exception('The second transaction executes, throwing an exception manually');
$connection->commit();
}catch (\Throwable $e){
echo ('Get new link exception catch:' . $e->getMessage());
echo "\n";
try{
$connection->rollBack();
}catch (\Throwable $e2){
echo ('The exception triggered by the second rollback:' . $e2->getMessage());
echo "\n";
}
}
表
CREATE TABLE `classic` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`class_name` VARCHAR(50) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
COLLATE='utf8_general_ci'
ENGINE=InnoDB
AUTO_INCREMENT=1;
此代码使数据库实际插入一条数据
答案 0 :(得分:0)
第二次交易非常奇怪,有些人如何找到一种提交的方式。 将第二个连接名称更改为$ connection1并运行。
<?php
namespace app;
ini_set('display_errors', 1);
$pdoOptions = [
\PDO::ATTR_TIMEOUT => 30,
\PDO::ATTR_PERSISTENT => true,
];
$dsn = "mysql:host=localhost;port=3306;dbname=test;charset=utf8";
$connection = new \PDO($dsn, 'root', 'infiniti', $pdoOptions);
try{
$connection->beginTransaction();
$smtm = $connection->prepare("INSERT INTO classic(class_name)VALUES(:name)");
$smtm->bindValue(':name','111');
$smtm->execute();
throw new \Exception('Manual exception throwing');
$connection->commit();
}catch (\Exception $e){
echo ('Received exception information thrown:' . $e->getMessage());
echo "\n";
try{
$connection->rollBack();
}catch (\Exception $e2){
echo ('Exception fired by rollback:' . $e->getMessage());
echo "\n";
}
}
$connection = null;
echo 'connection Set to null, the current pdo link is broken';
echo "\n";
$connection1 = new \PDO($dsn, 'root', 'infiniti', $pdoOptions);
echo 'Set to null and get the new link again to determine whether it is in the transaction:' .($connection1->inTransaction()?'yes':'no');
echo "\n";
$connection1->beginTransaction();
echo 'BeginTransaction to start a transaction';
echo "\n";
try{
echo('New link transaction open status:'.($connection1->inTransaction()?'yes':'no'));
echo "\n";
$smtm = $connection1->prepare("INSERT INTO classic(class_name)VALUES(:name)");
echo ('Current linked transaction status after connection->prepare() execution:'.($connection1->inTransaction()?'yes':'no'));
echo "\n";
$smtm->bindValue(':name','222');
// echo $smtm->queryString;
$smtm->execute();
echo 'After the new link is obtained, an exception is thrown and the second execution fails to roll it back';
echo "\n";
throw new \Exception('The second transaction executes, throwing an exception manually');
echo 'wowowowo'."\n";
$connection1->commit();
}catch (\Exception $e){
echo ('Get new link exception catch:' . $e->getMessage());
echo "\n";
try{
$connection1->rollBack();
}catch (\Exception $e2){
echo ('The exception triggered by the second rollback:' . $e2->getMessage());
echo "\n";
}
}
?>
答案 1 :(得分:0)
关闭连接时,您应同时关闭两者 连接对象以及 语句对象
$ connection = null; $ smtm = null;
我想这应该解决您的问题。花了更多时间修复!
<?php
namespace app;
ini_set('display_errors', 1);
$pdoOptions = [
\PDO::ATTR_TIMEOUT => 30,
\PDO::ATTR_PERSISTENT => true,
];
$dsn = "mysql:host=localhost;port=3306;dbname=test;charset=utf8";
$connection = new \PDO($dsn, 'root', 'infiniti', $pdoOptions);
try{
$connection->beginTransaction();
$smtm = $connection->prepare("INSERT INTO classic(class_name)VALUES(:name)");
$smtm->bindValue(':name','111');
$smtm->execute();
throw new \Exception('Manual exception throwing');
$connection->commit();
}catch (\Exception $e){
echo ('Received exception information thrown:' . $e->getMessage());
echo "\n";
try{
$connection->rollBack();
}catch (\Exception $e2){
echo ('Exception fired by rollback:' . $e->getMessage());
echo "\n";
}
}
$connection = null;
$smtm = null;
echo 'connection Set to null, the current pdo link is broken';
echo "\n";
$connection = new \PDO($dsn, 'root', 'infiniti', $pdoOptions);
echo 'Set to null and get the new link again to determine whether it is in the transaction:' .($connection->inTransaction()?'yes':'no');
echo "\n";
$connection->beginTransaction();
echo 'BeginTransaction to start a transaction';
echo "\n";
try{
echo('New link transaction open status:'.($connection->inTransaction()?'yes':'no'));
echo "\n";
$smtm = $connection->prepare("INSERT INTO classic(class_name)VALUES(:name)");
echo ('Current linked transaction status after connection->prepare() execution:'.($connection->inTransaction()?'yes':'no'));
echo "\n";
$smtm->bindValue(':name','222');
// echo $smtm->queryString;
$smtm->execute();
echo 'After the new link is obtained, an exception is thrown and the second execution fails to roll it back';
echo "\n";
throw new \Exception('The second transaction executes, throwing an exception manually');
echo 'wowowowo'."\n";
$connection->commit();
}catch (\Exception $e){
echo ('Get new link exception catch:' . $e->getMessage());
echo "\n";
try{
$connection->rollBack();
}catch (\Exception $e2){
echo ('The exception triggered by the second rollback:' . $e2->getMessage());
echo "\n";
}
}
?>