sqlserver併發處理,鎖和事務

2022-01-28 16:30:57 字數 4588 閱讀 5955

本文系**,謝謝:

另外這個也不錯

鎖的概述

一. 為什麼要引入鎖

多個使用者同時對資料庫的併發操作時會帶來以下資料不一致的問題:

丟失更新

a,b兩個使用者讀同一資料並進行修改,其中乙個使用者的修改結果破壞了另乙個修改的結果,比如訂票系統

髒讀 a使用者修改了資料,隨後b使用者又讀出該資料,但a使用者因為某些原因取消了對資料的修改,資料恢復原值,此時b得到的資料就與資料庫內的資料產生了不一致

不可重複讀

a使用者讀取資料,隨後b使用者讀出該資料並修改,此時a使用者再讀取資料時發現前後兩次的值不一致

併發控制的主要方法是封鎖,鎖就是在一段時間內禁止使用者做某些操作以避免產生資料不一致

二 鎖的分類

鎖的類別有兩種分法:

1. 從資料庫系統的角度來看:分為獨佔鎖(即排它鎖),共享鎖和更新鎖

ms-sql server 使用以下資源鎖模式。

鎖模式 描述

共享 (s) 用於不更改或不更新資料的操作(唯讀操作),如 select 語句。

更新 (u) 用於可更新的資源中。防止當多個會話在讀取、鎖定以及隨後可能進行的資源更新時發生常見形式的死鎖。

排它 (x) 用於資料修改操作,例如 insert、update 或 delete。確保不會同時同一資源進行多重更新。

意向鎖 用於建立鎖的層次結構。意向鎖的型別為:意向共享 (is)、意向排它 (ix) 以及與意向排它共享 (six)。

架構鎖 在執行依賴於表架構的操作時使用。架構鎖的型別為:架構修改 (sch-m) 和架構穩定性 (sch-s)。

大容量更新 (bu) 向表中大容量複製資料並指定了 tablock 提示時使用。

共享鎖

共享 (s) 鎖允許併發事務讀取 (select) 乙個資源。資源上存在共享 (s)

鎖時,任何其它事務都不能修改資料。一旦已經讀取資料,便立即釋放資源上的共享 (s)

鎖,除非將事務隔離級別設定為可重複讀或更高階別,或者在事務生存週期內用鎖定提示保留共享 (s) 鎖。

更新鎖

更新 (u) 鎖可以防止通常形式的死鎖。一般更新模式由乙個事務組成,此事務讀取記錄,獲取資源(頁或行)的共享 (s)

鎖,然後修改行,此操作要求鎖轉換為排它 (x) 鎖。如果兩個事務獲得了資源上的共享模式鎖,然後試圖同時更新資料,則乙個事務嘗試將鎖轉換為排它

(x) 鎖。共享模式到排它鎖的轉換必須等待一段時間,因為乙個事務的排它鎖與其它事務的共享模式鎖不相容;發生鎖等待。第二個事務試圖獲取排它 (x)

鎖以進行更新。由於兩個事務都要轉換為排它 (x) 鎖,並且每個事務都等待另乙個事務釋放共享模式鎖,因此發生死鎖。

若要避免這種潛在的死鎖問題,請使用更新 (u) 鎖。一次只有乙個事務可以獲得資源的更新 (u) 鎖。如果事務修改資源,則更新 (u) 鎖轉換為排它 (x) 鎖。否則,鎖轉換為共享鎖。

排它鎖

排它 (x) 鎖可以防止併發事務對資源進行訪問。其它事務不能讀取或修改排它 (x) 鎖鎖定的資料。

意向鎖

意向鎖表示 sql server 需要在層次結構中的某些底層資源上獲取共享 (s) 鎖或排它 (x)

鎖。例如,放置在表級的共享意向鎖表示事務打算在表中的頁或行上放置共享 (s) 鎖。在表級設定意向鎖可防止另乙個事務隨後在包含那一頁的表上獲取排它

(x) 鎖。意向鎖可以提高效能,因為 sql server

僅在表級檢查意向鎖來確定事務是否可以安全地獲取該錶上的鎖。而無須檢查表中的每行或每頁上的鎖以確定事務是否可以鎖定整個表。

意向鎖包括意向共享 (is)、意向排它 (ix) 以及與意向排它共享 (six)。

鎖模式 描述

意向共享 (is) 通過在各資源上放置 s 鎖,表明事務的意向是讀取層次結構中的部分(而不是全部)底層資源。

意向排它 (ix) 通過在各資源上放置 x 鎖,表明事務的意向是修改層次結構中的部分(而不是全部)底層資源。ix 是 is 的超集。

與意向排它共享 (six) 通過在各資源上放置 ix

鎖,表明事務的意向是讀取層次結構中的全部底層資源並修改部分(而不是全部)底層資源。允許頂層資源上的併發 is 鎖。例如,表的 six

鎖在表上放置乙個 six 鎖(允許併發 is 鎖),在當前所修改頁上放置 ix 鎖(在已修改行上放置 x

鎖)。雖然每個資源在一段時間內只能有乙個 six 鎖,以防止其它事務對資源進行更新,但是其它事務可以通過獲取表級的 is

鎖來讀取層次結構中的底層資源。

