各位好
請問MYSQL的交易機制啟動時,是否會自動鎖表或鎖ROW呢?
比如說現在有兩個使用者,同時進行
假設member id = 10 的 amount = 100
USER1:
1.交易開始
2.UPDATE member SET 'amount` = amount-10 WHERE id=10; //結果90
3.檢查不符合條件 (USER2 已經提交)
4.回滾 (因user2 已提交, 這時候回滾的amount是?)
5.交易結束
有這種可能性嗎?
還是當USER1交易開始 跑到UPDATE步驟的時候,就會做 lock 不讓USER2 繼續 的動作了呢? 或是要再另外下一個 SELECT * FORM member WHERE id=10 for update 的 row lock 呢?
這部分不太懂...又擔心到時 死結的問題
第一次發問,若問題說的不清楚請見諒,我再補充
為什麼兩個User都會要處理Id=10的事呢
因為想不到什麼比較簡單說明的例子...所以拿同樣處理同一個ID做舉例
因為在網路爬文有寫到要row lock要小心死結的問題
如.
user1:
時間1. select * from member where id='4' for update
時間2. select * from paylog where member_id='4' for update
等待...user2 解鎖 paylog 資料表
user2:
時間1. select * from paylog where member_id='4' for update
時間2. select * from member where id='4' for update
等待...user1 解鎖 member 資料表
就這樣互相等解鎖的問題....最後要重開機解決
這樣子的問題會發生嗎 ?
既然user1就先做了,那為何user2會跑到前面???
因為如果同時開始,或差距毫秒時間開始,若因為user1的中間還有較多執行程序,或因查詢某段SQL查詢較久,user2 應該有可能會超強步驟。(不同支程式的情況)
還有死結跟這裡沒關係啊.....
因為在網路爬文有寫到要row lock要小心死結的問題
如.
user1:
時間1. select * from member where id='4' for update
時間2. select * from paylog where member_id='4' for update
等待...user2 解鎖 paylog 資料表
user2:
時間1. select * from paylog where member_id='4' for update
時間2. select * from member where id='4' for update
等待...user1 解鎖 member 資料表
就這樣互相等解鎖的問題....最後要重開機解決
這樣子的問題會發生嗎 ?
MySQL 交易功能 Transaction 整理 - XYZ的筆記本
這個我有爬文過,謝謝...大致上有一點點概念...但有些地方覺得不確定
另外官方英文看不太懂...小弟不才
通常是程式設計師的 transaction 包得太大、設計不良所致。
恩...因為我也擔心會發生這樣的錯誤...到時要找問題很難找
測試又不知道要從何測..才能測出相同狀況重現...因為要可能2~3個使用者同時執行或執行時間點不同才會發生
不發生,你怎麼知道是問題?
也是啦...但某些情況下經不起他發生..例如會影響訂單量..會員跑了之類的
imagine10255提到:
因為在網路爬文有寫到要row lock要小心死結的問題
如果是很多人的線上交易系統
我們部會讓 insert 的 session 去啟動 Update 機制
INSERT Transaction 不啟動 Update Master Table 的機制
由另外一個專門 Update 的 session 去處理,
並回報處理狀況 (就是成功後 insert 另一筆 交易成功紀錄更改前後異動欄位值)
你的例子不可能會發生。因為:
- 既然 user1 已經啟動 transaction,user2 就不可能再做寫入 (insert, update, delete),直到 user1 的 transaction 結束,才會輪到 user2 的 update 指令。
這點我想確認...是當user1的交易啟動時,會先掃描這個程序範圍 有用到那些update,insert,就先限制寫入,還是當跑到 insert那段sql的時候才限制update,insert呢?
另外想知道,是不是在這幾個情況下才建議使用 for update 這種row lock
1.更新結果需依前面的查詢結果而訂
2.不希望更新前的資料讓別人讀取
這樣概念對嗎? 請賜教
其實,SQL 跟程式一樣,不要用會讓系統有機會deadlock的語法。
依我的經驗,會發生 deadlock!雖然機會極低,但我遇到了。
而原因通常是程式設計師的 transaction 包得太大或是設計不良所致。就如同你用的語法,可以考慮:
- 有沒有必要用到 transaction?
購物網站,會員進行訂單送出,從取得檢查資料開始包住,接著儲存訂單資料、會員扣款,新增扣款紀錄,交易結束。中途失敗或拋出錯誤就回滾。確保資料一致性
- 若 for update 有疑慮,可否改寫成其它語法?
是說改成類似排隊執行的方式嗎 ?
謝謝建議