天天看點

Sql Server之旅——第十四站 深入的探讨鎖機制

  上一篇我隻是做了一個堆表讓大家初步的認識到鎖的痙攣狀态,但是在現實世界上并沒有這麼簡單的事情,起碼我的表不會沒有索引對吧,,,還

有就是我的表一定會有很多的連接配接過來,10:1的讀寫,很多碼農可能都會遇到類似神乎其神的死鎖,卡住,讀不出來,插不進入等等神仙的事情導緻性

能低下,這篇我們一起來探讨下。

一: 當select遇到性能低下的update會怎麼樣?

1. 還是使用原始的person表,插入6條資料,由于是4000位元組,是以兩條資料就是一個資料頁,如下圖:

2. 為了模拟性能低下的update操作,我們開個顯式事務來更新id=4的記錄,并且用profile看一下,如下圖:

Sql Server之旅——第十四站 深入的探讨鎖機制

3. 然後我們開下另一個會話連接配接,讀取id=6的記錄會是怎樣????好奇嗎????

Sql Server之旅——第十四站 深入的探讨鎖機制

從上面流程你是否看到,當掃描到89号資料頁的slot1槽位的時候卡住了。。。我想你應該知道update正好已經給這條記錄加上了x鎖。。。如果你

夠細心,你還會發現,給s鎖附加記錄的條件是在當引擎發現記錄所在的資料頁已經附加上了ix鎖的情況下,才給該号資料頁下的每條記錄附加s鎖,

對吧。。。好了,既然在profile上面看不到了,我還是有其他辦法來判斷到底select語句現在處于什麼狀态。

4. 使用sys.dm_tran_locks來看目前各個連接配接持有鎖的狀态。

Sql Server之旅——第十四站 深入的探讨鎖機制

仔細觀察上圖可以看到,目前有51和52号會話,51号在1:89:1槽位上使用了x鎖并且沒有釋放,52号此時也進入了1:89:1中,并且想給該

rowid附加s鎖,但是你也知道s和x鎖是排斥的,是以很無奈的一直保持等待狀态。

二:使用索引或許可以幫你逃過一劫

  當你看完上面的講叙,是不是有點害怕???要是在生産環境下出現了這種情況,那我們是不是死的很慘???那接下來使用索引是不是真

的可以幫我們躲過一劫呢???下面跟我一起看一看。

1. 建立索引index

2. 然後我們看下資料頁的分布情況,可以看到下圖中78,89,90是表資料頁,93号為索引資料頁。

Sql Server之旅——第十四站 深入的探讨鎖機制

3. 麻蛋的,繼續執行上面的那個慢update

4. 激動人心的時刻來了,由于資料太少,是以我這裡強制讓引擎執行我建立的索引,看看結果怎樣?

Sql Server之旅——第十四站 深入的探讨鎖機制

居然沒卡住???現在是不是有一股強烈的好奇心來了,狗狗狗。。。馬上開啟profile,看看到底都發生了什麼???

Sql Server之旅——第十四站 深入的探讨鎖機制

仔細看完這個圖,是不是覺得很有意思呢???具體步驟如下:

第一步:給表(object)加上is鎖。

第二步:因為要走索引,給93号索引資料頁加上is鎖。

第三步:找到93号索引資料頁的目标key,給這個key加上s鎖,有人可能就會問了。。。這個key不就是6嘛,為什麼這個key=(61005a25560e),

    你要是太好奇我可以告訴你,年輕人說話不要太屌,每行索引記錄都有一個散列值,這個值就是根據索引的幾個字段散列出來的,好處就是

   防止你的索引長度過大,導緻鎖這個記錄的時候太耗費鎖空間了。。。。如果你還是不太相信的話,我用dbcc給你看一看。

Sql Server之旅——第十四站 深入的探讨鎖機制

第四步:根據這個key直接跳到存放記錄的90号資料頁中,萬幸的是update的記錄剛好不在90号資料頁中。。。。就這樣躲過一劫了。。。然

   後select順利的讀取到了該讀的記錄,最後釋放相關的is鎖。