2010-03-30

淺談偵測「死結(DeadLock)」的作法,使用「警示(Alert)」作訊息通知,以WMI 提供者為例

在文章:
淺談偵測「死結(DeadLock)」的作法,以使用「追蹤旗標(Trace flag)」1204、1222為例
http://sharedderrick.blogspot.com/2010/03/deadlocktrace-flag12041222.html

我們已經討論過將發生「死結」的資訊記錄到SQL Server記錄檔內。






但是若要做到主動通知資料庫管理人員得知此事件的發生,
可以使用以下的方式來完成。

功能說明:
使用警示,可將 XML 死結圖形事件儲存在資料表中,以便稍後進行分析。
SQL Server Agent 會提交 WQL 要求、接收 WMI 事件,以及執行工作來回應事件。
請注意,雖然在處理通知訊息時包含數個 Service Broker 物件,但是 WMI 事件提供者會處理建立與管理這些物件的詳細資料。

首先,在 msdb 資料庫中建立一個資料表來容納死結圖形事件。
此資料表包含兩個資料行:AlertTime 資料行容納警示執行的時間,而 DeadlockGraph 資料行容納其中包含死結圖形的 XML 文件。

接著,建立警示。指令碼會先建立警示將執行的工作、將作業步驟加入到工作中,然後將工作目標瞄準為目前的 SQL Server 執行個體。然後,指令碼會建立警示。

作業步驟會擷取 WMI 事件執行個體的 TextData 屬性,然後將該值插入 DeadlockEvents 資料表的 DeadlockGraph 資料行中
。請注意,SQL Server 會以隱含的方式,將字串轉換為 XML 格式。作業步驟會使用 Transact-SQL 子系統,因此,作業步驟不會指定 Proxy。

每當記錄死結圖形追蹤事件時,警示就會執行作業。
對於 WMI 警示,SQL Server Agent 會使用指定的命名空間和 WQL 陳述式來建立通知查詢。

SQL Server Agent 會針對此警示監視本機電腦上的預設執行個體。
WQL 陳述式會要求預設執行個體中的任何 DEADLOCK_GRAPH 事件。若要變更警示所監視的執行個體,將警示的執行個體名稱取代為 @wmi_namespace 中的 MSSQLSERVER。








實作練習:
偵測「死結(DeadLock)」的作法,使用「警示(Alert)」作訊息通知,以WMI 提供者為例


準備工作:
1. 請確認SQL Server 服務啟動帳戶,已經加入到 sysadmin 角色內。




任務1:設定「取代回應警示之所有作業的 Token」
SQL Server Agent 可讓您在 Transact-SQL 作業步驟指令碼中使用 Token。
撰寫作業步驟時使用 Token,所賦予您的彈性與撰寫軟體程式時使用的變數一樣。
在作業步驟指令碼中插入 Token 後,SQL Server Agent 就會先在執行階段取代此 Token,然後再由 Transact-SQL 子系統執行作業步驟。



--01 設定「取代回應警示之所有作業的 Token」
USE [msdb]
GO
EXEC msdb.dbo.sp_set_sqlagent_properties @alert_replace_runtime_tokens=1
GO

請參考下圖所示:





任務2:建立存放「死結(DeadLock)」記錄的資料表:msdb.dbo.DeadlockEvents

-- 01 建立存放「死結(DeadLock)」記錄的資料表:msdb.dbo.DeadlockEvents
USE msdb;
GO
IF  EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[DeadlockEvents]') AND type in (N'U'))
DROP TABLE [dbo].[DeadlockEvents]
GO
CREATE TABLE dbo.DeadlockEvents
(Rid INT IDENTITY, AlertTime DATETIME, DeadlockGraph XML) ;
GO



任務3:建立「作業(Job)」與「步驟(Step)」

--01 建立「作業(Job)」,用於當發生「死結」時,使用「警示」來觸發執行此「作業」。
USE [msdb]
GO
IF  EXISTS (SELECT job_id FROM msdb.dbo.sysjobs_view WHERE name = N'記錄「死結」資訊')
EXEC msdb.dbo.sp_delete_job @job_name=N'記錄「死結」資訊', @delete_unused_schedule=1
GO

