Ari*_*iel 6 php mysql mysqli commit rollback
我已经阅读了在线 php 手册,但我仍然不确定这两个函数的工作方式:mysqli::commit 和 mysqli::rollback。
我要做的第一件事是:
$mysqli->autocommit(FALSE);
Run Code Online (Sandbox Code Playgroud)
然后我提出一些疑问:
$mysqli->query("...");
$mysqli->query("...");
$mysqli->query("...");
Run Code Online (Sandbox Code Playgroud)
然后我通过执行以下操作提交由这 3 个查询组成的事务:
$mysqli->commit();
Run Code Online (Sandbox Code Playgroud)
但是,在这些查询之一不起作用的不幸情况下,所有 3 个查询都被取消还是我必须自己调用回滚?我希望所有 3 个查询都是原子的,并且只被视为一个查询。如果一个查询失败,那么所有 3 个查询都应该失败并且没有任何效果。
我问这个是因为在我在手册页上看到的评论中:http : //php.net/manual/en/mysqli.commit.php 如果其中一个查询失败,用户 Lorenzo 会调用回滚。
如果 3 个查询是原子的,回滚有什么好处?我不明白。
编辑:这是我怀疑的代码示例:
<?php
$all_query_ok=true; // our control variable
$mysqli->autocommit(false);
//we make 4 inserts, the last one generates an error
//if at least one query returns an error we change our control variable
$mysqli->query("INSERT INTO myCity (id) VALUES (100)") ? null : $all_query_ok=false;
$mysqli->query("INSERT INTO myCity (id) VALUES (200)") ? null : $all_query_ok=false;
$mysqli->query("INSERT INTO myCity (id) VALUES (300)") ? null : $all_query_ok=false;
$mysqli->query("INSERT INTO myCity (id) VALUES (100)") ? null : $all_query_ok=false; //duplicated PRIMARY KEY VALUE
//now let's test our control variable
$all_query_ok ? $mysqli->commit() : $mysqli->rollback();
$mysqli->close();
?>
Run Code Online (Sandbox Code Playgroud)
我认为这段代码是错误的,因为如果任何查询失败,$all_query_ok==false那么您不需要回滚,因为事务没有被处理。我对吗?
我认为这段代码是错误的,因为如果任何查询失败并且 $all_query_ok==false 那么你不需要回滚,因为事务没有被处理。我对吗?
不,如果单个 SQL 语句失败,事务不会跟踪。
如果单个 SQL 语句失败,则该语句将回滚(如@eggyal 的回答中所述)-但事务仍处于打开状态。如果您commit现在调用,成功语句不会回滚,您只是将“损坏的”数据插入到数据库中。您可以轻松重现这一点:
m> CREATE TABLE transtest (id INT NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100) NOT NULL DEFAULT '',
CONSTRAINT UNIQUE KEY `uq_transtest_name` (name)) ENGINE=InnoDB;
Query OK, 0 rows affected (0.07 sec)
m> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
m> INSERT INTO transtest (name) VALUE ('foo');
Query OK, 1 row affected (0.00 sec)
m> INSERT INTO transtest (name) VALUE ('foo');
ERROR 1062 (23000): Duplicate entry 'foo' for key 'uq_transtest_name'
m> INSERT INTO transtest (name) VALUE ('bar');
Query OK, 1 row affected (0.00 sec)
m> COMMIT;
Query OK, 0 rows affected (0.02 sec)
m> SELECT * FROM transtest;
+----+------+
| id | name |
+----+------+
| 3 | bar |
| 1 | foo |
+----+------+
2 rows in set (0.00 sec)
Run Code Online (Sandbox Code Playgroud)
您会看到“foo”和“bar”的插入成功,尽管第二个 SQL 语句失败了 - 您甚至可以看到AUTO_INCREMENT错误查询增加了 -value。
因此,您必须检查每个query-call的结果,如果失败,则调用rollback以撤消否则成功的查询。所以洛伦佐在 PHP 手册中的代码是有道理的。
强制 MySQL 回滚事务的唯一错误是“事务死锁”(这是特定于 InnoDB 的,其他存储引擎可能会以不同的方式处理这些错误)。