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

时间:2017-02-13 08:25:36

标签: mysql transactions innodb

我正在研究金融系统,我遇到了MySQL事务的问题。

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

过程如下:

  1. 用户想购买1000美元的股票
  2. 在订单中有4个优惠250美元
  3. START TRANSACTION
  4. 每个优惠:
  5. 脚本执行UPDATE查询(将USD从一个用户移动到另一个用户并以相反的方式共享)。然后脚本将条目INSERT到历史表。
  6. 用户支付费用(更新余额)。
  7. 重复5和6以获得下一个优惠。
  8. COMMIT
  9. 现在关键部分 - 在某些情况下,从第5点开始的更改不会保存,但是从6开始就是保存(我看到费用已经支付,但历史记录中没有交易)。 我在这次交易中没有使用ROLLBACK并且脚本没有中断(因为在这种情况下不会支付费用)。

    是否有可能在没有ROLLBACK查询的情况下回滚事务?或者MySQL只能提交几个最新的查询而不是全部查询?

2 个答案:

答案 0 :(得分:1)

是否交易,您的客户端代码有责任验证所有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,除非您终止具有挂起更改的会话。

答案 1 :(得分:0)

问这个问题已经很长时间了,但是实际上问题是我没有为每个查询检查SQL错误。

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

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