Dynamics CRM 2015 パフォーマンスの公開ドキュメント その 2

みなさん、こんにちは。

前回に引き続き、パフォーマンスに関する公開ドキュメントの紹介をします。
シリーズものとなっているため、まだ前回の記事を見られていない方はご覧ください。

Dynamics CRM 2015 パフォーマンスの公開ドキュメント その 1

Microsoft Dynamics CRM 2015 Performance and Scalability Documentation(英語):
https://www.microsoft.com/en-us/download/details.aspx?id=45905

データベースのトランザクション

Dynamics CRM のパフォーマンスを理解するうえで最も基本的な概念のひとつは、
データベースのトランザクションです。
これによりシステムへの要求とデータの一貫性が保たれています。

- Dynamics CRM は、同じデータベースのデータやリソースでやり取りされる
- データベースの分離レベルの制御により動作している
- データベースは、競合からデータを保護するためリソースをロックする
- ロックは、トランザクションがコミットまたは中止されるまで解放されない

SQL Server の既定の分離レベルは Read Committed です。
以降の記事ではこの既定の分離レベルの動作を記載しています。

トランザクションとロック

SQL Server は分離レベルに基づき適切なロックをかけます。
パフォーマンスの問題を引き起こす一般的な理由は、
トランザクションによる影響を理解しないままカスタマイズや開発が行われることです。

- 単一レコードを読み取る場合、そのレコードの読み取りロックがかかる
- 範囲を指定してレコードを読み取る場合、読み取る範囲によってその範囲、または
   テーブル全体の読み取りロックがかかる
- 単一レコードを作成、更新する場合、そのレコードに対する書き込みロックがかかる
- ロックがテーブルまたは特定のレコードに対して行われている場合、
   該当のレコードのインデックスに対してもロックがかけられている

例を用いて解説します。
取引先企業のレコードを更新する一連の処理は、1 つトランザクション内で実行されます。
その期間中に、別の非同期ワークフローが同じ取引先企業のレコードを更新しようとすると、
書き込みロックにより待たされます。

image

ポイントは、 以下の通りです。
- トランザクションはプラットフォームが保持している有効期間内で保持されている
- ロックの期間は、セッションやユーザーが操作が行われている期間ではない
- リクエストが完了するとデータベースの接続や関連するトランザクションやロックが解除される

ブロッキング

複数のユーザーが同じレコードを更新した場合、後から更新したユーザーは待たされます。

例えば、取引先担当者に自動採番している場合、複数の取引先担当者を作成すると、
複数のリクエストが同じ自動採番のリソースにアクセスする必要があります。
それにより 2 つ目以降のリクエストは、前のリクエストが完了するまで待たされます。
つまり、最終的には同時リクエスト数だけブロッキングが発生し、全体の処理時間が増加します。

以下の例の場合、最初の要求ではすぐに完了することができますが、
2 つ目以降の要求は前の要求の完了を待つ必要があります。

image

ロックのリリース

トランザクションが完了するまでロックが発生することは前述の通りですが、
ロックがリリースできない理由は 2 つです。

- データの一貫性を保つため
- エラーが発生した場合、トランザクション全体のロールバックを可能にするため

もし、トランザクション内の一部の変更が完了した場合でも、
トランザクション全体がコミットされるまでロックは保持される続けます。

以下の例の場合、カスタムエンティティのレコードを作成することで発生する
同期ワークフローやプラグイン処理は 1 つのトランザクション内で実行されます。
トランザクション全体が完了するまで該当のレコードに対する書き込みロックが発生しています。

image

エラーの発生頻度

断片的に発生するエラーは、同時リクエストによるブロッキングの症状の代表的なものです。
この場合、再度同じ処理を実行すると成功する場合があります。
こういった潜在的な競合が発生しているか、ブロッキング情報を確認する必要があります。
潜在的な競合は、個々の処理時間を短く最適化することで発生頻度を少なくすることができます。

トランザクションのコントロール

画面操作によるトランザクション

画面操作で発生するトランザクションと他処理への影響度は以下の通りです。

- フォーム:低 
   プラットフォームに該当のレコードを取得するリクエストを投げます。
   レコードに読み取りロックをかけます。
- 作成:低
   プラットフォームに該当のレコードを作成するリクエストを投げます。
- 更新:中
   プラットフォームに該当のレコードを更新するリクエストを投げます。
   完了するまで更新ロックをかけるため、他の更新や読み取りをブロックする場合あります。 
   テーブルの広い範囲を読み取りロックする場合があります。