獨佔鎖:只允許進行鎖定操作的程式使用,其他任何對他的操作均不會被接受。執行資料更新命令時,sql server會自動使用獨佔鎖。當物件上有其他鎖存在時,無法對其加獨佔鎖。

共享鎖:共享鎖鎖定的資源可以被其他使用者讀取,但其他使用者無法修改它,在執行select時,sql server會對物件加共享鎖。

更新鎖:當sql server準備更新資料時,它首先對資料物件作更新鎖鎖定,這樣資料將不能被修改,但可以讀取。等到sql server確定要進行更新資料操作時,他會自動將更新鎖換為獨佔鎖,當物件上有其他鎖存在時,無法對其加更新鎖。

2. 從程式設計師的角度看:分為樂觀鎖和悲觀鎖。

樂觀鎖:完全依靠資料庫來管理鎖的工作。

悲觀鎖:程式設計師自己管理資料或物件上的鎖處理。

ms-sqlserver 使用鎖在多個同時在資料庫內執行修改的使用者間實現悲觀併發控制

三 鎖的粒度

鎖粒度是被封鎖目標的大小,封鎖粒度小則併發性高,但開銷大,封鎖粒度大則併發性低但開銷小

sql server支援的鎖粒度可以分為為行、頁、鍵、鍵範圍、索引、表或資料庫獲取鎖

資源 描述

rid 行識別符號。用於單獨鎖定表中的一行。

鍵 索引中的行鎖。用於保護可序列事務中的鍵範圍。

頁 8 千位元組 (kb) 的資料頁或索引頁。

擴充套件盤區 相鄰的八個資料頁或索引頁構成的一組。

表 包括所有資料和索引在內的整個表。

db 資料庫。

四 鎖定時間的長短

鎖保持的時間長度為保護所請求級別上的資源所需的時間長度。

用於保護讀取操作的共享鎖的保持時間取決於事務隔離級別。採用 read committed

rowlock,tablelock個人認為他們都屬於排它鎖

鎖定提示                                 描述

holdlock        將共享鎖保留到事務完成,而不是在相應的表、行或資料頁不再需要時就立即釋放鎖。holdlock        等同於serializable

nolock        不要發出共享鎖,並且不要提供排它鎖。當此選項生效時,可能會讀取未提交的事務或一組在讀取中間回滾的頁面。有可能發生髒讀。僅應用於select語句。

paglock        在通常使用單個表鎖的地方採用頁鎖。

readcommitted        用與執行在提交讀隔離級別的事務相同的鎖語義執行掃瞄。預設情況下,sql        server        2000        在此隔離級別上操作。

readpast        跳 過鎖定行。此選項導致事務跳過由其它事務鎖定的行(這些行平常會顯示在結果集內),而不是阻塞該事務,使其等待其它事務釋放在這些行上的鎖。 readpast        鎖提示僅適用於執行在提交讀隔離級別的事務,並且只在行級鎖之後讀取。僅適用於select語句。

readuncommitted        等同於        nolock。

repeatableread        用與執行在可重複讀隔離級別的事務相同的鎖語義執行掃瞄。

rowlock        使用行級鎖,而不使用粒度更粗的頁級鎖和表級鎖。

serializable用與執行在可序列讀隔離級別的事務相同的鎖語義執行掃瞄。等同於        holdlock。

tablock        使用表鎖代替粒度更細的行級鎖或頁級鎖。在語句結束前,sql        server        一直持有該鎖。但是,如果同時指定        holdlock,那麼在事務結束之前,鎖將被一直持有。

tablockx        使用表的排它鎖。該鎖可以防止其它事務讀取或更新表,並在語句或事務結束前一直持有。

updlock        讀取表時使用更新鎖,而不使用共享鎖,並將鎖一直保留到語句或事務的結束。updlock        的優點是允許您讀取資料(不阻塞其它事務)並在以後更新資料,同時確保自從上次讀取資料後資料沒有被更改。

xlock        使用排它鎖並一直保持到由語句處理的所有資料上的事務結束時。可以使用        paglock        或        tablock        指定該鎖,這種情況下排它鎖適用於適當級別的粒度

sql server對併發的處理 樂觀鎖和悲觀鎖

假如兩個執行緒同時修改資料庫同一條記錄,就會導致後一條記錄覆蓋前一條,從而引發一些問題。例如 乙個售票系統有乙個餘票數,客戶端每呼叫一次出票方法,餘票數就減一。情景 總共300張票,假設兩個售票點,恰好在同一時間出票,它們做的操作都是先查詢餘票數,然後減一。一般的sql語句 12 3456 789d...

高併發和鎖

面試被問到了這個問題,找了答案,記錄一下 假如有100w個使用者,搶一張票,除了負載均衡的辦法,怎麼支援高併發?修改字段 將庫存欄位number欄位設為unsigned,當庫存為0時,因為字段不能為負數,將會返回false 利用悲觀鎖 不適合高併發 悲觀鎖,也就是在修改資料的時候,採用鎖定狀態,排斥...

併發安全和鎖

有時候在go 中可能會存在多個goroutine同時操作乙個資源,這種情況會發生資料競態問題。舉例 var x int64 var wg sync.waitgroup func add wg.done func main 上面的 中開啟了 2 個goroutine去累加變數x的值,這 2 個goro...