EXEC  msdb.dbo.sp_add_job @job_name=N'記錄「死結」資訊',
@enabled=1, @owner_login_name = 'sa',
@notify_level_eventlog=3,
@description=N'此「作業」用來記錄 DEADLOCK_GRAPH 事件' ;
GO

--02 建立「步驟(Step)」:發生「死結」時,將「死結」資訊由 Service Broker 寫入到資料表:DeadlockEvents。
EXEC msdb.dbo.sp_add_jobstep
@job_name = N'記錄「死結」資訊',
@step_name=N'新增資料列到資料表:DeadlockEvents',
@step_id=1,
@on_success_action=1,
@on_fail_action=2,
@subsystem=N'TSQL',
@command=N'INSERT INTO DeadlockEvents (AlertTime, DeadlockGraph)
VALUES (getdate(), N''$(ESCAPE_SQUOTE(WMI(TextData)))'')',
@database_name=N'msdb' ;
GO

--03 指派此「作業」給本機伺服器使用。若未指定,此「作業」將以「多伺服器作業」方式存在
EXEC msdb.dbo.sp_add_jobserver @job_name = N'記錄「死結」資訊' ;
GO

請參考下圖所示:




任務4:建立「警示(Alert)」:發生「死結」,使用此「警示」來回應,並執行「作業」
--01 建立「警示(Alert)」:發生「死結」,使用此「警示」來回應,並執行「作業」。
USE [msdb]
GO
IF  EXISTS (SELECT name FROM msdb.dbo.sysalerts WHERE name = N'回應 DEADLOCK_GRAPH 事件')
EXEC msdb.dbo.sp_delete_alert @name=N'回應 DEADLOCK_GRAPH 事件'
GO
EXEC msdb.dbo.sp_add_alert @name=N'回應 DEADLOCK_GRAPH 事件',
@wmi_namespace=N'\\.\root\Microsoft\SqlServer\ServerEvents\MSSQLSERVER',
@wmi_query=N'SELECT * FROM DEADLOCK_GRAPH',
@job_name=N'記錄「死結」資訊' ;
GO

請參考下圖所示:


由上,已經完成使用「警示」來偵測「死結」的組態。
請自行在設定此「警示」要使用的「操作員(Operator)」來做回應。




在建立完成後,若發生「死結」事件,可以查詢資料表來取得與「死結」相關的資料。
--01 若是發生「死結」事件,可以使用以下的 XQuery 來查詢資料
SELECT Rid, AlertTime ,DeadlockGraph.query('/TextData/deadlock-list') N'DeadlockGraph_XML'
FROM msdb.dbo.DeadlockEvents
ORDER BY Rid DESC

請參考下圖所示:




請將此 XML 文件存檔後,修改其附檔名為 *.xdl。
在開啟此 *.xdl 檔案,就可以在 SSMS 管理工具內,使用圖型介面方式來閱讀與「死結」相關的資料。

請參考下圖所示:




參考資料:
於作業步驟使用 Token
http://msdn.microsoft.com/zh-tw/library/ms175575.aspx

伺服器事件的 WMI 提供者概念
http://msdn.microsoft.com/zh-tw/library/ms180560.aspx

範例:使用伺服器事件的 WMI 提供者建立 SQL Server Agent 警示
http://msdn.microsoft.com/zh-tw/library/ms186385.aspx

WMI Event Alerts
http://sqlblogcasts.com/blogs/martinbell/archive/2009/05/26/WMI-Event-Alerts.aspx

Event Notifications
http://sqlblogcasts.com/blogs/martinbell/archive/2009/05/22/Event-Notifications.aspx

2010-03-29

淺談偵測「死結(DeadLock)」的作法,以使用「追蹤旗標(Trace flag)」1204、1222為例

若是使用 SSMS 管理工具,在遭遇「死結」時,系統將顯示以下的錯誤訊息:

訊息 1205,層級 13,狀態 51,行 2
交易 (處理序識別碼 54) 在 鎖定 資源上被另一個處理序鎖死並已被選擇作為死結的犧牲者。請重新執行該交易。

請參考下圖所示:




死結偵測由鎖定監視器執行緒所執行,它會定期在 Database Engine 執行個體的所有工作中啟動搜尋。

