並行執行做爲提高查詢響應時間,提升用戶體驗的一種有效手段被你們所熟知,感興趣的朋友能夠看我之前的博客SQL Server優化技巧之SQL Server中的"MapReduce", SQL Server優化器特性-位圖過濾(Bitmap),然而正如我一直強調的,任何事物均有利弊,重點在於抉擇.近日有朋友問我關於在今年7月份SQL Saturday中分享的並行執行中關於並行死鎖的內容,這裏我就詳細解釋下我舉的實例中的並行死鎖.html
並行死鎖咱們能夠理解爲SQL Server的」BUG」,即按照並行方式執行時遭遇特定異常使得執行沒法繼續.官方給的解決方式大多很簡單,改成串行就能夠了.但其中仍是有值得咱們深究的地方以便咱們更好的利用並行.數據庫
注:因爲案例涉及的並行知識點較多,缺少相關知識的同窗能夠先預覽一下我當時分享的PPT,若是有不清楚的地方也能夠私信我. Inside Parallel Query架構
閒篇到此,上實例分佈式
生成測試數據ide
CREATE TABLE Numbers ( Number INT NOT NULL, CONSTRAINT PK_Numbers PRIMARY KEY CLUSTERED (Number) WITH FILLFACTOR = 100 ) INSERT INTO Numbers SELECT (a.Number * 256) + b.Number AS Number FROM ( SELECT number FROM master..spt_values WHERE type = 'P' AND number <= 255 ) a (Number), ( SELECT number FROM master..spt_values WHERE type = 'P' AND number <= 255 ) b (Number)
接下來咱們執行以下語句,取30000下最大偶數,此時我將執行並行數maxdop隨意調整爲奇數,3,5,7個人執行均可以迅速返回結果.測試
執行代碼優化
set statistics time on select maxN=max(num.number) from dbo.numbers as num where num.number<30000 and convert(integer,convert(varchar(max),num.number)) % 2=0 option ( Maxdop 3,-----5,7 querytraceon 8649 );
但當我將並行數調整爲偶數時,執行時間竟然長達數秒…打開trace profiler跟蹤dead lock chain咱們發現,當並行數爲偶數時出現了死鎖.spa
如圖1-1,1-2,1-3線程
select maxN=max(num.number) from dbo.numbers as num where num.number<30000 and convert(integer,convert(varchar(max),num.number)) % 2=0 option ( Maxdop 4,-----2,6 querytraceon 8649 );
圖1-1code
圖1-2
圖1-3
咋一看有的同窗可能以爲蹊蹺,Bug多是不少人的第一反應.而到底發生了什麼由咱們具體分析下並行死鎖的相應執行計劃
分析:
1訪問基表數據時用的是彙集索引掃描,但掃描方式是backward,而SQL server中只有forward scan能夠並行掃描,backward只能串行掃描
2 所以在作exchange向各個threads分發數據時(distribute streams)採用roundrobin輪詢分發數據,這勢必形成奇偶數據按threads分開流向下一個過濾操做符
3 在Filter時將奇數的數據過濾,而相應的threads也就沒有了數據
4 因此在最後exchange彙總數據時(gather streams)有的threads沒有數據,於是形成死鎖.
注:thread 0爲主線程,不參與並行分支工做
分析如圖2-1
圖2-1
而反觀並行採用奇數並行數,這時當分發數據時就不會形成某個thread所持有的數據只是奇數或是偶數,也就不會形成後來的情形,死鎖也就不會出現.如圖2-2感興趣的同窗能夠作實驗調整並行數並閱讀相應的執行計劃.
圖2-2
小結:要讀懂並行執行計劃須要必定的知識儲備,不瞭解的同窗可先看我分享的PPT.並行執行作爲提高複雜查詢響應時間的殺手鐗被不少數據庫廠商普遍應用,而其中的部分思想也應用的分佈式系統當中,能夠說當下硬件架構下並行是執行引擎健壯性的重要體現.
結語:萬事皆有因果,一個簡單的BUG能夠作爲迴應,但深究可能窺其本質,而且頗有意思.技術人需有這種精神.
認爲有收穫的同窗請點贊.