php中使用pdo事务保证多表操作的原子性,核心方法是调用 $pdo->begintransaction() 开启事务,依次执行多条sql语句,若全部成功则调用 $pdo->commit() 提交,若中途出现异常或错误则调用 $pdo->rollback() 回滚。通过 try...catch 结构包裹这些操作,可以确保在发生数据库错误时自动撤销已执行的修改,从而维持数据的一致性。

PDO事务中如何捕获并处理SQL异常?
在PHP中,必须将PDO设置为抛出异常模式(PDO::ERRMODE_EXCEPTION),这样当SQL执行失败时才会触发 PDOException,进而被 catch 块捕获并触发回滚。如果未设置此模式,默认的错误处理可能不会中断代码流程,导致事务无法正确回滚。

<?php $dsn = 'mysql:host=localhost;dbname=test';
$user = 'root';
$password = '';
try {
// 1. 创建PDO实例并设置错误模式为异常
$pdo = new PDO($dsn, $user, $password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 2. 开启事务
$pdo->beginTransaction();
try {
// 3. 执行第一个表的操作
$sql1 = "INSERT INTO accounts (name, balance) VALUES (:name, :balance)";
$stmt1 = $pdo->prepare($sql1);
$stmt1->execute([':name' => 'Alice', ':balance' => 1000]);
// 4. 执行第二个表的操作
$sql2 = "UPDATE accounts SET balance = balance - 100 WHERE name = 'Bob'";
$stmt2 = $pdo->exec($sql2);
// 5. 如果以上都成功,提交事务
$pdo->commit();
echo "Transaction committed successfully.";
} catch (Exception $e) {
// 6. 如果任何一步出错,回滚事务
$pdo->rollBack();
echo "Transaction rolled back due to error: " . $e->getMessage();
}
} catch (PDOException $e) {
echo "Connection failed: " . $e->getMessage();
}
?>
嵌套事务在PDO中是如何处理的?
PDO本身不支持真正的嵌套事务(Nested Transactions)。如果在已经开启的事务中再次调用 beginTransaction(),它通常会被忽略或引发警告,具体取决于驱动和版本。因此,在实际开发中,应避免在事务内部再次开启新事务,而是通过逻辑判断或在应用层模拟保存点(Savepoints)来实现类似效果,但最稳妥的方式是保持事务扁平化。

<?php // 模拟嵌套事务的逻辑(伪代码示例)
$pdo->beginTransaction();
try {
// 主事务操作
$pdo->exec("INSERT INTO logs (message) VALUES ('Start')");
// 尝试开启子事务(在大多数PDO驱动中无效或报错)
// $pdo->beginTransaction(); // 不推荐这样做
// 正确的做法:使用单个事务,通过条件控制
if ($condition) {
$pdo->exec("INSERT INTO details (info) VALUES ('Detail A')");
} else {
$pdo->exec("INSERT INTO details (info) VALUES ('Detail B')");
}
$pdo->commit();
} catch (Exception $e) {
$pdo->rollBack();
}
?>
基于程序中某个输入、条件或结果的具体问题
在上述代码中,如果 $stmt1->execute() 因为唯一键冲突而失败,catch 块会捕获异常并执行 $pdo->rollBack()。此时,即使 $stmt2 尚未执行,整个事务也会回滚,确保 accounts 表中不会插入部分数据。这是保证原子性的关键:要么所有操作都生效,要么都不生效。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