下列幾點描述搜尋程序:
預設間隔是 5 秒。
如果鎖定監視器執行緒發現死結,死結偵測間隔會從 5 秒降低,最低降至 100 毫秒,視死結頻率而定。
如果鎖定監視器執行緒停止尋找死結,Database Engine 會增加搜尋間隔為 5 秒。

如果剛偵測到死結,則會假設後續還有必須等待鎖定的執行緒進入死結循環。
在偵測到死結之後,前面幾個鎖定等待會立即觸發死結搜尋,而不需等到下個死結偵測間隔。

例如,如果目前間隔是 5 秒,並且剛偵測到死結,則下個鎖定等待會立即啟動死結偵測設定。如果這個鎖定等待是死結的一部分,則會立即偵測到它,而不需等到下個死結搜尋期間。


但是若在用戶端應用程式上,若沒有設計處理這類問題的功能,僅是接收到錯誤號碼 1025,但將無從得知為何會發生「死結」。

若要偵測「死結」,可以使用數種方式,例如:使用 SQL Profiler 等,請參考下圖所示:


但使用 SQL Profiler 這類的工具,這表示說必須要事先開啟執行,否則將無法錄製到相關的資訊。



以下將使用「追蹤旗標(trace flag)」作法,將發生「死結」的相關資料,寫入到 SQL Server 記錄檔內作存放。

/*
追蹤旗標 (Trace flag)

追蹤旗標 1204 和追蹤旗標 1222
發生死結時,追蹤旗標 1204 和追蹤旗標 1222 會傳回在 SQL Server 2005 錯誤記錄檔中擷取到的資訊。

追蹤旗標 1204 報告死結所涉及的每一個節點格式化的死結資訊。
追蹤旗標 1222 先按處理序再按資源來格式化死結資訊。

可同時啟用兩種追蹤旗標來取得相同死結事件的兩種表示法。

追蹤旗標 3605 可以將記錄到的結果寫到SQL Server 錯誤記錄檔。

但是蹤旗標 1204 和追蹤旗標 1222 ,已經會將其輸出到 SQL Server 2005 錯誤記錄檔中。
所以,可以省略使用追蹤旗標 3605。
*/
USE master
GO
-- 啟用追蹤旗標 1204、1222。
DBCC TRACEON (1204, 1222,-1)
GO

-- 列出所有針對目前工作階段而啟用的追蹤旗標。
DBCC TRACESTATUS;
GO



在啟用追蹤旗標後,若是遭遇到「死結」,則在 SQL Server 記錄檔,可以看到以下的紀錄,請參考下圖所示:





若需要在 SQL Server 啟動時,一併啟用追蹤旗標來記錄「死結」,可以使用 -T 選項來啟動 SQL Server。
具有 -T 選項的追蹤旗標時,請使用大寫 "T" 來傳送追蹤旗標號碼。


但去調整 SQL Server 的啟動,也可能會發生遇到管理人員忘了有這件事的案例。
或許可以改用,使用「作業(Job)」,在 SQL Agent Service 啟動時,一併啟用追蹤旗標 1204、1222。





-- 停用指定的追蹤旗標 1204、1222。
DBCC TRACEOFF(1204, 1222,-1)
GO

-- 列出所有針對目前工作階段而啟用的追蹤旗標。
DBCC TRACESTATUS;
GO





若是要建立「作業(Job)」於 SQL Server Agent 服務啟動,一併使用「追蹤旗標」來偵測「死結」,請參考以下的範例:

USE [msdb]
GO
--01 建立「作業」
IF  EXISTS (SELECT job_id FROM msdb.dbo.sysjobs_view WHERE name = N'使用「追蹤旗標」來偵測「死結」')
EXEC msdb.dbo.sp_delete_job @job_name=N'使用「追蹤旗標」來偵測「死結」', @delete_unused_schedule=1
GO
EXEC msdb.dbo.sp_add_job @job_name=N'使用「追蹤旗標」來偵測「死結」',
@enabled=1,
@owner_login_name=N'sa'

