我试图根据另一个代码块的结果回滚一个PDO事务。如果DB插入失败但是如果"其他东西"抛出异常,它没有回滚提交。我做错了什么?
PHP版本5.4,数据库是MS SQL
<?php
try {
$dbh = new PDO($dataSource);
$dbh->beginTransaction();
$sql = "INSERT INTO $table
(field1, field2, etc)
VALUES
(:field1, :field2, :etc)"
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':field1', $data["field1"]);
$stmt->bindParam(':field2', $data["field2"]);
$stmt->bindParam(':etc', $data["etc"]);
$stmt->execute();
$dbh->commit();
//do some other stuff which can throw an Exception
} catch (Exception $e) {
//make sure we have something to roll back
try { $dbh->rollBack(); } catch (Exception $e2) {}
$log->logFatal("Error: controller.inc.php: " . $e->getMessage());
}
?>
答案 0 :(得分:1)
调用commit()
有效地完成了beginTransaction()
之前开始的开放式交易,因此在调用commit()
之后,rollBack()
没有剩余数据库操作。
如果您希望在成功提交后运行其他代码,则可以在if()
块中检查其返回值。如果提交操作本身失败,PDO::commit()
将返回FALSE
,因此您可以通过抛出另一个异常来阻止您的邮件操作。
try {
$dbh = new PDO($dataSource);
$dbh->beginTransaction();
// etc...
// etc...
// Attempt to commit, and do other actions if successful
if ($pdo->commit()) {
// Do other actions
// mail, etc...
}
else {
// Otherwise, throw another exception which your catch {} will handle
throw new Exception('Transaction was not committed');
}
} catch (Exception $e) {
// Docs are unclear on whether rollBack() will throw an error on failure
// or just return false. It is documented to throw an exception if
// no transaction is actually active.
try { $pdo->rollBack(); } catch (Exception $e2) {}
// Log your error, either a normal PDO error, or failed commit()...
$log->logFatal("Error: controller.inc.php: " . $e->getMessage());
}
}