数据库乐观锁与悲观锁
前面說到了數據庫的隔離級別,隔離性是數據庫中數據有意義的條件之一,而不同的隔離級別,歸根到底其實是在讀和寫的操作中對表、事務后者是表進行對應的鎖定操作,所以下面簡單總結下數據庫的兩種類型鎖:樂觀和悲觀鎖,很多是概念性的東西和個人理解,不足之處也請指正。
一、鎖的概念
簡單說說數據庫鎖的概念,和多線程中的鎖類似,數據庫中對數據的鎖定其實也是保證數據同步的主要手段,它表現出來的是:并發下,線程之間對數據庫數據的操作是單方的。而在數據庫里面主要有兩種鎖手段保證這種并發下的線程單方面操作:悲觀鎖和樂觀鎖,兩者對數據同步采取的機制不同,下面逐一進行簡單總結。
二、悲觀鎖
1、概念。悲觀鎖是這樣一種概念:當線程訪問數據庫的某些數據時,我先給數據上鎖,然后進行事務處理,當事務提交(or失敗回滾)成功的時候,我才釋放這些數據的鎖,其他線程才能訪問這些數據。悲觀鎖其實和多線程中的鎖同步概念是很類似的。總的來說,悲觀鎖對高并發持一種悲觀的態度:它總是認為系統數據的訪問時高并發的,所以需要在操作數據(包括讀和寫)的第一時間就獲取鎖,這和下面的樂觀鎖形成鮮明的對比。
2、實現原理。悲觀鎖的實現原理和編程中的多線程差不多,數據庫中的數據都會有本身對應的鎖(有數據庫自己提供),當該數據的鎖被對應線程獲得時,其他訪問該數據的線程處于阻塞狀態,只有該線程釋放該鎖時,該數據才可再次被訪問。總的來說,悲觀鎖原理和線程中的lock概念差不多。
3、具體用法。樂觀鎖只是一種概念而已,在mysql中,一般的用法表現是利用sql語句的for update指令對數據進行鎖定。例如,select * from user where user_id=1 for update這條語句,它是這樣一種意思:我要拿user表中user_id為1的數據出來并且后面我會對該行數據進行更新操作,所以請數據庫幫我鎖定該條數據不 讓其他線程訪問(讀寫都不行),這時就會導致其他訪問該數據的線程處于阻塞狀態。
三、樂觀鎖
1、概念。相比于上面的悲觀鎖,樂觀鎖的概念和其不同,它不會在業務持續開始對數據庫進行事務操作時就開始給數據庫上鎖,而是將數據的同步時間后移到數據提交的時候再進行檢查,檢查完數據是否有沖突再進行提交。樂觀鎖對并發問題持有一種樂觀的態度:它總是假設系統的數據在一段時間內不會有太多改變(即寫跟新數據的并發線程遠遠小于讀的線程)。
2、實現原理。樂觀鎖其實并沒有在數據庫中對數據進行加鎖的操作,它不會直接鎖定數據,而是采用一種手段來標記數據的版本,在事務開始的時候先獲取版本,然后事務結束的時候對比版本是否有改變,如果沒改變,直接將事務提交成功,更新數據;否則告訴用戶版本沖突,不可執行事務。
而具體來說,實現樂觀鎖的原理大概有兩種:一個是版本號的記錄,另外一個就是時間節點的記錄。前者數據庫會記錄每次數據修改的版本號,用于標記;后者則根據數據修改時間進行標記操作。具體的實現原理就不展開說,有興趣的可以百度谷歌MVCC和CAS進行了解。
四、悲觀鎖VS樂觀鎖。
所以,我們應該在悲觀和樂觀鎖的兩者之間如何抉擇呢?個人理解有一下總結,具體用法還是看業務需要:
1、數據更新(寫操作)并發嚴重,采用悲觀鎖可以保證程序執行更新操作成功的次數,而采用樂觀鎖可以提高響應的速度但是執行更新操作成功次數會降低;
2、復雜業務采用悲觀鎖會容易死鎖,樂觀鎖不存在這方面的問題;
3、業務回滾的代價:若回滾代價過大則采用悲觀鎖,否則再考慮是否采用樂觀鎖;
4、對于寫讀讀少的,采用悲觀鎖更好;讀多與寫的話考慮樂觀鎖。
總結
以上是生活随笔為你收集整理的数据库乐观锁与悲观锁的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 哪里有面包车出租 寻找最便捷的面包车租赁
- 下一篇: 车载冰箱放哪里 车内装备必备,车载冰箱放