【问题标题】:MySQL transaction is committed even when error occurred即使发生错误,也提交 MySQL 事务
【发布时间】:2013-06-28 11:08:39
【问题描述】:

在我的项目中,我删除和更新了许多表中的许多行,因此我决定使用事务。但是即使发生错误并且脚本正在结束,也会提交事务。

我只使用 mysql_ 而不是 mysqli_PDO 因为在该服务器上不受支持。

mysql_query("START TRANSACTION");
$res = mysql_query("some insert...");
if($res === false){
  //this save error log and exit script with die() or exit()
  trigger_error(mysql_errno()."\n".mysql_error()); 
}
$res = mysql_query("some delete...");
if($res === false){
  trigger_error(mysql_errno()."\n".mysql_error()); 
}
mysql_query("COMMIT");

在我的项目中,我有 mysql 我的类,所以我不会这样输入,但是这样可以工作。

当第一次查询错误发生后,错误日志被保存结束脚本结束。但是插入的数据保留在数据库中。我虽然,当COMMIT 没有被执行并且连接被关闭时,自动ROLLBACK 发生。

附:我知道,使用 mysqli 应该会更好,但是 mysql_mysqli_ 是一样的,不是吗?

【问题讨论】:

  • 你应该只在成功后提交,在错误后回滚
  • 我只在成功后提交,而不是在错误时回滚。我以为是自动的。

标签: php mysql transactions


【解决方案1】:

我建议阅读:http://dev.mysql.com/doc/refman/5.0/en/commit.html,特别是关于 SET autocommit=0。我相信,如果您希望它不自动提交,您需要说出来,然后才会不会自动调用 COMMIT ROLLBACK 您的声明。

最好有一个调用 ROLLBACK 的处理程序代码,否则您可能会相信 MySQL 会为您完成所有工作,并且未来对 MySQL 的任何与 TRANSACTIONS 相关的更改可能您的代码无法正确处理。

【讨论】:

  • 顺便说一句,您发布的网站上写着,START TRANSACTION 禁用自动提交。我在错误函数中添加了回滚。但仍然不明白为什么保存数据,当没有执行 COMMIT 并且 START TRANSACTION 禁用自动提交
  • 不知道,抱歉,需要“真正调试”
【解决方案2】:

您确定数据保留在数据库中/未执行提交查询就提交了吗?

MySQL documentation:

要为单个语句系列隐式禁用自动提交模式,请使用 START TRANSACTION 语句:

开始交易;

SELECT @A:=SUM(salary) FROM table1 WHERE type=1;

UPDATE table2 SET summary=@A WHERE type=1;

提交;

使用 START TRANSACTION,自动提交保持禁用状态,直到您使用 COMMIT 或 ROLLBACK 结束事务。然后自动提交模式恢复到之前的状态。

我使用 MySQL 5.5 和 PHP 5.3 测试了这段代码:

sql> create table t10 (id integer auto_increment primary key, status char(32))

<?php

  if( ($link = mysql_connect("localhost", "db_user", "*****")) === false )
    exit(1);

  mysql_select_db("test", $link);

  var_dump(mysql_query("start transaction;"));
  var_dump(mysql_query("insert into t10 (status) values (\"foo1\"), (\"foo2\");"));
  exit();
  //var_dump(mysql_query("commit;"));
  var_dump(mysql_close());
?>

值 foo1 和 foo2 未插入数据库表 t10。还要记住,在“全有或全无”规则的意义上,MySQL 事务并不是完全原子的。您可以提交一个事务,其中一半语句已完成,另一半则失败(来源:Kouber Saparev 于 2010 年 12 月 3 日上午 11:01 在 MySQL 页面 http://dev.mysql.com/doc/refman/5.5/en/ansi-diff-transactions.html)。

测试用例:

mysql> create table t7 (id integer primary key auto_increment, name text, lastname text);
Query OK, 0 rows affected (0.04 sec)

mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t7 (name, lastname) values('name1', 'lastname1');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t7 (name, lastname) values('name1', 'lastname1');
Query OK, 1 row affected (0.00 sec)

mysql> insert into t7 (name, lastname) ('name1', 'lastname1');
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that
corresponds to your MySQL server version for the right syntax to use near ''name
1', 'lastname1')' at line 1
mysql> commit;
Query OK, 0 rows affected (0.01 sec)

mysql> select * from t7;
+----+-------+-----------+
| id | name  | lastname  |
+----+-------+-----------+
|  1 | name1 | lastname1 |
|  2 | name1 | lastname1 |
+----+-------+-----------+
2 rows in set (0.00 sec)

我们看到即使事务成功提交,失败的插入查询也没有计算在内。

【讨论】:

    猜你喜欢
    • 2015-12-15
    • 2018-12-13
    • 1970-01-01
    • 2020-01-13
    • 2016-06-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-30
    相关资源
    最近更新 更多