MySQL事务回滚可以不用ROLLBACK查询吗?

问题描述 投票:2回答:1

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

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

该过程如下:

  1. 用户想以1000美元的价格购买股票
  2. 在订单中有4个优惠250美元
  3. START TRANSACTION
  4. 每个优惠:
  5. 脚本执行UPDATE查询(将USD从一个用户移动到另一个用户并以相反的方式共享)。然后脚本将条目INSERT到历史表。
  6. 用户支付费用(UPDATE余额)。
  7. 重复5和6以获得下一个优惠。
  8. COMMIT

现在关键部分 - 在某些情况下,从第5点开始的更改不会保存,但是从6开始就是保存(我看到费用已经支付,但历史记录中没有交易)。我在这次交易中没有使用ROLLBACK而且脚本没有破坏(因为在这种情况下不会支付费用)。

如果没有ROLLBACK查询,交易是否有可能回滚?或者MySQL COMMIT只能提供几个最新的查询而不是全部?

mysql transactions innodb
1个回答
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,除非你终止一个有未决更改的会话。

© www.soinside.com 2019 - 2024. All rights reserved.