2017-02-13 127 views
0

我正在從事金融系統工作,並且遇到了MySQL事務的問題。MySQL事務回滾沒有ROLLBACK查詢?

該系統是一個簡單的證券交易所,用戶可以在其中購買和出售虛擬股票。爲了保持購買和銷售過程的完整性,我使用交易。 問題是,在某些情況下(我不知道它依賴於什麼)一些事務回滾(或未提交),但是下一個查詢被處理。

的過程如下:

  1. 用戶希望購買的股票爲1000美元
  2. 在訂單量有4個報價爲250美元
  3. START TRANSACTION
  4. 對於每一個報價:
  5. 腳本進行UPDATE查詢(將美元從一個用戶轉移到另一個用戶,並以相反方式分享)。然後腳本將條目插入到歷史記錄表中。
  6. 用戶支付費用(更新餘額)。
  7. 對下一個報價重複5和6。
  8. COMMIT

現在關鍵的部分 - 在某些情況下,從5點不保存更改,而是從6他們(我看到費已支付,但在歷史上沒有交易)。 在此交易中,我沒有使用ROLLBACK,並且腳本沒有中斷(因爲在這種情況下,費用不會被支付)。

查詢有沒有可能回滾沒有ROLLBACK?或者MySQL可以只提交幾個最新的查詢而不是全部?

非常感謝您的回覆。

+1

不,交易應該始終是原子的。要麼它什麼都不做或什麼都不做。 – Barmar

+0

系統中的第一個漏洞是您在交易之前檢查訂單(僅),因此可能已更改;例如訂單1可能已被使用,只剩下3個開放優惠,根據您的實際代碼,第5步可能不會做任何事情,但第6步可能仍然收取費用。但這只是一個問題,只有你的概念。還有很多其他的事情你可以做錯(例如使用myisam,使用錯誤的事務級別,不鎖定選擇,...),所以這裏可能還有其他問題。如果你用真實的金錢/價值進行交易,你應該找一位顧問來檢查你的代碼。 – Solarflare

+0

我沒有在第一篇文章中寫過(對不起),但是我在啓動過程之前使用'SELECT FOR UPDATE'鎖定行。 當我處理單個優惠時,我正在檢查另外一項,如果優惠仍然存在,用戶有有效餘額等。 但是目前它是演示系統。 – Zachmian

回答

0

事務與否,您的客戶端代碼的責任是確保您的所有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 

我們應該rollbacked這裏中止,但我們沒有。

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是什麼我不知道,可以發生,除非你用未決更改終止會話。