MySQL中的樂觀鎖是通過版本號的方式來實(shí)現(xiàn)的。每個行數(shù)據(jù)都有一個版本號,當(dāng)數(shù)據(jù)被修改時,版本號也會同步更新。當(dāng)多個事務(wù)同時更新同一行數(shù)據(jù)時,只有其中一個事務(wù)可以成功,其他事務(wù)會被標(biāo)記為失敗,需要重新嘗試。
行鎖是在修改數(shù)據(jù)時使用的機(jī)制,它可以保證數(shù)據(jù)的一致性。當(dāng)一個事務(wù)對數(shù)據(jù)進(jìn)行修改時,會對該數(shù)據(jù)行進(jìn)行加鎖,其他事務(wù)無法對該行數(shù)據(jù)進(jìn)行修改,只能等待當(dāng)前事務(wù)完成并釋放鎖。
樂觀鎖和行鎖是兩種不同的鎖機(jī)制,它們實(shí)現(xiàn)的功能也不同。樂觀鎖是通過版本號來保證數(shù)據(jù)的一致性,而行鎖是通過加鎖機(jī)制來保證數(shù)據(jù)的一致性。
在MySQL中,樂觀鎖和行鎖是可以同時存在的。當(dāng)兩個事務(wù)同時對同一行數(shù)據(jù)進(jìn)行修改時,會先進(jìn)行行鎖的競爭,只有一個事務(wù)可以獲得該行數(shù)據(jù)的鎖,并且在修改完成后釋放鎖。然后再通過樂觀鎖的競爭來確定哪個事務(wù)能夠成功提交修改。
SET @@SESSION.autocommit = 0; -- 關(guān)閉自動提交
-- 開啟事務(wù)
START TRANSACTION;
-- 查詢數(shù)據(jù)并且獲取版本號
SELECT * FROM table WHERE id = '1' FOR UPDATE;
-- 修改數(shù)據(jù)
UPDATE table SET name = 'new_name' WHERE id = '1';
-- 提交事務(wù)
COMMIT;
-- 關(guān)閉事務(wù)
ROLLBACK;
在上面的代碼中,我們先開啟了一個事務(wù),然后對數(shù)據(jù)進(jìn)行加鎖,并且獲取了數(shù)據(jù)的版本號。在修改數(shù)據(jù)時,進(jìn)行了樂觀鎖的競爭,如果當(dāng)前事務(wù)的版本號和數(shù)據(jù)行的版本號一致,則修改成功;否則需要重新嘗試。最后提交事務(wù)或者回滾事務(wù)。