--02 建立「步驟」
EXEC msdb.dbo.sp_add_jobstep
@job_name =  N'使用「追蹤旗標」來偵測「死結」',
@step_name=N'stp01_使用「追蹤旗標(Trace flag)」1204、1222',
@step_id=1,
@cmdexec_success_code=0,
@on_success_action=1,
@on_success_step_id=0,
@on_fail_action=2,
@os_run_priority=0, @subsystem=N'TSQL',
@command=N'-- 啟用追蹤旗標 1204、1222。
DBCC TRACEON (1204, 1222,-1)
GO  ',
@database_name=N'master'

--03 設定排程
EXEC msdb.dbo.sp_add_jobschedule
@job_name =  N'使用「追蹤旗標」來偵測「死結」',
@name=N'sch_SQLServerAgent啟動時,自動啟動',
@enabled=1,
@freq_type=64,
@freq_interval=0,
@freq_subday_type=0,
@freq_subday_interval=0,
@freq_relative_interval=0,
@freq_recurrence_factor=0,
@active_start_date=20100330,
@active_end_date=99991231,
@active_start_time=0,
@active_end_time=235959

--04 指派此「作業」給本機伺服器使用。若未指定,此「作業」將以「多伺服器作業」方式存在
EXEC msdb.dbo.sp_add_jobserver @job_name =  N'使用「追蹤旗標」來偵測「死結」' ;
GO





參考資料:
偵測與結束死結
http://msdn.microsoft.com/zh-tw/library/ms178104.aspx

使用 SQL Server 服務啟動選項
http://msdn.microsoft.com/zh-tw/library/ms190737.aspx

SQL Server 技術公告-如何解決死結
http://support.microsoft.com/?kbid=832524

處理 SQL Server 中的死結情況的描述
http://support.microsoft.com/kb/118552/zh-tw

2010-03-05

淺談與統計資料(Statistics) 相關的資料庫屬性:自動建立統計資料、自動更新統計資料與自動非同步更新統計資料。AUTO_CREATE_STATISTICS、AUTO_UPDATE_STATISTICS、AUTO_UPDATE_STATISTICS_ASYNC

與「統計資料」相關的資料庫屬性有:


(1)自動建立統計資料(AUTO_CREATE_STATISTICS)

(2)自動更新統計資料(AUTO_UPDATE_STATISTICS)

(3)自動非同步更新統計資料(AUTO_UPDATE_STATISTICS_ASYNC) -- SQL Server 2005 版本新增加



在 SQL Server 2008 線上叢書 (2009 年 7 月) 寫到:
自動建立統計資料選項 AUTO_CREATE_STATISTICS 和自動更新統計資料選項 AUTO_UPDATE_STATISTICS 預設已開啟,而且我們建議您針對大部分的使用者資料庫使用此預設值。


查詢最佳化工具會使用「統計資料」來建立可改善查詢效能的查詢計畫。

但在 SQL Server 2000 版本,此項可能會產生不必要的額外負荷,例如:
大型資料表在初始化產生「統計資料」時。


有巨量的資料的異動作業,導致需要同步更新「統計資料」。


在 SQL Server 2000 版本使用的是系統資料表 sysindexes 的 rowmodctr 資料行內容值作為「統計資料」的依據,需要即時更新,這可能會耗用過的資源。

在某些特定情形下,或許可以考慮停用「統計資料」,手動排程於離峰時間執行更新「統計資料」。


在 SQL Server 2005 版本,已不再使用系統資料表 sysindexes 的 rowmodctr 資料行內容值。而是使用系統基底資料表 sys.sysrowsetcolumns 的 rcmodified 資料行。

並且增加了自動非同步更新統計資料(AUTO_UPDATE_STATISTICS_ASYNC)選項。



在 SQL Server 2008 版本使用系統基底資料表 sys.sysrscols 的 rcmodified 資料行。
並且增加了「篩選統計資料(filtered statistics)」與「篩選索引(Filtered indexes)」等功能。






認識「自動非同步更新統計資料(AUTO_UPDATE_STATISTICS_ASYNC) 」


若為 [True],初始化自動更新過期統計資料的查詢,將不會在編譯之前等待統計資料更新。當有可用的更新統計資料時,後續的查詢會使用這些統計資料。

