在mysql中,可以利用數(shù)據(jù)版本Version記錄機(jī)制實現(xiàn)樂觀鎖,給數(shù)據(jù)表加一個version字段,每操作一次記錄的版本號加一,判斷version的值是否與剛查詢的值相等,若相等則執(zhí)行更新,若不相等則不進(jìn)行更新。
本教程操作環(huán)境:windows10系統(tǒng)、mysql8.0.22版本、Dell G3電腦。
mysql樂觀鎖怎么實現(xiàn)
實現(xiàn)方法
1、用數(shù)據(jù)版本Version記錄機(jī)制實現(xiàn),這是樂觀鎖最常用的一種實現(xiàn)方式。
2、數(shù)據(jù)版本,即為數(shù)據(jù)增加一個版本標(biāo)識,一般是通過為數(shù)據(jù)庫表增加一個數(shù)字類型的 version字段來實現(xiàn)。當(dāng)讀取數(shù)據(jù)時,將version字段的值一同讀出,數(shù)據(jù)每更新一次,對此version值加1。當(dāng)我們提交更新的時候,判斷數(shù)據(jù)庫表對應(yīng)記錄的當(dāng)前版本信息與第一次取出來的version值進(jìn)行比對,如果數(shù)據(jù)庫表當(dāng)前版本號與第一次取出來的version值相等,則予以更新,否則認(rèn)為是過期數(shù)據(jù)。
實例
update TABLE set value=2,version=version+1 where id=#{id} and version=#{version}
樂觀鎖不是數(shù)據(jù)庫自帶的,需要我們自己去實現(xiàn)。
樂觀鎖是指操作數(shù)據(jù)庫時(更新操作),想法很樂觀,認(rèn)為這次的操作不會導(dǎo)致沖突,在操作數(shù)據(jù)時,并不進(jìn)行任何其他的特殊處理(也就是不加鎖),而在進(jìn)行更新后,再去判斷是否有沖突了。整體思想就是CAS思想。
通常實現(xiàn)是這樣的:在表中的數(shù)據(jù)進(jìn)行操作時(更新),先給數(shù)據(jù)表加一個版本(version)字段,每操作一次,將那條記錄的版本號加1。也就是先查詢出那條記錄,獲取出version字段,如果要對那條記錄進(jìn)行操作(更新),則先判斷此刻version的值是否與剛剛查詢出來時的version的值相等,如果相等,則說明這段期間,沒有其他程序?qū)ζ溥M(jìn)行操作,則可以執(zhí)行更新,將version字段的值加1;如果更新時發(fā)現(xiàn)此刻的version值與剛剛獲取出來的version的值不相等,則說明這段期間已經(jīng)有其他程序?qū)ζ溥M(jìn)行操作了,則不進(jìn)行更新操作。
eg:
下單操作包括3步驟:
1、查詢出庫存信息:
select (id,count,version) from t_goodsku where id=#{id}
2、扣減2個庫存:
程序中計算:count = count – 2;
3、更新庫存:
update t_goodsku set count={count},version=version+1 where id=#{id} and version=#{version};
第1步中查到的version其實是快照(read-commited和read-repeatable隔離機(jī)制下的MVCC機(jī)制),在這種情況下,第3步去update時,獲取鎖,where條件中進(jìn)行判斷中的version=#{version},其實是拿當(dāng)前version和第1步中的快照version進(jìn)行比對
如果比對成功,說明在這段時間內(nèi)這條數(shù)據(jù)沒有被其他線程更新過,update成功;
如果對比失敗,說明這段時間內(nèi)這條數(shù)據(jù)被更新過,那么update失敗,報錯回滾或自旋。
當(dāng)然,這里是為了模擬樂觀鎖的場景,實際上更新庫存時一步便可以實現(xiàn):
1、更新庫存:
update t_goodsku set count=count -2 where id=#{id};
推薦學(xué)習(xí):mysql視頻教程