日韩久久久精品,亚洲精品久久久久久久久久久,亚洲欧美一区二区三区国产精品 ,一区二区福利

SQL Server鎖分區特性引發死鎖解析

系統 2642 0
原文: SQL Server鎖分區特性引發死鎖解析

鎖分區技術使得SQL Server可以更好地應對并發情形,但也有可能帶來負面影響,這里通過實例為大家介紹,分析由于鎖分區造成的死鎖情形.

前段時間園友 @JentleWang 在我的博客 鎖分區提升并發,以及鎖等待實例 中問及鎖分區的一些特性造成死鎖的問題,這類死鎖并不常見,我們在這里仔細分析下.不了解鎖分區技術的朋友請先看下我的鎖分區那篇實例.

Code(執行測試腳本時請注意執行順序,說明)

步驟1 創建測試數據

      
        use
      
      
         tempdb


      
      
        go
      
      
        create
      
      
        table
      
      
         testdlk

(

id 
      
      
        int
      
      
        identity
      
      (
      
        1
      
      ,
      
        1
      
      ) 
      
        primary
      
      
        key
      
      
        ,

str1 
      
      
        char
      
      (
      
        3000
      
      
        )

)


      
      
        go
      
      
        insert
      
      
        into
      
       testdlk(str1) 
      
        select
      
      
        '
      
      
        aaa
      
      
        '
      
      
        insert
      
      
        into
      
       testdlk(str1) 
      
        select
      
      
        '
      
      
        bbb
      
      
        '
      
      
        insert
      
      
        into
      
       testdlk(str1) 
      
        select
      
      
        '
      
      
        ccc
      
      
        '
      
      
        insert
      
      
        into
      
       testdlk(str1) 
      
        select
      
      
        '
      
      
        ddd
      
      
        '
      
    

步驟2 開啟 session 1 執行語句

      
        --
      
      
        session 1 
      
      
        begin
      
      
        tran
      
      
        update
      
       testdlk 
      
        set
      
       str1
      
        =
      
      
        '
      
      
        ttt
      
      
        '
      
      
        where
      
       id
      
        =
      
      
        1
      
      
        --
      
      
        -session id 55 this example
      
      
        

--
      
      
        -rollback tran 
      
      
        

--
      
      
        -manual after session 3 rollback session 1
      
    

步驟3 開啟session 2 執行語句

      
        --
      
      
        session 2
      
      
        BEGIN
      
      
        TRAN
      
      
        update
      
       testdlk 
      
        set
      
       str1
      
        =
      
      
        '
      
      
        abc
      
      
        '
      
      
        where
      
       id
      
        =
      
      
        2
      
      
        --
      
      
        -update the content of id=2
      
      
        SELECT
      
      
        *
      
      
        FROM
      
       testdlk 
      
        WITH
      
      (TABLOCKX)
      
        --
      
      
        ---- try to get X lock on the object testdlk
      
      
        rollback
      
      
        tran
      
      
        --
      
      
        -session id 58 this example
      
    

步驟4 開啟session 3執行數據

      
        --
      
      
        session 3
      
      
        BEGIN
      
      
        TRAN
      
      
        update
      
       testdlk 
      
        set
      
       str1
      
        =
      
      
        '
      
      
        abc
      
      
        '
      
      
        where
      
       id
      
        =
      
      
        3
      
      
        --
      
      
        -----update the content of id=3 
      
      
        SELECT
      
      
        *
      
      
        FROM
      
       testdlk 
      
        WITH
      
      (TABLOCKX)
      
        --
      
      
        - try to get X lock on the object testdlk
      
      
        rollback
      
      
        tran
      
      
        --
      
      
        -session id 59 this example
      
    

步驟5 創建腳本的session中執行語句

      
        select
      
      
         request_session_id,resource_lock_partition,resource_type,


      
      
        object_name
      
      (resource_associated_entity_id) 
      
        as
      
      
        object_name
      
      
        ,request_mode,request_status 


      
      
        from
      
       sys.dm_tran_locks 
      
        where
      
       resource_database_id
      
        =
      
      
        2
      
      
        and
      
       resource_type
      
        =
      
      
        '
      
      
        OBJECT
      
      
        '
      
      
        select
      
      
         session_id,blocking_session_id,wait_type,resource_description 


      
      
        from
      
       sys.dm_os_waiting_tasks 
      
        where
      
       blocking_session_id 
      
        is
      
      
        not
      
      
        null
      
    

