where句と一致せず、コミットしないため、Oracleで「0行が更新されました」という更新ステートメントを実行すると、テーブルのどの部分でもロックが保持されますか? 私の推測ではノーですが、それを証明することはできません。
3 に答える
何も更新されなかった更新の後、行ロックは保持されません (結局のところ、行がない場合、どの行をロックする必要がありますか?)
トランザクションには (テーブルに対する) 共有ロックがまだいくつかありますが、それらは他のトランザクションがテーブルを変更するのを防ぐためだけのものです。これは基本的に、select ステートメントがテーブルで取得するのと同じ種類の「ロック」です。
行は、ライターによって変更された場合にのみロックされます。
TX ロックとも呼ばれる行ロックは、テーブルの単一行に対するロックです。トランザクションは、変更された行ごとに行ロックを取得します
したがって、行が変更されない場合、ロックはありません。
ロックを保持しません。
単純なテスト ケース
- 2 つの Oracle セッションを開きます (sqlplus または sqldeveloper またはその他の方法で)。
- update table1 where 句 (セッション 1)
- update table1 where 節 (セッション 2)
- session1 からコミットします (テーブル ロックがある場合、これはハングするはずです)。
- commit from session2 (テーブル ロックがある場合、このステートメントはデッドロックを引き起こします)
条件は、行ロック (存在する場合は両方のセッションが同じ行を削除する) と同じです。
文書化されているように:
INSERT、UPDATE、DELETE、および SELECT ... FOR UPDATE ステートメントのロック特性は次のとおりです。
DML ステートメントを含むトランザクションは、ステートメントによって変更された行に対して排他的な行ロックを取得します。ロックしているトランザクションがコミットまたはロールバックされるまで、他のトランザクションはロックされた行を更新または削除できません。
DML ステートメントを含むトランザクションは、サブクエリまたは暗黙的なクエリ (WHERE 句内のクエリなど) によって選択された行に対して行ロックを取得する必要はありません。DML ステートメント内のサブクエリまたは暗黙的なクエリは、クエリの開始時点で一貫性があることが保証されており、それが含まれている DML ステートメントの影響は見られません。
トランザクション内のクエリは、同じトランザクション内の以前の DML ステートメントによって行われた変更を確認できますが、それ自体のトランザクションの後に開始された他のトランザクションの変更を確認することはできません。
必要な排他的な行ロックに加えて、DML ステートメントを含むトランザクションは、影響を受ける行を含むテーブルに対して少なくとも行の排他的なテーブル ロックを取得します。含まれているトランザクションが、そのテーブルの共有、共有行の排他的、または排他的なテーブル ロックを既に保持している場合、行の排他的なテーブル ロックは取得されません。包含トランザクションがすでに行共有表ロックを保持している場合、Oracle Databaseはこのロックを行排他表ロックに自動的に変換します。
更新の進行中にテーブルを変更から保護するには、テーブル ロックが必要です。更新によって行が変更されない場合は、これが適用される唯一のロックです。
ステートメントがその行に変更をもたらさない行に対して更新を実行した場合 (たとえば、date_of_birth が既に null である行に対して SET DATE_OF_BIRTH = NULL を実行した場合)、行ロックは引き続き行われます。