阿里面試:MySQL樂(lè)觀鎖是什么?底層實(shí)現(xiàn)原理?
MySQL樂(lè)觀鎖經(jīng)常在大廠被問(wèn)到,比如:MySQL樂(lè)觀鎖是什么?實(shí)現(xiàn)原理?…等,下面我就來(lái)詳解MySQL樂(lè)觀鎖@mikechen
MySQL樂(lè)觀鎖
MySQL樂(lè)觀鎖,顧名思義就是很“樂(lè)觀”,也就在更新數(shù)據(jù)時(shí)不加鎖,而是通過(guò)“版本號(hào)”、或“時(shí)間戳”來(lái)檢測(cè)數(shù)據(jù)是否被修改。
MySQL樂(lè)觀鎖實(shí)現(xiàn)原理
MySQL的樂(lè)觀鎖通過(guò)版本號(hào)或時(shí)間戳機(jī)制實(shí)現(xiàn),其核心原理:是在更新數(shù)據(jù)時(shí)檢查數(shù)據(jù)是否被其他事務(wù)修改,從而避免并發(fā)沖突。
圖片
實(shí)現(xiàn)步驟,如下:
第一:增加“版本號(hào)”。
在數(shù)據(jù)庫(kù)表,中添加一個(gè)版本號(hào)字段,通常命名為 version 。
ALTER TABLE orders ADD COLUMN version INT DEFAULT 1;
這個(gè)字段用于記錄數(shù)據(jù)的版本信息,每當(dāng)數(shù)據(jù)被更新時(shí),版本號(hào)會(huì)自動(dòng)遞增。
第二:讀取數(shù)據(jù)。
獲取當(dāng)前數(shù)據(jù)的版本號(hào),(如:version字段)、或時(shí)間戳。
讀取數(shù)據(jù)
SELECT id, stock, version FROM product WHERE id = 1;
第三:提交更新。
更新數(shù)據(jù)時(shí),校驗(yàn)版本號(hào),是否與讀取時(shí)一致。
UPDATE table
SET column1 = new_value, version = version + 1
WHERE id = target_id AND version = old_version;
比如,通過(guò)版本號(hào)的方式,更新庫(kù)存:
更新時(shí)校驗(yàn)版本號(hào)
UPDATE product
SET stock = stock - 1, version = version + 1
WHERE id = 1 AND version = 1; -- 假設(shè)當(dāng)前version=1
在更新數(shù)據(jù)時(shí),檢查 version 字段的值是否與預(yù)期一致,如果一致則更新數(shù)據(jù)并遞增 version 值,否則更新失敗。
圖片
比如:成功(affected rows > 0),更新成功,業(yè)務(wù)繼續(xù)執(zhí)行。
失?。╝ffected rows = 0),說(shuō)明數(shù)據(jù)已被其他事務(wù)修改,需要重新讀取數(shù)據(jù)并重試。
在讀多寫少的場(chǎng)景下,樂(lè)觀鎖不會(huì)像悲觀鎖那樣在讀操作時(shí)加鎖,從而減少了鎖的開(kāi)銷,這是MySQL樂(lè)觀鎖最大的優(yōu)點(diǎn)。
適用于數(shù)據(jù)沖突較少的場(chǎng)景,避免鎖帶來(lái)的性能損耗。
但是,在大部分金融交易,要求數(shù)據(jù)強(qiáng)一致性的場(chǎng)景,則需要悲觀鎖。