MySQL 没有ROLLBACK 查询的事务可以回滚吗?

Can MySQL transaction rollback without ROLLBACK query?

我在金融系统上工作,我遇到了 MySQL 交易的问题。

该系统是一个简单的证券交易所,用户可以在这里买卖虚拟股票。为了在买卖过程中保持完整性,我使用交易。 问题是在某些情况下(我不知道它取决于什么)一些事务被回滚(或未提交),但处理了下一个查询。

流程如下:

  1. 用户想以 1000 美元购买股票
  2. 订单簿中有 4 个 250 美元的出价
  3. START TRANSACTION
  4. 对于每个报价:
  5. 脚本执行更新查询(将美元从一个用户转移到另一个用户并以相反的方式共享)。然后编写 INSERTs 条目到历史表的脚本。
  6. 用户支付费用(更新余额)。
  7. 重复第 5 步和第 6 步以获得下一个报价。
  8. COMMIT

现在是关键部分 - 在某些情况下,第 5 点的更改未保存,但第 6 点的更改已保存(我看到已支付费用,但历史记录中没有交易)。 在此交易期间我没有使用 ROLLBACK 并且脚本没有中断(因为在这种情况下不会支付费用)。

是否有可能在没有 ROLLBACK 查询的情况下交易正在回滚?或者 MySQL 可以只提交少数最新查询而不是全部吗?

事务与否,您的客户端代码有责任验证您的所有 INSERT 或 UPDATE 查询是否成功完成,然后发出显式 ROLLBACK 或关闭与我们的 COMMIT 的连接以发出隐式 ROLLBACK。如果其中任何一个失败但您的代码继续运行,这些查询将不会生效(因为它们失败了)但其余的会生效。

这是一个简化的例子:

mysql> create table test (
    ->     id int(10) unsigned not null,
    ->     primary key (id)
    -> );
Query OK, 0 rows affected (0.02 sec)

mysql> insert into test(id) values (1);
Query OK, 1 row affected (0.00 sec)

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

mysql> insert into test(id) values (2);
Query OK, 1 row affected (0.00 sec)

mysql> insert into test(id) values (-3);
ERROR 1264 (22003): Out of range value for column 'id' at row 1

我们应该在这里回滚和中止,但我们没有。

mysql> insert into test(id) values (4);
Query OK, 1 row affected (0.00 sec)

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

mysql> select * from test;
+----+
| id |
+----+
|  1 |
|  2 |
|  4 |
+----+
3 rows in set (0.00 sec)

需要 4 行,得到 3 行。

除此之外,在很多情况下,您可能会收到不需要的 COMMIT,但我不确定是否会发生不需要的 ROLLBACK,除非您终止带有未决更改的会话。

很久没问这个问题了,但问题实际上是我没有检查每个查询的 SQL 错误。

实际上在某些时候,当我应该回滚事务时,我没有这样做。

如果您正在寻找答案 - 请再次检查您是否测试了事务中的所有查询以成功执行并且不相信您正在使用的框架会自动为您执行此操作(只需再次检查)。