鎖的定義:鎖主要用於多用戶環境下,保證數據庫完整性和一致性的技術。程序員
鎖的解釋:當多個用戶併發地存取數據時,在數據庫中就會產生多個事務同時存取同一數據的狀況。若對併發操做不加控制就可能會讀取和存儲不正確的數據,破壞數據庫的完整性和一致性。當事務在對某個數據對象進行操做前,先向系統發出請求,對其加鎖。加鎖後事務就對該數據對象有了必定的控制。數據庫
鎖的分類,在教材上,網絡上好多都是按兩個維度來描述的。一種維度是按鎖的功能來劃分,一種維度是按概念來劃分。安全
1)、按概念劃分(從程序員的角度看)微信
• 悲觀鎖(Pessimistic Lock)
網絡• 樂觀鎖(Optimistic Lock)併發
2)、按鎖的功能來劃分(從數據庫系統的角度來看)app
• 共享鎖 (S) (Shared (S) Locks) 用於不更改或不更新數據的操做(只讀操做),如SELECT語句。數據庫設計
• 更新鎖 (U) (Update (U) Locks)用於可更新的資源中。防止當多個會話在讀取、鎖定以及隨後可能進行的資源更新時發生常見形式的死鎖。ide
• 排它鎖 (X) (Exclusive (X) Locks) 用於數據修改操做,例如INSERT、UPDATE或DELETE。確保不會同時對同一資源進行多重更新。性能
• 意向鎖 (I)(Intent Locks) 用於創建鎖的層次結構。意向鎖的類型爲:意向共享(IS)、意向排它(IX)以及與意向排它共享(SIX)。
SQL Server數據庫高級進階之鎖實戰演練
1)、共享鎖 (S)
共享鎖 (S) (Shared (S) Locks) 用於不更改或不更新數據的操做(只讀操做),如SELECT語句。
2)、 更新鎖 (U)
更新鎖 (U) (Update (U) Locks) 用於可更新的資源中。防止當多個會話在讀取、鎖定以及隨後可能進行的資源更新時發生常見形式的死鎖。
3)、排它鎖 (X)
排它鎖 (X) (Exclusive (X) Locks) 用於數據修改操做,例如INSERT、UPDATE或DELETE。確保不會同時對同一資源進行多重更新。
4)、意向鎖 (I)
意向鎖 (I) (Intent Locks) 用於創建鎖的層次結構。意向鎖的類型爲:意向共享(IS)、意向排它(IX)以及與意向排它共享(SIX)。
• 一、防止鎖升級的最簡單,最安全的方法是保持事務的簡短,並減小昂貴查詢的鎖佔用空間,以便不超過鎖升級閾值,有幾種方法能夠實現這一目標。將大批量操做分解爲幾個較小的操做。刪除大量數據的時候,能夠一次只刪除500個,執行屢次,能夠顯着減小每一個事務累積的鎖定數量並防止鎖定升級。
• 二、 建立索引使查詢儘量高效來減小查詢的鎖定佔用空間。若是沒有索引會形成表掃描可能會增長鎖定升級的可能性, 更可怕的是,它增長了死鎖的可能性,而且一般會對併發性和性能產生負面影響。根據查詢條件建立合適的索引,最大化提高索引查找的效率,此優化的一個目標是使索引查找返回儘量少的行,以最小化查詢的的成本。
死鎖(Dead Lock)
死鎖是指一種進程之間互相永久阻塞的狀態,可能涉及兩個或更多的進程。死鎖是指在一組進程中的各個進程均佔有不會釋放的資源,但因互相申請被其餘進程所站用不會釋放的資源而處於的一種永久等待狀態。
首先要理解,在多併發的環境中死鎖是不可避免的,只能經過合理的數據庫設計、良好的索引、適當的查詢語句以及隔離等級等措施儘可能減小死鎖。
最開始列出了死鎖的4個必要條件,只要想辦法破壞任意1個或多個條件就能夠避免產生死鎖。下列方法有助於最大限度的下降死鎖:
a) 按同一順序訪問對象;
b)避免事務中的用戶交互,也就是在事務執行過程當中不要包含用戶交互的步驟;
c)保持事務簡短並在一個批處理中;
d)SELECT語句加WITH(NOLOCK)提示;
SELECT * FROM TableName WITH(NOLOCK);
一、併發性具體帶來什麼問題?
在多用戶環境中,在同一時間可能會有多個用戶更新相同的記錄,這會產生衝突。這就是著名的併發性問題。
1)、髒讀取:當一個事物讀取其它完成一半事務的記錄時,就會發生髒讀取。
例:用戶A和用戶B看到的值都是5,用戶B將值修改成2,用戶A看到的值仍然是5,這時就發生了髒讀取。
2)、不可重複讀取:在每次讀數據時,若是你得到的值都不同,那代表你遇到了不可重複讀取問題。
例:用戶A看到的值是5,用戶B將值修改成2,用戶A刷新後看到的值仍然是5,這時就發生了不可重複讀取。
3)、虛幻行:若是update和delect SQL語句未對數據形成影響,極可能遇到了虛幻行問題。
例:用戶A將全部值都把5修改成2,用戶B使用值2插入一個新記錄,用戶A查詢全部值爲2的記錄,但卻找不到新添加的記錄,這時就叫虛幻行。
4)、更新丟失:一個事務的更新覆蓋了其它事務的更新結果,就是所謂的更新丟失。
例:用戶A將全部值從5修改成2,用戶B將全部值從2修改成5,用戶A丟失了他的更新。
二、如何解決併發性的問題
爲了解決這些併發帶來的問題。 咱們須要引入併發控制機制。
悲觀鎖(Pessimistic Lock)——應用場景:寫多
顧名思義,很悲觀。每次去拿數據的時候都認爲別人會修改數據,因此每次在拿數據的時候都會上鎖,這樣別人想拿這個數據就會阻塞直到它拿到鎖。
樂觀鎖(Optimistic Lock)——應用場景:讀多
顧名思義,很樂觀,每次去拿數據的時候都認爲別人不會修改,因此不會上鎖,可是在更新的時候會判斷在此期間別人有沒有去更新這個數據。
1,樂觀鎖適用於多讀的應用類型,這樣能夠提升吞吐量。
2,樂觀鎖通常加時間戳字段(或者自定義版本號字段)來實現。
在實際生產環境裏邊,若是併發量不大且不容許髒讀,可使用悲觀鎖解決併發問題;但若是系統的併發很是大的話,悲觀鎖定會帶來很是大的性能問題,因此咱們就要選擇樂觀鎖定的方法。
樂觀鎖復瑣事務控制
樂觀鎖:大多數是基於數據版本(version)的記錄機制實現的。即爲數據增長一個 版本標識,在基於數據庫表的版本解決方案中,通常是經過爲數據庫表添加一個」version" 字段來實現讀取出數據時,將此版本號同讀出,以後更新時,對此版本號加1。此時,將提交數據的版本號與數據庫表對應記錄的當前版本號進行比對,若是提交的數據版本號大於數據庫當前版本號,則予以更新,不然認爲是過時數據。