【发布时间】:2023-03-03 05:14:28
【问题描述】:
我使用 PHP PDO 事务。我有插入和更新语句,我想在 rowCount() 返回 0 时回滚事务。请参阅下面的示例代码。
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'root', '', array(
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_EMULATE_PREPARES => false
));
$userIds = [1,2,""];
$paymentAmounts = [10.50,20.50,30.50];
$error = array();
$pdo->beginTransaction();
try
{
foreach($userIds as $key => $userId )
{
$sql = "INSERT INTO payments (user_id, amount) VALUES (?, ?)";
$stmt = $pdo->prepare($sql);
$stmt->execute(array(
$userId,
$paymentAmounts[$key]
)
);
if($stmt->rowCount() <= 0)
{
$error[] = ["Error occurred in userId: ".$userId];
}
$sql = "UPDATE users SET credit = ? WHERE id = ?";
$stmt = $pdo->prepare($sql);
$stmt->execute(array(
$paymentAmounts[$key],
$userId
)
);
if($stmt->rowCount() <= 0)
{
$error[] = ["Error occurred in userId: ".$userId];
}
}
if(!empty($error))
{
$displayError = implode(",", $error);
throw new Exception($displayError);
}
// It should not reach here, if there is an error.
$pdo->commit();
}
catch(Exception $e){
echo $e->getMessage(); // displayError
$pdo->rollBack(); // <<<==== It should rollback both Insert and Update to original state
}
?>
我有 $userIds 数组。对于 userId 1 和 2,rowCount() 将为插入和更新返回 1。但是对于空的 userId,rowCount() 将返回 0。如果 rowCount() 为 0,我将错误消息分配给 $error[]。如果 $error 不为空,它将捕获 Exception 并回滚所有 $userId 的事务。
我的预期结果是当 $error 不为空时,将抛出异常并在 catch 中回滚。它应该假设删除表支付中 userIds (1,2) 的记录,并更新回表 users 中 userIds (1,2) 的原始信用值。
我得到的结果是当代码到达 $pdo->rollBack() 时,它只从支付表中删除插入的记录,并且它没有将原始信用值更新回用户表中的 userIds (1, 2).
您能否就代码的问题提出建议? 谢谢。
========== 查询创建表和插入语句 ==========
-- CREATE TABLE "payments" -------------------------------
CREATE TABLE `payments` (
`id` BigInt( 11 ) UNSIGNED AUTO_INCREMENT NOT NULL,
`user_id` BigInt( 11 ) UNSIGNED NOT NULL,
`amount` VarChar( 20 ) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
PRIMARY KEY ( `id` ) )
CHARACTER SET = latin1
COLLATE = latin1_swedish_ci
ENGINE = InnoDB
AUTO_INCREMENT = 1;
-- -------------------------------------------------------------
-- CREATE TABLE "users" -------------------------------
CREATE TABLE `users` (
`id` BigInt( 11 ) UNSIGNED AUTO_INCREMENT NOT NULL,
`credit` VarChar( 20 ) CHARACTER SET latin1 COLLATE latin1_swedish_ci NOT NULL,
PRIMARY KEY ( `id` ) )
CHARACTER SET = latin1
COLLATE = latin1_swedish_ci
ENGINE = InnoDB
AUTO_INCREMENT = 1;
-- -------------------------------------------------------------
INSERT INTO `users` ( `credit`, `id`)
VALUES ( '5', 1 ),( '10', 2 ),( '15', 3 );
【问题讨论】:
-
你的代码应该包含一个表创建查询和插入查询来填充它,这样每个人都可以确认行为。 How to create MCVE for a PDO related problem
-
不过是个疯狂的猜测。您的用户的表引擎确实是 InnoDB 吗?
-
是的,它是 InnoDB。感谢您的回复。
-
我已经添加了表格和插入查询。
-
您应该提供旨在一次性运行的完整代码。让一个人复制并粘贴它并获得结果。但是请确保您事先自己运行它,它实际上支持您声称某些表不会回滚
标签: php mysql pdo transactions rollback