SQL Server 的事務和鎖(一)
最近在項目中進行壓力測試遇到了數據庫的死鎖問題,簡言之,如下的代碼在 SERIALIZABLE 隔離級別造成了死鎖:
SELECT @findCount=COUNT(id) FROM MyTable WHERE [fk_related_id]=@Argument IF (@findCount > 0) BEGIN ROLLBACK TRANSACTION RETURN ERROR_CODE END INSERT INTO MyTable ([fk_related_id],…) VALUES (@Argument,…) COMMIT TRANSACTION RETURN SUCCESS_CODE
在搞清楚這個問題的過程中做了不少的實驗,與各位共享。這一篇是開篇,主要說明的是 SQL Server 的四種(其實還有別的)經典的事務隔離級別,以及在不同的隔離級別下鎖的使用手段,以及所帶來的不同的數據一致性。
SQL Server 中鎖的種類(Schema操作就暫時不涉及了)
| 鎖類型 | 描述 |
| (Shared Lock) | 用于只讀操作數據鎖定 |
| (Update Lock) | 用于數據的更新,在數據真正的需要更新的時候會申請升級為X鎖。 |
| X(Exclusive Lock) | 獨占鎖,用于數據的更改。 |
| Key-Range Lock(稍后討論) | 僅僅在 Serializable 隔離級別保護數據,以避免任何有可能使得本事務第二次讀取信息產生錯誤的數據插入操作 |
各個事務隔離級別下鎖的使用
SQL Server 中有四種事務隔離級別,具體的大家去參建 MSDN。下面列出在不同的事務隔離級別下這些鎖是如何使用的:
| 隔離級別 | 讀數據鎖狀態 | 寫數據鎖狀態 | 鎖持有時間 |
| Read Uncommitted | 不獲得任何鎖 | 不獲得任何鎖 | |
| Read Committed | 數據獲得S鎖 | 對于 INSERT、DELETE、UPDATE的執行,獲得X鎖;對于UPDATE的標記,獲得U鎖; | 讀完即釋放,并不持有至事務結束。 |
| Repeatable Read | 數據獲得S鎖 | 對于 INSERT、DELETE、UPDATE的執行,獲得X鎖;對于UPDATE的標記,獲得U鎖; | 持有至事務結束 |
| Serializable | 數據獲得S鎖,同時獲得Key-Range鎖。 | 對于 INSERT、DELETE、UPDATE的執行,獲得X鎖;對于UPDATE的標記,獲得U鎖,同時獲得Key-Range鎖。 | 持有至事務結束 |
我們可以利用這些知識形象說明各個隔離級別下的數據一致性:
Read Uncommitted 級別
(1)臟讀
(2)更新丟失
(3)不可重復讀
(4)幻讀
Read Committed 級別
(1)臟讀
(2)更新丟失
(3)不可重復讀
(4)幻讀
Repeatable Read 級別
(1)臟讀
(2)更新丟失
(3)不可重復讀
(4)幻讀
Serializable 級別
(1)臟讀
(2)更新丟失
(3)不可重復讀
(4)幻讀
我們從上圖可以比較直觀的看到以下的結論
| 臟讀 | 更新丟失 | 不可重復讀 | 幻讀 | |
| Read Uncommitted | 可能 | 可能 | 可能 | 可能 |
| Read Committed | 不可能 | 可能 | 可能 | 可能 |
| Repeatable Read | 不可能 | 不可能 | 不可能 | 可能 |
| Serializable | 不可能 | 不可能 | 不可能 | 不可能 |
這一篇到此為止,下一篇詳細介紹 Key-Range Lock 并分析開篇提到的死鎖問題。




![clip_image001[5] clip_image001[5]](https://images.cnblogs.com/cnblogs_com/lxconan/201110/201110200038187430.png)











浙公網安備 33010602011771號