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