2012-08-10 114 views
5

我正在使用PL/SQL(Oracle 11g)更新EMPLOYEES表薪金列。使用FOR UPDATE語句

我用兩個獨立的腳本來做同樣的事情,即更新員工的工資。

一個腳本使用FOR UPDATE OF語句,因爲另一個腳本不使用它。在這兩種情況下,我發現oracle持有行級鎖,直到我們執行命令ROLLBACKCOMMIT命令。

那麼兩個腳本之間有什麼區別?

哪一個更好用?

這裏有兩個劇本我談論:

-- 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; 

我發現,甲骨文收購了在兩種情況下,行級鎖。那麼,使用FOR UPDATE OF有哪些好處,以及哪種編碼更好?

+2

不要忘記:如果員工== mrp然後設置工資+ = 100000 – stark 2012-08-10 03:17:30

回答

12

當您指定FOR UPDATE時,該行被鎖定在您的數據點SELECT處。如果沒有FOR UPDATE,該行將被鎖定在您行UPDATE的位置。在第二個腳本中,另一個會話可能會在執行SELECT的時間與您嘗試使用UPDATE的時間之間鎖定該行。

如果您正在處理返回相對較少的行和緊密的內部循環的SELECT語句,則兩者之間不可能有明顯差異。在SELECT上添加一個FOR UPDATE也使您有機會添加超時子句,前提是您不希望腳本無限制地阻塞,如果某個其他會話碰巧有一行您嘗試更新鎖定的行。

+0

FOR UPDATE腳本運行得更快,因爲它通過'WHERE CURRENT OF'子句中的'ROWID'有效地訪問更新? – Ollie 2012-08-10 08:52:46

+2

@Ollie - 可能。但'SELECT'必須在返回第一行之前訪問每一行來設置鎖定屬性,因此它將涉及第二次觸及每一行(儘管第二次打擊可能在緩存對象上)。我希望兩者能夠相互抵消。另外,如果目標是最大限度地提高速度,那麼您需要編寫一個'UPDATE'語句或至少PL/SQL批量操作,而不是逐行遊標'FOR'循環。 – 2012-08-10 14:45:04