View a markdown version of this page

Aurora DSQL での外部キー制約の使用 - Amazon Aurora DSQL

Aurora DSQL での外部キー制約の使用

Aurora DSQL での外部キー制約により、アプリケーションの参照整合性ロジックをデータベースにプッシュできます。Aurora DSQL は、NO ACTION、RESTRICT、CASCADE、SET NULL、SET DEFAULT の各参照アクションをサポートしています。また、MATCH FULL および MATCH SIMPLE の一致タイプと、遅延可能な外部キー制約もサポートしています。構文の完全な内訳については、「外部キー制約」を参照してください。

Aurora DSQL が参照整合性を維持する方法

Aurora DSQL は、トランザクション実行時のスナップショット検証とコミット時の競合解決という 2 つのステップで参照整合性を維持します。2 つのステップを組み合わせることで、コミットされたトランザクションが外部キー制約に違反しないことが保証されます。

スナップショット検証。Aurora DSQL のすべてのトランザクションは、その開始時に取得されたデータベースの一貫したスナップショットに対して実行されます。参照する行を挿入または更新すると、Aurora DSQL はトランザクションの開始時のスナップショットで、参照されるテーブルを読み取り、参照されるキーが存在することを確認します。参照されるキーを削除または更新すると、Aurora DSQL はトランザクションのスナップショットで、参照するテーブルを読み取ります。参照する行が存在しないこと (RESTRICT の場合)、またはオペレーションによって孤立した行が残らないこと (NO ACTION の場合) を確認します。この検証はロックを取得する代わりにトランザクションの開始時のスナップショットから読み取るため、他のトランザクションは参照されるテーブルと参照するテーブルを並行して変更し続けることができます。

コミット時の解決。スナップショット検証により、制約はトランザクションの開始時に保持されることが保証されますが、開始からコミットまでの間は保証されません。同時実行トランザクションは、トランザクションの開始後に、参照される行を削除したり、競合する参照する行を挿入したりできます。これらの競合を判定するために、Aurora DSQL は参照される行に KEY SHARE 句を暗黙的に適用して、同時実行の変更によってスナップショットが無効になったかどうかを検出します。Aurora DSQL が競合を検出すると、トランザクションはシリアル化エラーで失敗します。KEY SHARE 句が同時実行トランザクションに与える影響の詳細については、「Aurora DSQL での同時実行制御」を参照してください。

参照整合性チェックで追加の読み取りが発生する

参照されるテーブルまたは参照するテーブルに対するすべてのデータ操作言語 (DML) オペレーションでは、参照整合性を保証するために追加の読み取りが発生します。テーブルに外部キー制約を追加する前に、ワークロードのベンチマークを行い、パフォーマンス特性が期待を満たしていることを検証してください。

シナリオ例

次のシナリオでは、orders テーブルの product_id 列に、products テーブルを参照する外部キー制約があります。これにより、products が参照されるテーブル、orders が参照するテーブルになります。

CREATE TABLE products ( product_id integer PRIMARY KEY, name text, price numeric ); CREATE TABLE orders ( order_id integer PRIMARY KEY, product_id integer REFERENCES products, quantity integer ); INSERT INTO products VALUES (1, 'Widget', 9.99);

競合: 削除と挿入の同時実行

このシナリオでは、あるセッションが参照される行を削除し、別のセッションが参照する行を挿入します。

-- Session A BEGIN; DELETE FROM products WHERE product_id = 1; -- Session B BEGIN; INSERT INTO orders VALUES (100, 1, 5); -- Session A COMMIT; -- succeeds -- Session B COMMIT; -- fails with serialization error ERROR: change conflicts with another transaction (OC000) (SQLSTATE 40001)

両方のセッションが同時に実行されます。Aurora DSQL はコミット時に競合を解決します。削除された製品を指す注文が残ることはありません。

競合なし: 非キー列の更新

このシナリオでは、あるセッションで参照される行の非キー列を更新し、別のセッションで参照する行を挿入します。

-- Session A BEGIN; UPDATE products SET name = 'Super Widget' WHERE product_id = 1; -- Session B BEGIN; INSERT INTO orders VALUES (101, 1, 3); -- Session A COMMIT; -- succeeds -- Session B COMMIT; -- succeeds

name (非キー列) を更新しても、product_id の外部キーとは競合しません。参照する行は、参照される行のキー列が変わらないことのみを気にします。

Aurora DSQL での外部キーのベストプラクティス

再試行ロジックを実装する

競合が発生すると、待機ではなくエラーが発生します。失敗したトランザクションを再試行するようにワークロードを設計してください。Aurora DSQL での同時実行の詳細については、「Aurora DSQL での同時実行制御」を参照してください。

頻繁に参照される行のキー列の変更を最小限に抑える

複数の参照する行が同じ行を参照し、そのキー列が頻繁に変化する場合は、スキーマの再構築を検討してください。頻繁に変化する値を非キー列に移動することで、参照される列を安定させます。参照されるテーブルの非キー列を変更しても、参照する側の挿入と競合することはありません。