スケーラブル カスタマイズ設計: 自動付番の例
注意
この例では、スケーラブル カスタマイズ設計に関する一連のトピックをサポートします。 最初から始めるには、Microsoft Dataverse におけるスケーラブル カスタマイズ設計 を参照してください。
Dataverse でトランザクションが処理される方法について一般的な誤解を示すシナリオは、自動付番スキームを実装することです。
このシナリオでは、通常、次の要件があります:
- 特定のパターンに従って一意の番号を生成します。
- 関連するレコードの種類を生成するために多数の同時実行要求を許可します; 例えば一意な参照を必要とするアカウント。
- 一意な番号の連番を使用できます。
- 番号の生成に一貫性があり、スケーラブルで、ロード中にエラーが発生しないことを確認してください。 重複した番号が生成されないようにする必要があります。
- 関連するレコードの作成で番号を生成します。
一般的な方法には次の種類が含まれます:
- 自動付番インデックスのデータストアで最後に使用された番号を保存します; 例えばデータの種類ごとの行とユーザー定義エンティティ。
- 最後に使用された番号を取得し、その番号を増やします。
- 新しく作成されたレコードに対して新しい番号を記録します。
- 新しい番号を自動付番インデックス ストアで最後に使用された番号として保存します。
次のセクションでは Dataverse で取られるさまざまな方法を説明し、その影響を強調して、トランザクションの利用方法を理解する重要性と利点の両方を示します。
方法1: トランザクションの外へ
最も簡単な方法は、一般的に要求されるリソースを使用するとブロックされる可能性が生じることを認識することです。 これはスケーラビリティに影響を与えるため、自動付番を生成するときにプラットフォーム トランザクションを回避べきと決定する可能性があります。 検証前プラグインのパイプライン トランザクションの外側で自動付番を生成する方法を考えてみましょう。
これを個別に実行すると正常に動作します。 ただし、実際には同時実行エラーから保護しません。 下記の図が示すように、2 つの要求が両方とも並行して最新の数値を要求し、両方とも値を増加させ更新すると、数値が重複することになります。 取得した数に対してロックが保持されないため、競合状態が発生し両方のスレッドが同じ値になってしまう可能性があります。
多くの場合、複数の要求が発生していても、重複するウィンドウが限られているため、うまく機能する可能性がありますが、それは重複を防ぐための良い設計ではなく運に頼っています。
アプローチ 2: プラグイン トランザクション内で
トランザクション (txn) に登録されているプラグインから自動付番をする場合、これは確かにうまくいきます。
重複した要求が同時に番号を生成しようとするのと同じ状況では、両方の要求に自動付番テーブルに共有読み取りロックを付与することが可能です。 残念ながら、アプリケーションがこれを排他ロックにアップグレードしようとする時点では、別の共有読み取りロックが妨げるためこれは不可能です。
クエリが生成されている方法よって、正確な振る舞いが異なる可能性がありますが、それらの条件に頼り一意性が不可欠であるという結果が信頼できないのは理想的ではありません。 これにより障害が発生しないとしても、分離モードが正しくない場合は共有読み取り機能によって重複した番号が生成される可能性があります。 次の図が示すように、両方のレコードが自動付番で同じ値 8 になってしまいます。
アプローチ 3: プラグイン トランザクションの Pre-lock
トランザクションが機能する方法を理解することは、これを行う安全な方法を生み出せることにつながります。
このアプローチでは、純粋に一貫性を維持する目的で使用されるフィールド(たとえば UpdateInProgress)に対して、トランザクションの開始時から自動付番レコードでプレースホルダの更新が実行されます。 更新が開始されようとしていることを示す更新を書き込むことによってこれを行います。 次に、このプロセスは自動付番テーブルのその行に排他的書き込みロックを要求および実施して、他のプロセスが自動付番アプローチを開始するのをブロックします。
これにより他のプロセスが干渉することなく、更新された自動付番を安全に増分して書き戻すことができます。
手順が同じプラットフォーム トランザクションで発生するため、自動付番の更新だけでなくアカウント作成要求もシリアル化する影響があります。 アカウントの作成がクイック アクションならば、それは完全に良いアプローチである可能性があり、それはアカウントの作成と自動付番が一貫して実行されることを保証します; もし一方が失敗した場合は、両方とも失敗してロールバックします。
実際、トランザクションで他の処理が速い場合は、これがカスタマイズで自動付番を実装する最も一貫性があり効率的なアプローチです。
ただし、完了までの時間を伸ばす他の同期プラグインやワークフローを導入する場合、自動付番のプロセスがそれ自体をブロックするだけでなく他の活動の完了待機もブロックするため、シリアル化は現実にスケーラビリティの課題になります。
通常、自動付番の生成はイベント前プラグインで行われます。 作成ステップの入力パラメータに番号を含め、アカウントに対して生成された自動付番を記録する後処理で 2 回目の更新を回避します。
スケーラビリティの影響を念頭に、アカウント作成プロセスに他の複雑な処理がある場合、代替策は自動付番の生成を作成後プロセスに移動することで、これも一貫した更新プロセスを保証します。 その利点は、ロックがプロセスの終わりに向かってのみ行われるため、自動付番レコードのロックが保持されるトランザクションの時間を短縮することです。 自動付番のテーブルが最も競合の激しいリソースである場合、それにアクセスするすべてのプロセスに対してこのアプローチが取られれば全体の競合量が減少します。
ここでのトレードオフは、自動付番記録の待機をブロックしている全体の時間を減らす間に、アカウントに追加の更新を実行する必要があることです。
注意
ドキュメントの言語設定についてお聞かせください。 簡単な調査を行います。 (この調査は英語です)
この調査には約 7 分かかります。 個人データは収集されません (プライバシー ステートメント)。