MySQL 事務(wù)行鎖和樂(lè)觀鎖是兩種常見(jiàn)的數(shù)據(jù)庫(kù)并發(fā)控制方式,本文將著重介紹它們的特點(diǎn)和使用場(chǎng)景。
事務(wù)行鎖
事務(wù)行鎖,即一種悲觀鎖,假設(shè)兩個(gè)事務(wù)可能會(huì)同時(shí)訪問(wèn)同一個(gè)數(shù)據(jù)行,當(dāng)一個(gè)事務(wù)對(duì)該數(shù)據(jù)行進(jìn)行修改時(shí)需要先對(duì)該行進(jìn)行鎖定,避免其他事務(wù)讀/寫導(dǎo)致臟數(shù)據(jù)。
BEGIN; SELECT * FROM t WHERE id=1 FOR UPDATE; UPDATE t SET val=val+1 WHERE id=1; COMMIT;
這里使用 FOR UPDATE 鎖定表 t 的 ID=1 行,并在事務(wù)結(jié)束前一直持有鎖。如果有其他事務(wù)嘗試鎖定該行,會(huì)被阻塞,直到該事務(wù)釋放鎖。
事務(wù)行鎖的優(yōu)點(diǎn)是簡(jiǎn)單可靠,強(qiáng)制控制數(shù)據(jù)一致性。但如果事務(wù)較多,爭(zhēng)奪同一行的鎖就會(huì)引發(fā)死鎖和阻塞,導(dǎo)致性能下降。
樂(lè)觀鎖
樂(lè)觀鎖是基于版本號(hào)實(shí)現(xiàn)的,每次更新前會(huì)先將當(dāng)前數(shù)據(jù)行的版本號(hào)與操作前一致性讀取出來(lái),進(jìn)行比較。如果版本號(hào)一致則更新數(shù)據(jù)行,否則提示版本沖突,需要重新讀取。
START TRANSACTION; SELECT val,version FROM t WHERE id=1; -- 檢查 version 是否仍然是 1,如果仍然是 1,執(zhí)行下一步: UPDATE t SET val=2,version=2 WHERE id=1 AND version=1; COMMIT;
這里使用 version 字段標(biāo)識(shí)數(shù)據(jù)行修改的版本號(hào),當(dāng)兩個(gè)事務(wù)同時(shí)更新同一行時(shí),只有第一個(gè)事務(wù)能夠順利執(zhí)行,第二個(gè)事務(wù)會(huì)被拒絕,需要重新讀取數(shù)據(jù)。
樂(lè)觀鎖的優(yōu)點(diǎn)是不會(huì)阻塞其他事務(wù),可以同時(shí)支持多個(gè)并發(fā)事務(wù)。但需要注意并發(fā)訪問(wèn)情況下的版本控制和更新策略,否則容易導(dǎo)致數(shù)據(jù)破壞。
在實(shí)際應(yīng)用中,事務(wù)行鎖與樂(lè)觀鎖各有優(yōu)缺點(diǎn),需要根據(jù)具體場(chǎng)景選擇適合的并發(fā)控制方式。