gpt4 book ai didi

php - mysqli::commit 和 mysqli::rollback 如何工作?

转载 作者:可可西里 更新时间:2023-11-01 07:20:28 27 4
gpt4 key购买 nike

我已经阅读了在线 php 手册,但我仍然不确定这两个函数的工作方式:mysqli::commit 和 mysqli::rollback。

我要做的第一件事是:

$mysqli->autocommit(FALSE);

然后我做一些查询:

$mysqli->query("...");
$mysqli->query("...");
$mysqli->query("...");

然后我通过执行以下操作提交由这 3 个查询组成的事务:

$mysqli->commit();

但是在不幸的情况下,其中一个查询不起作用,是所有 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();
?>

我认为这段代码是错误的,因为如果任何查询失败并且 $all_query_ok==false 那么您不需要进行回滚,因为事务未被处理。我说得对吗?

最佳答案

I think this code is wrong because if any of the queries failed and $all_query_ok==false then you don't need to do a rollback because the transaction was not processed. Am I right?

不,如果单个 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)

尽管第二条 SQL 语句失败,但您会看到“foo”和“bar”的插入是成功的 - 您甚至可以看到 AUTO_INCREMENT 值已因错误查询而增加。

因此您必须检查每个 query 调用的结果,如果失败,调用 rollback 以撤消其他成功的查询。所以 Lorenzo 在 PHP 手册中的代码是有道理的。

迫使 MySQL 回滚事务的唯一错误是“事务死锁”(这是 InnoDB 特有的,其他存储引擎可能以不同方式处理这些错误)。

关于php - mysqli::commit 和 mysqli::rollback 如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17649926/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com