翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。
Amazon QLDB 同時実行モデル
重要
サポート終了通知: 既存のお客様は、07/31/2025 のサポート終了QLDBまで Amazon を使用できます。詳細については、「Amazon Ledger QLDB を Amazon Aurora Postgre に移行するSQL
Amazon QLDB は、高性能なオンライントランザクション処理 (OLTP) ワークロードのニーズに対応することを目的としています。QLDB は SQLのようなクエリ機能をサポートし、完全なACIDトランザクションを提供します。さらに、QLDBデータ項目はドキュメントであり、スキーマの柔軟性と直感的なデータモデリングを提供します。ジャーナルを中核とする を使用すると、 QLDBを使用して、データへのすべての変更の完全で検証可能な履歴にアクセスし、必要に応じてコヒーレントトランザクションを他のデータサービスにストリーミングできます。
オプティミスティック同時実行制御
ではQLDB、同時実行制御はオプティミスティック同時実行制御 () を使用して実装されますOCC。OCC は、複数のトランザクションが相互に干渉することなく頻繁に完了できるという原則に基づいています。
を使用するとOCC、 のトランザクションはデータベースリソースのロックを取得QLDBせず、完全な直列化可能な分離で動作します。QLDB は、トランザクションが連続的に開始された場合と同じ効果が得られるように、同時トランザクションを連続的に実行します。
コミットする前に、各トランザクションは検証チェックを実行し、他のコミットされたトランザクションがアクセスしているデータを変更していないことを確認します。このチェックによって競合する変更、またはデータの変更の状態が明らかになった場合、トランザクションのコミットは拒否されます。ただし、トランザクションは再開できます。
トランザクションが に書き込むとQLDB、OCCモデルの検証チェックはQLDBそれ自体で実装されます。の検証フェーズで障害が発生したためにトランザクションをジャーナルに書き込めない場合OCC、 はアプリケーションレイヤーOccConflictException
に QLDBを返します。トランザクションの再責任はアプリケーションソフトウェアが負います。アプリケーションは、拒否されたトランザクションを中止し、最初からトランザクション全体を再試行する必要があります。
QLDB ドライバーがOCC競合やその他の一時的な例外を処理して再試行する方法については、「」を参照してくださいAmazon のドライバーを使用した再試行ポリシーについて QLDB。
インデックスを使用してテーブル全体のスキャンを回避する
ではQLDB、すべての PartiQL ステートメント (すべてのSELECT
クエリを含む) がトランザクションで処理され、トランザクションのタイムアウト制限 が適用されます。
ベストプラクティスとして、インデックス付きフィールドまたはドキュメント ID でフィルタリングする WHERE
述語句を使用してステートメントを実行することをお勧めします。QLDB では、インデックス付きフィールドで等価演算子を使用してドキュメントを効率的に検索する必要があります。例えば、 WHERE indexedField = 123
や などですWHERE indexedField IN (456, 789)
。
このインデックス付きルックアップがないと、 はドキュメントを読み取るときに完全なテーブルスキャンを実行QLDBする必要があります。これにより、クエリのレイテンシーやトランザクションのタイムアウトが発生する可能性があり、競合するトランザクションとのOCC競合の可能性も高くなります。
たとえば、VIN
フィールドにのみインデックスがある Vehicle
という名前のテーブルについて考えます。これには以下のデータが含まれています。
VIN | Make | モデル | 色 |
---|---|---|---|
"1N4AL11D75C109151" |
"Audi" |
"A5" |
"Silver" |
"KM8SRDHF6EU074761" |
"Tesla" |
"Model S" |
"Blue" |
"3HGGK5G53FM761765" |
"Ducati" |
"Monster 1200" |
"Yellow" |
"1HVBBAANXWH544237" |
"Ford" |
"F 150" |
"Black" |
"1C4RJFAG0FC625797" |
"Mercedes" |
"CLK 350" |
"White" |
2 人の同時ユーザー (Alice と Bob) が、台帳内の同じテーブルを使用しています。彼らは、次のように 2 つの異なるドキュメントを更新します。
Alice:
UPDATE Vehicle AS v
SET v.Color = 'Blue'
WHERE v.VIN = '1N4AL11D75C109151'
Bob:
UPDATE Vehicle AS v
SET v.Color = 'Red'
WHERE v.Make = 'Tesla' AND v.Model = 'Model S'
Alice と Bob が同時にトランザクションを開始するとします。Alice の UPDATE
ステートメントは VIN
フィールドに対してインデックス付きのルックアップを行うため、該当する 1 つのドキュメントのみを読み取る必要があります。Alice は終了し、最初にトランザクションを正常にコミットします。
Bob のステートメントは、インデックス付けされていないフィールドをフィルタリングするため、テーブルスキャンを実行し、OccConflictException
が発生します。これは、Alice のコミットされたトランザクションが Bob のステートメントがアクセスしているデータを変更したためです。これには、Bob が更新中のドキュメントだけでなく、テーブル内のすべてのドキュメントが含まれます。
挿入のOCC競合
OCC 競合には、以前に存在していたドキュメントだけでなく、新しく挿入されたドキュメントが含まれる場合があります。次の図では、2 人の同時ユーザー (Alice と Bob) が台帳内の同じテーブルを操作しているとします。彼らは両方とも、述語値がまだ存在しないという条件の下でのみ新しいドキュメントを挿入したいと考えています。
この例では、Alice と Bob の両方が 1 つのトランザクション内で次の SELECT
および INSERT
ステートメントを実行します。アプリケーションは、INSERT
ステートメントが結果を返さない場合にのみ、SELECT
ステートメントを実行します。
SELECT * FROM Vehicle v WHERE v.VIN = 'ABCDE12345EXAMPLE'
INSERT INTO Vehicle VALUE
{
'VIN' : 'ABCDE12345EXAMPLE',
'Type' : 'Wagon',
'Year' : 2019,
'Make' : 'Subaru',
'Model' : 'Outback',
'Color' : 'Gray'
}
Alice と Bob が同時にトランザクションを開始するとします。どちらの SELECT
クエリも、ABCDE12345EXAMPLE
の VIN
が付いた既存のドキュメントを返しません 。したがって、彼らのアプリケーションは INSERT
ステートメントを続行します。
Alice は終了し、最初にトランザクションを正常にコミットします。その後、Bob はトランザクションをコミットしようとしますが、QLDB拒否して をスローしますOccConflictException
。これは、Alice のコミットされたトランザクションが Bob のSELECT
クエリの結果セットを変更し、Bob のトランザクションをコミットする前にこの競合OCCを検出したためです。
このトランザクション例をべき等にするには SELECT
クエリが必要です。Bob は、最初からトランザクション全体を再試行することができます。しかし、彼の次の SELECT
クエリは、Alice が挿入したドキュメントを返すので、Bob のアプリケーションは INSERT
を実行しません。
トランザクションをべき等にする
前のセクションの insert トランザクションも、べき等トランザクションの例です。つまり、同じトランザクションを複数回実行すると、同じ結果が得られます。Bob が、特定の VIN
が既に存在しているかどうかを最初に確認せずに INSERT
を実行すると、テーブルには、重複した VIN
値を持つドキュメントが作成されることがあります。
OCC 競合に加えて、他の再試行シナリオを検討してください。例えば、 がサーバー側でトランザクションをQLDB正常にコミットしても、クライアントが応答を待っている間にタイムアウトする可能性があります。ベストプラクティスとして、同時実行または再試行の場合に予期しない結果を避けるために、書き込みトランザクションをべき等にしてください。
秘匿化のOCC競合
QLDB は、同じジャーナルブロック上のリビジョンの同時編集を防止します。2 人の同時接続ユーザー (Alice と Bob) が、台帳の同じブロックにコミットされている 2 つの異なるドキュメントのリビジョンを秘匿化したいという例を考えてみましょう。まず、Alice は次のように REDACT_REVISION
ストアドプロシージャを実行して、1 つのリビジョンの秘匿化をリクエストします。
EXEC REDACT_REVISION `{strandId:"JdxjkR9bSYB5jMHWcI464T", sequenceNo:17}`, '5PLf9SXwndd63lPaSIa0O6', 'ADR2Ll1fGsU4Jr4EqTdnQF'
次に、Alice のリクエストがまだ処理中である間に、Bob は次のように別のリビジョンの秘匿化をリクエストします。
EXEC REDACT_REVISION `{strandId:"JdxjkR9bSYB5jMHWcI464T", sequenceNo:17}`, '8F0TPCmdNQ6JTRpiLj2TmW', '05K8zpGYWynDlEOK5afDRc'
QLDB は、2 つの異なるドキュメントリビジョンを編集しようとしているOccConflictException
にもかかわらず、 による Bob のリクエストを拒否します。これは、Alice が秘匿化中のリビジョンと Bob のリビジョンが同じブロックにあるからです。Alice のリクエストの処理が完了すると、Bob は秘匿化リクエストを再試行できます。
同様に、2 つの同時トランザクションが同じリビジョンを秘匿化しようとした場合、処理できるリクエストは 1 つだけです。もう 1 つのリクエストは、リダクションが完了するまでOCC競合例外で失敗します。その後、同じリビジョンを秘匿化しようとすると、そのリビジョンが既に秘匿化されていることを示すエラーが発生します。
同時セッションの管理
リレーショナルデータベース管理システム (RDBMS) の使用経験がある場合は、同時接続の制限に慣れているかもしれません。QLDB トランザクションはHTTPリクエストメッセージとレスポンスメッセージで実行されるため、 には従来のRDBMS接続の概念が同じではありません。
ではQLDB、同様の概念はアクティブなセッション です。セッションは概念的にはユーザーログインに似ており、これによって、台帳に対するデータトランザクションリクエストの情報が管理されます。アクティブセッションとは、トランザクションがアクティブに実行されているセッションを意味します。トランザクションが終了したばかりで、サービスが別のトランザクションがすぐに開始されることを期待している状態もセッションと見なされることがあります。QLDB は、セッションごとに 1 つのアクティブに実行されているトランザクションをサポートします。
台帳ごとの同時アクティブセッションの制限数は、「Amazon のクォータと制限 QLDB」に定義されています。この制限に達すると、トランザクションの開始を試行するセッションはエラー (LimitExceededException
) になります。
セッションのライフサイクルと、データトランザクションの実行時にQLDBドライバーがセッションを処理する方法については、「」を参照してくださいドライバーによるセッション管理。QLDB ドライバーを使用してアプリケーションでセッションプールを設定するベストプラクティスについては、「Amazon QLDBドライバーの推奨事項 QldbDriver オブジェクトの設定」の「」を参照してください。