2012-03-04 21 views
7

Oracle SQLの更新文では、更新が5行に影響すると仮定すると、update文は5行すべてを同時にまたは順次更新しますか?例えば。 (1-5一斉)上記の文において Oracle SQLの更新文では、行の更新は同時に行われますか?

UPDATE table1 
set column2 = 'completed' WHERE 
index between 1 AND 5 

は、5の指数1は、シーケンス内すなわち1、2、3、4を5に更新されることになる、またはそれは同時に起こります。

私はOracle documentationを参照しましたが、これについては何も言及されていないようです。

+0

論理的に、彼らは同時に発生します。実際には、彼らはしませんが、あなたは違いを見つけることができなくなります。あなたが 'UPDATE Table1 SET Index = Index + 1 WHERE Index BETWEEN 1 AND 5'を実行すると、もっと面白くなります。 –

答えて

4

UPDATEステートメントが実行された後、ステートメントの効果は残りのトランザクション(およびコミットした場合、他のトランザクション)に表示されます。オラクルが実際にどのような順序で実行するかは、の実装の詳細です(同様に、ORDER BYを指定する場合はを指定しない限り、SELECT結果の順序は保証されません)。


ほとんどの場合、この順序はクライアントには関係ありません。重複する行のセットを更新している別のトランザクションでデッドロックを回避する場合があります。 UPDATEは、トランザクションが終了するまで更新される行をロックします。したがって、2つのトランザクションが同じ行をロックしようとしたときに異なる順序でロックしようとすると、デッドロックが発生する可能性があります。

デッドロックを回避する標準的な方法は、常に明確な順序でロックすることです。残念ながら、UPDATEは、ORDER BY句を持っていませんが、あなたはこれを行うことができます。conditionは両方のステートメントでも同じです

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
SELECT ... WHERE condition ORDER BY ... FOR UPDATE; 
UPDATE ... WHERE condition; 
COMMIT; 

を。 WHEREが常に両方のステートメントの同じ行セットを参照するには、直列化可能な分離レベルが必要です。

あるいは、PL/SQLであなたはこのような何か行うことができます:

DECLARE 
    CURSOR CUR IS SELECT * FROM YOUR_TABLE WHERE condition ORDER BY ... FOR UPDATE; 
BEGIN 
    FOR LOCKED_ROW IN CUR LOOP 
     UPDATE YOUR_TABLE SET ... WHERE CURRENT OF CUR; 
    END LOOP; 
END; 
/
2

あなたが提供したリンクが実際にこれをカバーしています。 Oracleは常に文レベルの読取り一貫性を強制します。つまり、table1の問合せで更新されたレコードが戻されることはありません。これは、すべてまたは何もなく、分離レベルにかかわらずです。

+0

ありがとうございます。さらに明確にするために、インデックス4が読み取りロックを持っていると仮定すると、更新ステートメントは5つの行すべてを更新するために読み取りロックが解除されるのを待ちますか? – Ted

+0

@Ted:Oracleでは、読者と作家はお互いをブロックしません。データが更新されると、古いデータはしばらくの間(UNDO)自動的に保存されます。これにより、何らかの変化があっても、クエリが特定の時点でデータを読み取ることができます。 –

+0

@jonearlesはい、しかしライター** do **は(同じ行に書き込んでいるときに)お互いをブロックします。ライターは行単位でロックします。つまり、すべてのトランザクションで同じ順序で書き込みが行われないと、デッドロックが発生する可能性があります。 UPDATEにはORDER BY句がないため、ロック順序を保証するために、別々の 'SELECT ... ORDER BY ... FOR UPDATE'を使用する必要があります。 –

4

いずれかです。

この場合、5行しか更新していないため、パラレルDMLが適切である可能性は非常に低いです。 UPDATEがパラレルDMLを起動しないと仮定すると、行の更新順序は任意ですが、行は順次更新されます。 INDEX 1が最初に更新されるか、最後に更新されるか、または中央で更新される可能性があります。クエリプランによって異なります。

2

UPDATE、DELETEおよびINSERTには定義済みの注文がありません。概念的には、それらはセットに適用され、一度にすべて実行されます。実際に言えば、あなたが観察する可能性のあるシーケンスはどれも頼りにしてはいけません。変化する可能性のある実装の詳細です。実際の世界が理論のなかにあるためにのみ起こります。

+0

ありがとう!私は更新がセットベースで行われていると推測します。つまり、更新は更新ステートメントを実行する前にすべての行が利用可能になるのを待つでしょうか? – Ted

+0

@Ted:Oracleはブロック・レベルのロックを行いますが、更新の開始時にはすべての行をロック解除する必要はありません。 – jmoreno

0

すべてのレコードが1つのトランザクションで1つのレコードとして更新されます。オラクル社は、更新シーケンスでの順序を保証しません。

テーブルのdbms_transaction.local_transaction_idの値で任意のフィールドを更新して、チェックすることができます。

関連する問題