異なるセッション内で Amazon Redshift の複数のオペレーションを同時に実行すると「ERROR: 1023 DETAIL: Serializable isolation violation on table in Redshift」(エラー: 1023 詳細: 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);
Session2_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 ステートメントの影響を受けるものも含め、すべてロックします。
- オペレーションの実行順序に関係なく、同じ順序でテーブルをロックします。
- オペレーションを実行する前に、トランザクションの開始時にすべてのテーブルをロックします。
同時実行トランザクションにはスナップショットの分離を使用する
SERIALIZABLE オプションは厳密な直列化を実装しており、結果が同時に実行されているトランザクションの直列順序にマッピングできない場合、トランザクションは失敗する可能性があります。
SNAPSHOT ISOLATION オプションで同時実行性を高めることができ、同じテーブル内で異なる行への同時変更が正常に行われます。
トランザクションはデータベースの最新のコミット済みのバージョン、つまりスナップショットで引き続き動作します。
スナップショットの分離は、CREATE DATABASE または ALTER DATABASE コマンドの ISOLATION LEVEL パラメータを使用してデータベース上で設定します。
データベースで使用している並行処理モデルを表示するには、次の STV_DB_ISOLATION_LEVEL クエリの例を実行します。
SELECT * FROM stv_db_isolation_level;
The database can then be altered to SNAPSHOT ISOLATION:
ALTER DATABASE sampledb ISOLATION LEVEL SNAPSHOT;
データベースの分離レベルを変更する場合は、次の点を考慮してください。
- データベースの分離レベルを変更するには、現在のデータベースのスーパーユーザー権限または CREATE DATABASE 権限が必要です。
- DEV データベース環境の分離レベルは変更することができません。
- トランザクションブロック内の分離レベルは変更できません。
- 他のユーザーがデータベースに接続している場合、alter isolation level コマンドは失敗します。
- alter isolation level コマンドを使用すると、現在のセッションの分離レベル設定を変更できます。
関連情報
同時書き込み操作を管理する