資料庫 樂觀鎖與悲觀鎖
阿新 • • 發佈:2018-11-19
樂觀鎖
總是認為不會產生併發問題,每次去取資料的時候總認為不會有其他執行緒對資料進行修改,因此不會上鎖,但是在更新時會判斷其他執行緒在這之前有沒有對資料進行修改,一般會使用版本號機制或CAS操作實現。
version方式:一般是在資料表中加上一個資料版本號version欄位,表示資料被修改的次數,當資料被修改時,version值會加一。當執行緒A要更新資料值時,在讀取資料的同時也會讀取version值,在提交更新時,若剛才讀取到的version值為當前資料庫中的version值相等時才更新,否則重試更新操作,直到更新成功。
核心SQL程式碼:
update table set x=x+1, version=version+1 where id=#{id} and version=#{version};
CAS操作方式:即compare and swap 或者 compare and set,涉及到三個運算元,資料所在的記憶體值,預期值,新值。當需要更新時,判斷當前記憶體值與之前取到的值是否相等,若相等,則用新值更新,若失敗則重試,一般情況下是一個自旋操作,即不斷的重試。
悲觀鎖
總是假設最壞的情況,每次取資料時都認為其他執行緒會修改,所以都會加鎖(讀鎖、寫鎖、行鎖等),當其他執行緒想要訪問資料時,都需要阻塞掛起。可以依靠資料庫實現,如行鎖、讀鎖和寫鎖等,都是在操作之前加鎖,在Java中,synchronized的思想也是悲觀鎖。
樂觀鎖優點程式實現,不會存在死鎖等問題。他的適用場景也相對樂觀。阻止不了除了程式之外的資料庫操作。
悲觀鎖是資料庫實現,他阻止資料庫寫操作。
再來說更新資料丟失,所有的讀鎖都是為了保持資料一致性。樂觀鎖如果有人在你之前更新了,你的更新應當是被拒絕的,可以讓使用者從新操作。悲觀鎖則會等待前一個更新完成