書き込みおよび読み取り/書き込みオペレーション
異なるタイプのコマンドを実行するタイミングと方法を決定することで、同時書き込み操作の特定の動作を管理できます。次のコマンドがこの話題に関連します。
-
COPY コマンド、(初回または増分) ロードを実行します
-
INSERT コマンド、1 つまたは複数の行を 1 回で追加します
-
UPDATE コマンド、既存の行を変更します
-
DELETE コマンド、行を削除します
COPY および INSERT オペレーションは純粋な書き込み操作です。また、DELETE および UPDATE は読み取り/書き込みオペレーションです。(行を削除または更新するには、最初に読み取りを行う必要があります。) 同時書き込み操作の結果は、同時に実行されている特定のコマンドに依存します。同じテーブルに対する COPY および INSERT 操作はロックが解除されるまで待機状態に置かれます。その後、通常どおり進められます。
UPDATE 操作と DELETE 操作は、書き込み前に初回テーブル読み込みに依存するため、動作が異なります。同時トランザクションが互いに表示されるとすれば、UPDATE と DELETE は最後のコミットからデータのスナップショットを読み取る必要があります。最初の UPDATE または DELETE がそのロックを解除するとき、2 つ目の UPDATE または DELETE はそれがこれから処理するデータが古くなっている可能性がないか決定する必要があります。最初のトランザクションでそのロックが解除されるまで 2 つ目のトランザクションでデータのスナップショットが取得されないため、データは古くなりません。
同時書き込みトランザクションの考えられるデッドロック状況
トランザクションに複数のテーブルの更新が関連するとき、両方が同じテーブルセットに書き込もうとすると、同時実行トランザクションにデッドロックが発生する可能性があります。コミットまたはロールバックするとき、トランザクションはそのすべてのテーブルロックを一度に解除します。1 つずつロックを解除することはありません。
例えば、T1 と T2 というトランザクションが大体同じ時間に開始します。T1 がテーブル A に書き込みを開始し、T2 がテーブル B に書き込みを開始する場合、両方のトランザクションは競合なく進行します。ただし、T1 がテーブル A への書き込みを終了し、テーブル B への書き込みを開始する必要がある場合、T2 が引き続き B をロックしているため、T1 は進行できません。反対に、T2 がテーブル B への書き込みを終了し、テーブル A への書き込みを開始する必要がある場合、T1 が引き続き A をロックしているため、T2 は進行できません。その書込操作がコミットされるまでいずれのトランザクションもそのロックを解除できないため、いずれのトランザクションも進行できません。
この種のデッドロックを回避するには、同時書き込み操作の日程を注意深く計画する必要があります。例えば、常にトランザクションと同じ順序でテーブルを更新する必要があります。ロックを指定する場合、DML 操作を実行する前に同じ順序でテーブルをロックします。