数据库中的悲观锁和乐观锁
現(xiàn)在我們簡單聊一下數(shù)據(jù)庫中的悲觀鎖和樂觀鎖。
悲觀鎖
悲觀鎖正如其名稱,比較悲觀。總會認(rèn)為:每當(dāng)修改數(shù)據(jù)時,會有其他線程也會同時修改該數(shù)據(jù)。所以針對這種情況悲觀鎖的做法是:讀取數(shù)據(jù)之后就加鎖(eg: select...for update),這樣別的線程讀取該數(shù)據(jù)的時候就需要等待當(dāng)前線程釋放鎖,獲得到鎖的線程才能獲得該數(shù)據(jù)的讀寫權(quán)限。從而保證了并發(fā)修改數(shù)據(jù)錯誤的問題。但是由于阻塞原因,所以導(dǎo)致吞吐量不高。悲觀鎖更適用于多寫少讀的情況。
場景: 同學(xué)A和同學(xué)B都要給你轉(zhuǎn)500塊錢(開心壞了吧,這樣最終你能得到1000塊錢)。
使用悲觀鎖的流程:
假設(shè)轉(zhuǎn)賬過程沒有鎖,我們看看會發(fā)生什么:
丟失的500塊去哪里了呢?從第2步可以看到同學(xué)B獲取到的賬戶余額是0,而不是同學(xué)A轉(zhuǎn)帳之后的余額500。所以問題出在這里,這是高并發(fā)場景的常見問題。所以加鎖是非常必須的。但是加了悲觀鎖,同學(xué)都要排隊給我轉(zhuǎn)賬,對于沒有耐心的同學(xué)就直接不轉(zhuǎn)帳了,我豈不是錯失了發(fā)財?shù)暮脵C會。那有什么好辦法呢?答案就是下面的樂觀鎖
樂觀鎖
樂觀鎖顧名思義比較樂觀,他只有在更新數(shù)據(jù)的時候才會檢查這條數(shù)據(jù)是否被其他線程更新了(這點與悲觀鎖一樣,悲觀鎖是在讀取數(shù)據(jù)的時候就加鎖了)。如果更新數(shù)據(jù)時,發(fā)現(xiàn)這條數(shù)據(jù)被其他線程更新了,則此次更新失敗。如果數(shù)據(jù)未被其他線程更新,則更新成功。由于樂觀鎖沒有了鎖等待,提高了吞吐量,所以樂觀鎖適合多讀少寫的場景。
常見的樂觀鎖實現(xiàn)方式是:版本號version和CAS(compare and swap)。此處只介紹版本號方式。
要采用版本號,首先需要在數(shù)據(jù)庫表中新增一個字段version,表示此條記錄的更新版本,記錄每變動一次,版本號加1。依舊使用上面轉(zhuǎn)賬的例子說明:
總結(jié)
悲觀鎖:讀取時加鎖,更新完釋放鎖,再此過程中會造成其他線程阻塞,導(dǎo)致吞吐量低,適用于多寫場景。
樂觀鎖:不加鎖,只有在更新時驗證數(shù)據(jù)是否被其他線程更新,吞吐量較高,適用于多讀場景。
總結(jié)
以上是生活随笔為你收集整理的数据库中的悲观锁和乐观锁的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 国王
- 下一篇: linux cmake编译源码,linu