2012-08-10 3 views
5

テーブル給与列を更新するためにPL/SQL(Oracle 11g)を使用しています。FOR UPDATE文の使用

私は同じことをする、つまり従業員の給与を更新するために2つの別々のスクリプトを使用しました。

1つのスクリプトでは別のスクリプトとして使用していないFOR UPDATE OFステートメントを使用しています。どちらの場合も、私はROLLBACKまたはCOMMITコマンドを実行するまで、oracleに行レベルのロックが保持されていることがわかりました。

次に、2つのスクリプトの違いは何ですか?

どちらをお勧めしますか?ここで

は私が話しています2つのスクリプトです:

-- Script 1: Uses FOR UPDATE OF 

declare 
cursor cur_emp 
is 
select employee_id,department_id from employees where department_id = 90 for update of salary; 
begin 
    for rec in cur_emp 
    loop 
    update Employees 
    set salary = salary*10 
    where current of cur_emp; 
    end loop; 
end; 


--Script 2: Does the same thing like script 1 but FOR UPDATE OF is not used here 

declare 
cursor cur_emp 
is 
select employee_id,department_id from employees where department_id = 90; 
begin 
    for rec in cur_emp 
    loop 
    update Employees 
    set salary = salary*10 
    where Employee_ID = rec.employee_id; 
    end loop; 
end; 

私はOracleは両方のケースで、行レベルロックを取得していることが分かりました。では、FOR UPDATE OFを使用する利点は何ですか。そして、どちらがより良いコーディング方法ですか?

+2

従業員== mrpの場合salary + = 100000を設定 – stark

答えて

12

FOR UPDATEを指定すると、その行は、SELECTのデータがロックされた時点でロックされます。 FOR UPDATEがなければ、行はUPDATEの行にロックされます。 2番目のスクリプトでは、別のセッションでSELECTが実行された時刻とUPDATEに試行した時刻の間に行がロックされる可能性があります。

比較的少ない行とタイトな内側ループを返す文のSELECTを扱っている場合、2つの間に大きな違いがあるとは考えにくいです。また、にFOR UPDATEを追加すると、更新しようとしている行のいずれかがロックされている場合にスクリプトが無期限にブロックされないようにするには、タイムアウト句を追加することもできます。

+0

'WHERE CURRENT OF'節の' ROWID'を使って更新に効果的にアクセスしているので、 'FOR UPDATE'スクリプトは速く実行されませんか? – Ollie

+2

@Ollie - 可能です。しかし、 'SELECT'は全ての行にアクセスしてロック属性を設定してから最初の行を返さなければならないので、2番目のヒットはキャッシュされたオブジェクトになる可能性があります。私は2人がお互いに相殺することを期待している。さらに、速度を最大にすることが目的ならば、行ごとのカーソルの「FOR」ループではなく、単一のUPDATE文または少なくともPL/SQLの一括操作を記述します。 –