如何执行多个查询,usen commit(),如果出现问题,请回滚所有查询?
我注意到如果我将查询包装并在try / catch中提交,则只回滚不成功的查询
try{
$pdo->beginTransaction();
// create 10 tables
foreach($queries as $query)
$result = $pdo->query($query);
$pdo->commit();
}catch(PDOException $e){
// here if one of the tables fail to be created, undo all operations
$pdo->rollBack();
}
答案 0 :(得分:3)
MySQL不支持嵌入式交易。
如果您认为自己正在进行部分回滚,则表明您检错了。特别是,不成功的查询甚至不会运行,因此没有什么可以回滚。会发生什么事情是因为您忘记了START TRANSACTION
语句或因为您的表不是InnoDB而没有真正的事务。
编辑:我刚刚看到您更新了问题。您无法回滚CREATE TABLE
等DDL语句。您只能回滚DML语句(SELECT
,INSERT
,UPDATE
...)。这不是MySQL限制,它是我所知道的所有DBMS引擎中的标准行为。
答案 1 :(得分:3)
您可能遇到以下情况:
实现这种性质的唯一方法是使用检查点。就InnoDB和事务处理而言,它们将被称为保存点。
虽然您有START TRANSACTION,COMMIT和ROLLBACK命令用于在单个事务中处理整个SQL语句块,但您必须在SQL语句组之间手动注入保存点。
示例:如果您运行以下交易顺序
INSERT
10行SAVEPOINT savepoint1
UPDATE
3行SAVEPOINT savepoint2
DELETE
7行ROLLBACK TO SAVEPOINT savepoint1
结果是7个DELETE和3个UPDATE从InnoDB重做日志中消失了,但是10个INSERT仍然在日志中,可用于任何脏读,直到您执行以下操作之一:
COMMIT;
ROLLBACK;
RELEASE SAVEPOINT savepoint1
在PHP或PDO中可能没有这样的支持机制,但MySQL / InnoDB确实有这样的SQL。
请阅读MySQL文档的此部分,了解如何运行SAVEPOINT and ROLLBACK TO SAVEPOINT. There is also info on removing savepoints without COMMIT or ROLLBACK going off。
我刚刚阅读了Brian Fisher的评论,确实MySQL无法回滚表创建(Oracle可以)。实际上,任何表DDL都将提交任何未提交的数据并启动新事务。
答案 2 :(得分:1)
try{
$pdo->beginTransaction();
foreach($queries as $query)
$result = $pdo->query($query);
$pdo->commit();
}catch(PDOException $e){
$pdo->rollBack();
}