步驟6 session 1中rollback

      
        Rollback
      
       session 
      
        1
      
      
        --
      
      
        when session 1 rollback then session 3 deadlock
      
    

當session 1回滾時,session2 session 3造成死鎖,session 3犧牲.

原因分析.

通過步驟四我們可以得到相應的會話的鎖,及相關等待情況如圖1-1

??????????????????????????????????????????????????????????????? 圖1-1

?

可以看到session 1(圖中55)由于只是更新id=1的列,所以它會在key上加排它鎖(圖中未列出,感興趣朋友可以自行查看),而在Object testdlk中某個鎖分區中圖中為鎖分區1加上意向排它鎖.

Session 2(圖中58)由于更新了id=2的列,所以會在相應Key上加排他鎖,并在某個鎖分區中加意向排他鎖(IX),于此同時由于此事務下面查詢有表級TABLOCKX Hint,此時58會嘗試在表級上排他鎖(X鎖).由于X鎖需要在所有鎖分區中獲得,此時58在鎖分區0中獲得X鎖,但由于鎖分區1中有55獲得了意向排他鎖(IX),所以58在鎖分區1中嘗試獲取X鎖時狀態未Convert,被55阻塞.

Session 3(圖中59)由于更新了id=3的列,所以會在相應key上加排他鎖,同時在某個鎖分區中加意向排他鎖(IX),于此同時由于此事務下面查詢同樣有表級TABLOCKX Hint,這時59也會嘗試在表的所有分區中獲取X鎖.由于58已經獲得鎖分區0的X鎖,所以當59嘗試獲取鎖分區0的X鎖時,就會被58阻塞,狀態為Wait.

問題來了,當55回滾時,其上面的鎖也將被釋放.此時58,59都試圖獲得表級的所有分區X鎖,而又同時在鎖分區中持有IX鎖,這時死鎖就不可避免了.

死鎖視圖如圖1-2所示.

?

????????????????????????????????????????????? 圖1-2

?

問題解決

經過分析,可以看出是由于鎖分區的特性導致IX與不同spid中的X互斥導致,那如果能禁用鎖分區特性不就沒有在個別分區上的IX這回事兒了嗎.這里介紹一個啟動標記 trace flag 1229,可以禁用鎖分區特性.我們可以通過配置管理器中添加啟動標記,也可以在command啟動時加上響應參數.應當注意當使用配置管理器時,我們應在啟動參數末尾配置”-T1229”,如果使用command,這時是t1229(大小寫區分)

這里我用win中command啟用

Code

      Net start mssqlserver /t1229
    

重新啟動后重復上述實例,死鎖就不在出現了.

注: 此實例只為說明由于鎖分區造成的死鎖情形,實際生產中此類情形卻是罕見的,除非遇到這類情形并且沒有更好的規避方式,一般我們還是建議默認此特性.這對提升并發是很有幫助的.

關于鎖分區特性.

通過微軟的在線文檔可以得知,只有當CPU的邏輯數大于等于16時,才會默認開啟此特性,而授權又是按照CPU收費的.問題來了,當CPU小于16我如果想利用此特性是否可以呢?這個再給大家介紹一個啟動跟蹤標記 trace flag 1228.當有兩個及以上邏輯CPU時就會啟動鎖分區特性.不過我們使用時清楚自己的使用場景,是否會因此TF得到好處.由于這是無官方文檔記錄的特性,使用應只針對特定需求,并應慎重.

結語: SQL Server或是其他數據庫系統中任何一個特性的引入總會適應大多數場景,但也會伴隨著特定場景的弊端出現,清楚其所帶來的利弊并合理使用,使得SQL Server適應場景,我們也能適應SQL Server.

SQL Server鎖分區特性引發死鎖解析


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦!!!

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 田东县| 宜州市| 牡丹江市| 扬中市| 北海市| 昭通市| 广南县| 资源县| 石阡县| 松江区| 巩留县| 三门峡市| 庐江县| 罗平县| 江津市| 绥滨县| 桂阳县| 石渠县| 互助| 长丰县| 古蔺县| 神木县| 鹤岗市| 清苑县| 浦东新区| 荣成市| 上饶县| 三亚市| 万载县| 罗江县| 理塘县| 册亨县| 揭阳市| 甘孜县| 黎平县| 当阳市| 鄂温| 思茅市| 邓州市| 新干县| 收藏|