直列化可能な分離エラーのトラブルシューティング - Amazon Redshift

Amazon Redshift は、2025 年 11 月 1 日以降、新しい Python UDF の作成をサポートしなくなります。Python UDF を使用する場合は、その日付より前に UDF を作成してください。既存の Python UDF は引き続き通常どおり機能します。詳細については、ブログ記事を参照してください。

直列化可能な分離エラーのトラブルシューティング

エラー: 1023 詳細: Redshift テーブルで直列化可能分離に関する違反が発生しました

Amazon Redshift で直列化可能な分離エラーが検出されると、次のようなエラーメッセージが表示されます。

ERROR:1023 DETAIL: Serializable isolation violation on table in Redshift

直列化可能な分離エラーに対処するには、次の方法をお試しください。

  • キャンセルされたトランザクションを再試行します。

    Amazon Redshift は、同時ワークロードがシリアル化できないことを検出しました。これは、アプリケーションのロジックにギャップがあることを示唆しています。通常、エラーが発生したトランザクションを再試行することで回避できます。問題が解決しない場合は、他のいずれかの方法をお試しください。

  • 同じアトミックトランザクション内にある不要なオペレーションは、トランザクション外に移動します。

    この方法は、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 ステートメントの影響を受けるテーブルなど、トランザクションの影響を受けるすべてのテーブルをロックします。

    • オペレーションが実行される順序に関係なく、テーブルを同じ順序でロックします。

    • オペレーションを実行する前に、トランザクションの開始時にすべてのテーブルをロックします。

  • 同時実行トランザクションにはスナップショット分離を使用します。

    スナップショット分離で ALTER DATABASE コマンドを使用します。ALTER DATABASE の SNAPSHOT パラメータの詳細については、「パラメータ」を参照してください。

エラー: 1018 詳細: リレーションが存在しません

Amazon Redshift オペレーションの同時実行を異なるセッションで行うと、次のようなエラーメッセージが表示されます。

ERROR: 1018 DETAIL: Relation does not exist.

Amazon Redshift のトランザクションは、スナップショットの分離に従います。トランザクションが開始されると、Amazon Redshift はデータベースのスナップショットを作成します。トランザクションのライフサイクル全体で、トランザクションはスナップショットに反映されているデータベースの状態で動作します。トランザクションがスナップショットに存在しないテーブルから読み込む場合、前に示した 1018 エラーメッセージをスローします。トランザクションがスナップショットを取得した後に別の並行トランザクションがテーブルを作成した場合でも、トランザクションは新しく作成されたテーブルから読み込むことができません。

このシリアル化分離エラーに対処するには、テーブルが存在することがわかっている時点にトランザクションの開始を移動してみてください。

テーブルが別のトランザクションによって作成された場合、この時点は、少なくともそのトランザクションがコミットされた後です。また、テーブルを削除した可能性のある同時トランザクションがコミットされていないことを確認します。

session1 = # BEGIN; session1 = # DROP TABLE A; session1 = # COMMIT;
session2 = # BEGIN;
session3 = # BEGIN; session3 = # CREATE TABLE A (id INT); session3 = # COMMIT;
session2 = # SELECT * FROM A;

そのため、session2 によって読み込みオペレーションとして最後に実行されるオペレーションは、直列化可能な分離エラーになります。このエラーは、session2 がスナップショットを取得し、コミットされた session1 によってテーブルがすでに削除されている場合に発生します。別の表現をすると、同時実行の session3 がテーブルを作成しても、それがスナップショット内にないため、session2 はそのテーブルを認識しません。

このエラーを解決するには、次のようにセッションを並べ替えます。

session1 = # BEGIN; session1 = # DROP TABLE A; session1 = # COMMIT;
session3 = # BEGIN; session3 = # CREATE TABLE A (id INT); session3 = # COMMIT;
session2 = # BEGIN; session2 = # SELECT * FROM A;

session2 がスナップショットを取得するときに、session3 はすでにコミットされており、テーブルはデータベースにあります。Session2 は、エラーなしでテーブルから読み込むことができます。