mysql 事務遇到並發問題


在開發中遇到過這樣一個問題

一個看視頻記錄,更新到100就表示看完了,后面再有請求不繼續更新了.

結果是:

 

導致,里面很多數據出現問題.

推測是以下的情況才會導致

第一條請求  事務在執行中,還未提交(因為本地有時候比較難再現,於是手動在程序中,第一條記錄處理的時候,sleep了幾秒,就達到這種效果了)

第二條請求  事務已經開始執行,這個時候查到的歷史最大值不是100,才會去進行了更新

網上看了一下解決方案:

悲觀鎖

直接鎖行記錄

這個我在本地測試,確實有效,一個事務開始沒結束,第二個事務一個等待,不過會導致處於阻塞狀態,因為系統並發,不敢考慮,也就是記錄下這個方式.

 

手動模擬:

執行第一個事務:

 

-- 視頻100
BEGIN; SELECT
* FROM `biz_coursestudyhistory` WHERE sid = 5777166; UPDATE biz_coursestudyhistory set studyStatus = 100,versionNO=versionNO+1 WHERE sid = 1 AND versionNO = 0; -- commit ; 先不執行,先注解掉,只執行上面的

 

 

接着執行第二個事務:

BEGIN;

UPDATE biz_coursestudyhistory set studyStatus = 90,versionNO=versionNO+1 WHERE sid = 1 AND versionNO = 0;

SELECT * FROM `biz_coursestudyhistory` WHERE sid = 1 FOR UPDATE;

COMMIT;

  

會發現成功不了,一直處於等待狀態.

查看鎖

select * from information_schema.INNODB_TRX;

  

 

確實被鎖住了,這里只要執行第一個事務的commit ,第二個事務就會執行.

 

從這里可以看出,行鎖可以直接達到理想的數據統一狀態,一個事務修改,其他都不能操作,感覺這種比較適合銀行這種安全性的項目

樂觀鎖:

這種比較簡單,並且不會造成阻塞

方式就是加上版本號

var maxver = select max(version) from table

更新的話使用

update table set studystatus = xxx,version = version +1  where id =1 and version = maxver

寫入的話

INSERT into table  (contentStudyID,courseWareID,studyStatus,studyTime,endTime)

SELECT 27047358,3163,100,333,NOW() FROM dual WHERE NOT EXISTS (SELECT 1 FROM table WHERE contentStudyID =27047358 AND

courseWareID = 3163

 )

  

這種方式,可以在更新或者寫入的時候,直接判斷庫里面存在的數據是否存在,如果不存在則是別其他的線程使用了.

修改為這種寫法后,使用jmeter進行多線程測試,從最開始的多條記錄更新成功,變成只有一個成功,后面的失敗.

從最開始的插入多條記錄,到后來的只能插入一條數據了

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM