本記事はマイクロソフト社員によって公開されております。
高可用性の接続ブローカー (RDCB) 構成時、DB のトランザクションログが増大する事象について、回避策などをお知らせいたします。
事象:
SQL Server を高可用性 RDCB のDB として使用している際に、SQL Server のトランザクション ログ (.ldf ファイル) が肥大化する場合があることを確認しております。
肥大化にペースは環境によりますが、数分で GB 単位の出力がされることも報告されております。
原因:
RDCB は BrokerNotifications_Get_Timeout ストアド プロシージャにて 30 秒 に 1 度 BrokerNotification テーブルから古いセッション情報の削除処理を行います (DELETE 文)。その後 SELECT文にて情報を採取いたしますが、この SELECT 文にて、パラレルデッドロックが発生しております。この DELETE 文と SELECT 文は1つのトランザクションとして処理されるよう登録されておりますので、SELECT 文がデッドロックで失敗した場合、テーブルの整合性を保つために DELETE したレコードも Rollback いたします。
デッドロックが発生しない環境では、DELETE 文実行時の処理のみトランザクション ログが増加いたします。また、ここで実際にレコードが削除されますので、次回実行時のレコード数が少なくなります。
これに対し、デッドロックが発生いたしますと、この DELETE 文実行時の処理と デッドロック発生後の Rollback の処理の分だけトランザクション ログが増加いたします。また、Rollback 後レコード数が削除前の数に戻っているため、次回実行時のレコード数も多くなり、トランザクションログが急激に増大します。さらに、レコードが多くなるため、一度発生すると連続してデッドロックが発生しやすくなることも想定されます。
回避策:
パラレルデッドロックを防ぐため、Select 文をSQL Server内部で分割せずに実行することが有効となります。
以下のとおり、ストアド プロシージャを変更してください。
SQL Server Management Studio (SSMS) で対象の SQL Server インスタンスに接続します。
以下を右クリックし、[変更] を選択します。
[<サーバー名>]
-[データベース]
-[<データベース名>]
-[プログラミング]
-[ストアド プロシージャ]
-[rds.BrokerNotifications_Get_Timeout]以下の場所を見つけます。
1
2
3
4
5
6BEGIN
SELECT bn.Type, DATALENGTH(bn.Data) dataLen, bn.Data, CT.SYS_CHANGE_VERSION changeVersion
INTO #tmpBn
FROM BrokerNotification bn INNER JOIN
CHANGETABLE(CHANGES BrokerNotification, @LastSyncVersion) AS CT ON CT.Id = bn.Id
WHERE CT.SYS_CHANGE_OPERATION = 'I' AND CT.SYS_CHANGE_VERSION <= @latestSyncVersion;以下に変更 (「OPTION (MAXDOP 1)」の追加 )し、[実行]ボタンを押します。
1
2
3
4
5
6BEGIN
SELECT bn.Type, DATALENGTH(bn.Data) dataLen, bn.Data, CT.SYS_CHANGE_VERSION changeVersion
INTO #tmpBn
FROM BrokerNotification bn INNER JOIN
CHANGETABLE(CHANGES BrokerNotification, @LastSyncVersion) AS CT ON CT.Id = bn.Id
WHERE CT.SYS_CHANGE_OPERATION = 'I' AND CT.SYS_CHANGE_VERSION <= @latestSyncVersion OPTION (MAXDOP 1);