1. 程式人生 > 實用技巧 >資料庫死鎖 之 一.啥是死鎖

資料庫死鎖 之 一.啥是死鎖

資料庫死鎖之 啥是死鎖

1.理解死鎖

-- 1.1 學習資料 https://www.cnblogs.com/firstdream/p/4624473.html

資源的死鎖是因為資源的多方,自己需要使用的資源被其他人佔用上鎖;導致互相等待;從而發生死鎖; 先理解下鎖概念,資料庫存在 X 鎖 & S 鎖;
鎖型別 特性 說明 場景
X 排他獨佔 1.一旦上鎖無法上其他鎖 1.update 場景會上鎖 2.delete 場景會上鎖
S 共享 1.可與其他的共享鎖功能存在 2.當存在X鎖,無法上S鎖,因為X排他 1.select 場景

-- 1.2 死鎖場景

-- 1.2.1 死鎖場景一,多表交叉死鎖
A.先建立表TestA,TestB
CREATE TABLE TestA
(
  Name NVARCHAR(100)
)
CREATE TABLE TestB
(
  Name NVARCHAR(100)
)

B.觸發死鎖,讓我們玩壞這個

CREATE PROC p_TestA
as
BEGIN TRANSACTION ;
INSERT INTO TestA(Name) VALUES('張三') ;
SELECT name FROM TestB;
COMMIT;
CREATE PROC p_TestB
as BEGIN TRANSACTION ; INSERT INTO TestB(Name) VALUES('張三') ; SELECT name FROM TestA; COMMIT;
C.寫兩個現程迴圈呼叫這兩個儲存過程
using (SqlConnection conn = new SqlConnection("XXX"))
{
    SqlCommand commmand = new SqlCommand();
    commmand.Connection = conn;
    commmand.CommandText = "exec p_TestA;";
    conn.Open();
    commmand.ExecuteNonQuery();
    conn.Close();
    commmand.Dispose();
    conn.Dispose();
}
:) #看到沒,終於玩壞了
-- 1.2.2 死鎖場景二 單表死鎖
前面所說到,是資源互相的佔用上鎖導致死鎖,那單表怎麼死鎖呢? 語句1:select A,B,C from TestA where id in (''); 語句2:delete TestA where id in (''); 這裡說明下欄位的索引情況;存在主鍵id 是聚集索引,A,B是非聚集索引; 這種場景下,如果高併發的發生語句1和2就會發生死鎖。why?來,我們一步步分析 語句一:首先查詢A,B,因為存在索引,所以在索引 A,B上加上了S鎖,也就是共享查詢鎖;然後下一步呢?C欄位比較特殊了,沒有索引,所以就需要使用一個新概念了,bookmark search ,也就是書籤查;這裡C列會通過聚集索引(物理索引)來查詢,所以會給聚集索引加上S鎖; 縷一縷 第一步:給 A,B 上S鎖 第二部:給 id 上S鎖 語句二:刪除表資料, 第一步:首先給id聚集索引上X鎖(排他鎖); 第二步:資料更新後,要求更新其他索引,索引需要給A,B索引上X鎖; 那麼結論就出來了,這兩個步驟中出現了互相佔用資源的場景,所以死鎖了。。。 這種死鎖其實只要在欄位C加上索引就可以解決,保證查詢中不在依賴主鍵做書籤查詢即可,所以請關注你的select,不要的列不要亂加哦;