- ビュー:高 
   他の操作に比べ範囲が広いため、他処理をブロックする可能性があります。
   意図的にクエリに Nolock ヒントを付与することで回避できます。 
   広範囲にわたるような重たいクエリは、データベースのリソースに影響を与え、
   タイムアウトを引き起こす可能性があります。

イベントパイプライン

SQL Server のトランザクションは、イベントパイプラインが開始されると作成されます。
これはプラットフォームによって実行されるすべてのデータベースのやりとりに
一貫性があることを保証します。カスタマイズにより、これらトランザクションに
参加することが可能です。

プラグインのトランザクション

プラグインのイベントやステージの種類により、その処理がトランザクションに含むかが異なります。

イベント

ステージ

番号

トランザクションが 存在していない場合

トランザクションが すでに存在している場合

Pre-Event

Pre-validation

10

データベースで独立したトランザクションを使用

既存のトランザクションに参加

Pre-Event

Pre-operation

20

既存のトランザクションに参加

既存のトランザクションに参加

Platform Core Operation

Main operation

30

既存のトランザクションに参加

既存のトランザクションに参加

Post-Event

Post-operation

40

既存のトランザクションに参加

既存のトランザクションに参加

Async

   

データベースで独立したトランザクションを使用

適用されない

 

トランザクションが存在していないとは、例えばユーザーが取引先企業を画面から作成した場合、
そのイベントによりトランザクションが生成されます。 取引先企業の作成で実行されるプラグインは、
このトランザクションに含められます。
一方トランザクションがすでに存在しているとは、取引先企業の作成時にステージ 40 の
イベントから電子メール活動を作成している場合、電子メール活動の作成で実行されるプラグインでは、
親イベントである取引先企業のトランザクションに含められることになります。

その他のトランザクション

外部から Web サービスを介してリクエストする場合、
パイプラインからトランザクションが発生し、応答が返されるとトランザクションは解放されます。
複数の要求を同じトランザクションで実行するには、実行コンテキストを維持する必要があります。
プラグインではこれが可能ですが、ExecuteMultiple で複数の処理を実行する場合、
それぞれ独立したトランザクションになります。Web サービスを利用して複数の要求を
同じトランザクションで実行する場合、ExecuteTransactionRequest で実行可能です。

並列処理の問題

複数の要求が同時に発生するケースを考えてみます。複数の要求が同時に発生する場合、
ロックや競合が発生する可能性が高くなります。以下は、Dynamics CRM で要求を発生させる
主な場所です。

- 画面操作による処理
   ユーザーが画面から操作することで発生する処理です。
- 非同期処理
   他のアクションの結果、非同期で発生する処理です。トリガされた時点では開始時間はわかりません。
- 一括処理(一括削除機能やサーバー側同期)
   Dynamics CRM 内部によるものや、画面や外部プログラムにより実行される一括処理です。

並列の非同期処理

よくある誤解は、非同期ワークフローまたはプラグインがキューから連続的に処理されるため、
これらの処理の間に矛盾はないというものです。Dynamics CRM は各非同期サービスインスタンスの
スループットを向上されるため、別のサーバーに展開されている非同期サービスインスタンス間で
非同期ジョブを並列処理します。

image

直列処理とタイムアウト

ブロッキングやタイムアウトは、直列化された処理の割合が高いです。
多くの並列処理は、ブロッキングにより直列化され長い処理となりタイムアウトが発生します。

image

連鎖される処理

直接実行した処理によって関連する一連のイベントが発生する可能性があることを
理解する必要があります。例えば以下の例の場合、取引先企業のレコードを作成する
トランザクションには、取引先企業のプラグイン処理、電子メール活動の作成処理、
電子メール活動のプラグインやワークフローの処理が含まれます。

image

プラットフォームの制約

タイムアウトやロックはプラットフォームの制約により発生している場合があります。
エラーの簡単な解決策は、プラットフォームの制約を緩和することですが、
これはシステム全体の可用性とパフォーマンスの根本的な解決策ではありません。
これらは固定し、処理を実行しているところで制約に違反しないよう対処する必要があります。

まとめ

次回は、こういったトランザクションの動作を考慮したうえで、
適切にトランザクションを利用するためのカスタマイズや設定変更の
パターンをご紹介します。

- プレミアフィールドエンジニアリング 河野 高也