異なるセッション内で Amazon Redshift の複数のオペレーションを同時に実行すると「ERROR: 1023 DETAIL: Serializable isolation violation on table in Redshift」というメッセージが表示されます。 どうすればこのエラーを解決できますか?
Amazon Redshift の同時書き込みオペレーションは、直列化可能でなければなりません。すなわち、トランザクションは、同時に実行された場合と同じ結果を出せる 1 つ以上の順序で、直列的に実行可能でなければなりません。詳細は直列化可能分離をご覧ください。
直列化可能分離のエラーを解消するには、次のいずれか 1 つまたは両方の方法を使用します。
- 原子性のために同じトランザクションに存在している必要がないオペレーションをトランザクションの外部に移動させる
- 各セッションですべてのテーブルをロックして強制的に直列化する
原子性のために同じトランザクションに存在している必要がないオペレーションをトランザクションの外部に移動させる
この方法は、2 つのトランザクション内にある各オペレーションが、他方のトランザクションの結果に影響を与え得る方法で相互参照している場合に適用されます。たとえば、2 つのセッションが個々にトランザクションを開始したとします。
Session1_Redshift = # BEGIN;
Session2_Redshift = # BEGIN;
各トランザクションの SELECT ステートメントの結果は、他方のトランザクションの INSERT ステートメントの影響を受ける可能性があります。任意の順序で直列に実行した場合、一方の SELECT ステートメントの結果は、並列で実行した場合よりも常に 1 行多く行を返します。オペレーションを並列に実行した場合と同じ結果が出る、直列に実行できる順序が存在しないため、実行した最後のオペレーションで直列化可能分離エラーが発生します。
Session1_redshift=# select * from tab1; Session1_redshift =# insert into tab2 values (1);
Session2_redshift =# insert into tab1 values (1); Session1_redshift =# select * from tab2;
SELECT ステートメントの結果が重要ではない (すなわち、トランザクション内のオペレーションの原子性が重要ではない) 場合は、以下の例に示すように SELECT ステートメントをトランザクションの外部に移動させます。
Session1_Redshift=# BEGIN; Session1_Redshift = # insert into tab1 values (1) Session1_Redshift = # END; Session1_Redshift # select * from tab2;
Session2_Redshift # select * from tab1; Session2_Redshift =# BEGIN; Session2_Redshift = # insert into tab2 values (1) Session2_Redshift = # END;
この例では、トランザクションの相互参照は行われていません。2 つの INSERT ステートメントには互いに影響し合っていません。オペレーションを並列に実行した場合と同じ結果が出る、直列に実行できる順序が 1 つ以上存在するので、このトランザクションは直列化可能です。
各セッションですべてのテーブルをロックして強制的に直列化する
LOCK コマンドが、直列化可能分離エラーが発生するオペレーションをブロックします。LOCK コマンドを使用するときは、必ず次の手順に従います。
- トランザクションの影響を受けるテーブルを、トランザクション内の読み取り専用の SELECT ステートメントの影響を受けるものも含め、すべてロックします。
- オペレーションの実行順序に関係なく、同じ順序でテーブルをロックします。
- オペレーションを実行する前に、トランザクションの開始時にすべてのテーブルをロックします。