若為 [False],初始化自動更新過期統計資料的查詢,則會等到可在查詢最佳化計劃中使用更新的統計資料。

除非 [自動更新統計資料] 也設定為 [True],否則將這個選項設定為 [True] 時並不會有任何影響。



以下範例將討論若是關閉「統計資料」相關功能,將導致系統使用不恰當的索引來查詢資料。

--00 建立範例資料庫 AutoStat 與資料表 TH01
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
USE [master]
GO
IF  EXISTS (SELECT name FROM sys.databases WHERE name = N'AutoStat')
DROP DATABASE [AutoStat]
GO
CREATE DATABASE AutoStat
GO
USE AutoStat
GO
-- 建立資料表 TH01
SELECT  TransactionID, ProductID, ReferenceOrderID, ReferenceOrderLineID, TransactionDate, TransactionType, Quantity, ActualCost, ModifiedDate
INTO TH01
FROM    AdventureWorks2008.Production.TransactionHistory
-- 新增資料列
INSERT TH01(ProductID, ReferenceOrderID, ReferenceOrderLineID, TransactionDate, TransactionType, Quantity, ActualCost, ModifiedDate)
SELECT  ProductID, ReferenceOrderID, ReferenceOrderLineID, TransactionDate, TransactionType, Quantity, ActualCost, ModifiedDate
FROM    AdventureWorks2008.Production.TransactionHistory
-- 建立 CLUSTERED INDEX:TransactionID
CREATE CLUSTERED INDEX [CL_TID] ON [dbo].[TH01]
(
[TransactionID] ASC
)WITH (STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
-- 建立 NONCLUSTERED INDEX:ProductID
CREATE NONCLUSTERED INDEX [NCL_PID] ON [dbo].[TH01]
(
[ProductID] ASC
)WITH (STATISTICS_NORECOMPUTE  = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
GO
--
UPDATE TH01
SET ProductID=9999999
WHERE TransactionID=100000


以下為開始執行查詢資料表與分析其索引使用方式:
USE AutoStat
GO
-- 總計資料列有:226886
SELECT COUNT(*) FROM TH01
-- 檢視資料
SELECT * FROM TH01

-- EX1. 檢視執行計畫與磁碟活動量的相關資訊
/*
「索引搜尋(NonClustered Index Seek)」+「索引鍵查閱(Clustered Key Lookup)」+「巢狀迴圈(Nested Loops)」
估計的子樹成本:0.0065704
預估回傳資料列:1

資料表 'TH01'。掃描計數 1,邏輯讀取 5,實體讀取 1,讀取前讀取 0,LOB 邏輯讀取 0,LOB 實體讀取 0,LOB 讀取前讀取 0。
*/
SET STATISTICS IO ON
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
GO
SELECT TransactionDate
FROM TH01
WHERE ProductID=9999999




-- EX2.
/*
「叢集索引掃描(Clustered Index Scan)」
估計的子樹成本:1.421
預估回傳資料列:13140

資料表 'TH01'。掃描計數 1,邏輯讀取 1584,實體讀取 5,讀取前讀取 1308,LOB 邏輯讀取 0,LOB 實體讀取 0,LOB 讀取前讀取 0。
*/
SET STATISTICS IO ON
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
GO
SELECT TransactionDate
FROM TH01
WHERE ProductID BETWEEN 880 AND 900





/*=========================================================*/
--01 關閉 AUTO_CREATE_STATISTICS 與 AUTO_UPDATE_STATISTICS
USE [master]
GO
ALTER DATABASE [AutoStat]
SET AUTO_CREATE_STATISTICS OFF
WITH NO_WAIT
GO
ALTER DATABASE [AutoStat]
SET AUTO_UPDATE_STATISTICS OFF
WITH NO_WAIT
GO
--02 將 ProductID 資料行內容值都改為 9999999
/*
總計資料列有:226886
但 ProductID 資料行內容值都是 9999999
*/
USE AutoStat
GO
UPDATE TH01
SET ProductID=9999999


/*=========================================================*/
-- EX3. 再度先前 EX1. 陳述式,檢視其執行計畫,仍然與關閉 AUTO_UPDATE_STATISTICS 選項之前一樣
/*
「索引搜尋(NonClustered Index Seek)」+「索引鍵查閱(Clustered Key Lookup)」+「巢狀迴圈(Nested Loops)」
估計的子樹成本:0.0065704
預估回傳資料列:1,但實際上則是會回傳資料列:226886 筆

資料表 'TH01'。掃描計數 1,邏輯讀取 680971,實體讀取 34,讀取前讀取 56,LOB 邏輯讀取 0,LOB 實體讀取 0,LOB 讀取前讀取 0。
*/
SET STATISTICS IO ON
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
GO
SELECT TransactionDate
FROM TH01
WHERE ProductID=9999999





因為「統計資料」沒有更新,導致系統使用未更新的「統計資料」,使用不恰當的索引來查詢資料。

/*=========================================================*/
--01 重新啟用 AUTO_CREATE_STATISTICS 與 AUTO_UPDATE_STATISTICS 選項
USE [master]
GO
ALTER DATABASE [AutoStat]
SET AUTO_CREATE_STATISTICS ON
WITH NO_WAIT
GO
ALTER DATABASE [AutoStat]
SET AUTO_UPDATE_STATISTICS ON
WITH NO_WAIT
GO
--02 手動立即更新統計資料
EXEC sp_updatestats
GO


/*=========================================================*/
-- EX4. 再度檢視其執行計畫,系統已經重新產生,並且選用耗用成本最低的索引來查詢
/*
「叢集索引掃描(Clustered Index Scan)」
估計的子樹成本:1.421
預估回傳資料列:226886

資料表 'TH01'。掃描計數 1,邏輯讀取 1584,實體讀取 5,讀取前讀取 1594,LOB 邏輯讀取 0,LOB 實體讀取 0,LOB 讀取前讀取 0。
*/
USE AutoStat
GO
SET STATISTICS IO ON
DBCC DROPCLEANBUFFERS
DBCC FREEPROCCACHE
GO
SELECT TransactionDate
FROM TH01
WHERE ProductID=9999999




與 EX3. 比較起來,因為「統計資料」是正確的,系統可以選用耗用成本最低的索引來查詢。



參考資料:
Auto update statistics and auto create statistics - should you leave them on and/or turn them on??
http://www.sqlskills.com/blogs/Kimberly/post/Auto-update-statistics-and-auto-create-statistics-should-you-leave-them-on-andor-turn-them-on.aspx

Filtered indexes and filtered stats might become seriously out-of-date
http://www.sqlskills.com/BLOGS/KIMBERLY/post/Filtered-indexes-and-filtered-stats-might-become-seriously-out-of-date.aspx

Auto-create and Auto-update Statistics
http://blogs.msdn.com/ianjo/archive/2005/11/10/491549.aspx

在 SQL Server 的統計的維護功能 (autostats)
http://support.microsoft.com/kb/195565

分析執行緩慢之查詢的檢查清單
http://technet.microsoft.com/zh-tw/library/ms177500.aspx

使用統計資料來改善查詢效能
http://technet.microsoft.com/zh-tw/library/ms190397.aspx

系統基底資料表
http://technet.microsoft.com/zh-tw/library/ms179503.aspx

Q. The ability of SQL Server 2000 to automatically update statistics for my tables and indexes is enabled by default. How often does SQL Server perform this update, and does the action have a negative effect on performance?
http://www.microsoft.com/technet/abouttn/flash/tips/tips_070604.mspx

SQL Server Statistics
http://blogs.technet.com/rob/archive/2008/05/16/sql-server-statistics.aspx

Statistics Used by the Query Optimizer in Microsoft SQL Server 2005
http://technet.microsoft.com/zh-tw/library/cc966419%28en-us%29.aspx

Index Metadata and Statistics Update Date for SQL Server
http://www.mssqltips.com/tip.asp?tip=1550

The auto update statistics option, the auto create statistics option, and the Parallelism setting are turned off in the SQL Server database instance that hosts the BizTalk Server BizTalkMsgBoxDB database
http://support.microsoft.com/?scid=kb%3Ben-us%3B912262&x=12&y=7

The Parallelism setting for the instance of SQL Server when you configure BizTalk Server
http://support.microsoft.com/?scid=kb%3Ben-us%3B899000&x=18&y=17