for update 與where current of的問題

在剛學oracle時一直不明白for update 的做用,今天考試又遇到鬱悶半天,因此加以整理。java

一:sql

1>首先for update是對錶的行進行鎖定。鎖定就比如咱們學java Thread那一章時,爲某個線程的run()枷鎖,當實例化出來多個線程時,它必須一個線程所有執行完後,釋放鎖其餘線程纔有機會運行。本文for update功能上同樣,就是爲一個select語句枷鎖,這樣在對這個表進行update ,delete時就會處於等待狀態,等待selec執行commit或rollback(至關於線程釋放鎖)後,才能夠對錶進行更改或刪除。數據庫

怎樣看效果呢?1:首先在「運行」-->cmd-->鏈接數據庫 執行select * from emp for updateoracle

    2 :而後在打開另外一個窗口(就至關於建立了兩個用戶):「運行」-->cmd-->鏈接數據庫  執行update emp set sal=100;你會發現它不執行了。spa

2>那馬for update與for update of 有神馬區別呢?線程

1.select * from Table1 for update 鎖定表的全部行,只能讀不能寫 code

  2  select * from Table1 where id = 1 for update 只鎖定id=1的行ip

  3  select * from Table1 a join Table2 b on a.id=b.id for update 鎖定兩個表的全部記錄資源

  4 select * from Table1 a join Table2 b on a.id=b.id where a.id = 10 for update 鎖定兩個表的中知足條件的行cmd

  5. select * from Table1 a join Table2 b on a.id=b.id where a.id = 10 for update of a.id 只鎖定Table1中知足條件的行

  for update 是把全部的表都鎖點 for update of 根據of 後表的條件鎖定相對應的表

3>關於oracle:select...for update of columns

按照1>步驟執行1:select * from emp for update of sal在另外一個窗口中執:2:update emp set job='clerk' where empno=10;按照2>的的思惟咱們可能認:「1」只鎖定了emp表的sal列,其實否則當運行「2」時,咱們發現它任然不執行,因此for update of columns 是鎖定的與sal相關的行。那麼for update 與for update of 有神嗎區別呢?區別在於多表鏈接時;

例如:

按照1>分別執行 select ename,dname from emp,dept where emp.deptno=dept.deptno for update;

另外一窗口執行:update dept set dname='haha'where deptno=10;咱們發現dept表不能更改

當咱們在 select ename,dname from emp,dept where emp.deptno=dept.deptno for update of sal;時

update dept set dname='haha'where deptno=10;能夠在執行了。

由此咱們能夠綜結出:for update of columns 用在多表鏈接鎖定時,能夠指定要鎖定的是哪幾張表,而若是表中的列沒有在for update of 後面出現的話,就意味着這張表其實並無被鎖定,其餘用戶是能夠對這些表的數據進行update操做的。這種狀況常常會出如今用戶對帶有鏈接查詢的視圖進行操做場景下。用戶只鎖定相關表的數據,其餘用戶仍然能夠對視圖中其餘原始表的數據來進行操做。

4>關於nowait與wait

SELECT ... FOR UPDATE [OF column_list][WAIT n|NOWAIT][SKIP LOCKED]; 
1:其中: 

  OF 子句用於指定即將更新的列,即鎖定行上的特定列。 

NOWAIT不進行等待,若是這條語句的鎖沒被釋放,則會直接報出:系統資源正忙
  WAIT 子句指定等待其餘用戶釋放鎖的秒數,防止無限期的等待。 
  「使用FOR UPDATE WAIT」子句的優勢以下: 
  1防止無限期地等待被鎖定的行; 
  2容許應用程序中對鎖的等待時間進行更多的控制。 
  3對於交互式應用程序很是有用,由於這些用戶不能等待不肯定 
  4 若使用了skip locked,則能夠越過鎖定的行,不會報告由wait n 引起的‘資源忙’異常報告 :

2:如今執行以下操做: 

在plsql develope中打開兩個sql窗口, 在1窗口中運行sql 
select * from t where a='1' for update; 
在2窗口中運行sql1 
1. select * from t where a='1'; 這一點問題也沒有,由於行級鎖不會影響純粹的select語句 
再運行sql2 
2. select * from t where a='1' for update; 則這一句sql在執行時,永遠處於等待狀態除非窗口1中sql 被提交或回滾。 
如何才能讓sql2不等待或等待指定的時間呢? 咱們再運行sql3 
3. select * from t where a='1' for update nowait; 則在執行此sql時,直接報資源忙的異常。 
若執行 select * from t where a='1' for update wait 6; 則在等待6秒後,報 資源忙的異常。 若是咱們執行 sql4 
4. select * from t where a='1' for update nowait skip Locked; 則執行sql時,即不等待,也不報資源 忙異常。 
如今咱們看看執行以下操做將會發生什麼呢? 
在窗口1中執行: 
select * from t where rownum<=3 nowait skip Locked; 
在窗口2中執行: 
select * from t where rownum<=6 nowait skip Locked; 
select for update 也就如此了吧,insert、update、delete操做默認加行級鎖,其原理和操做與select for update並沒有兩樣。 
select for update of,這個of子句在牽連到多個表時,具備較大做用,如不使用of指定鎖定的表的列,則全部表的相關行均被鎖定,若在of中指定了需修改的列,則只有與這些列相關的表的行纔會被鎖定.

二:

1:

若是你想刪除或者更新被Select For Update引用的記錄,你可使用Where Current Of語句

 

  1.  
    DECLARE
  2.  
    CURSOR CUR_NAME IS
  3.  
    SELECT * FROM EMP WHERE deptno=10 FOR UPDATE OF sal;
  4.  
    BEGIN
  5.  
    FOR REC IN CUR_NAME LOOP
  6.  
    UPDATE EMP SET sal =100 ;
  7.  
    END LOOP;
  8.  
    END;

上述pl/sql執行過以後咱們發現emp表中全部的sal列數據都被更改,此時咱們只想更改跟遊標對應的行,因此咱們又到where current of執行遊標遍歷時的當前行就好像for(int i=0;i++;i<10){}where current of與「i」的功能類似。因此當咱們想執行遊標影響的行時,上咱們能夠把上面pl/sql快改成:

 

    1.  
      DECLARE
    2.  
      CURSOR CUR_NAME IS
    3.  
      SELECT JOB FROM EMP WHERE deptno=10 FOR UPDATE OF sal;
    4.  
      BEGIN
    5.  
      FOR REC IN CUR_NAME LOOP
    6.  
      UPDATE EMP SET sal =100 WHERE CURRENT OF CUR_NAME;
    7.  
      END LOOP;
    8.  
      END;
相關文章
相關標籤/搜索