oracle select for update

OraFige發表於2011-12-20
Normal 0 false false false EN-US ZH-CN X-NONE1.建立實驗表table_sfu,並初始化三條資料
sec@ora10g> create table table_sfu (a number);

Table created.

sec@ora10g> insert into table_sfu values (1);

1 row created.

sec@ora10g> insert into table_sfu values (2);

1 row created.

sec@ora10g> insert into table_sfu values (3);

1 row created.

sec@ora10g> commit;

Commit complete.

sec@ora10g> select * from table_sfu;

         A
----------
         1
         2
         3

2.使用Select For Update語句得到第一條資料
sec@ora10g> select * from table_sfu where a = 1 for update;

         A
----------
         1

3.檢視一下現在系統中的鎖定情 況,152會話(即上面語句所在的會話)獲得了一個TX鎖和一個TM鎖了,鎖定的表就是TABLE_SFU
sec@ora10g> @lock

lock        lock
holder    holder         lock             lock request       blocked
username  sessid SERIAL# type    id1  id2 mode    mode BLOCK  sessid
-------- ------- ------- ---- ------ ---- ---- ------- ----- -------
SEC          152   14985 TM    15396    0    3       0     0
SEC          152   14985 TX   327722 1790    6       0     0
             164       1 TS        3    1    3       0     0
             165       1 CF        0    0    2       0     0
             165       1 RS       25    1    2       0     0
             165       1 XR        4    0    1       0     0
             166       1 RT        1    0    6       0     0

7 rows selected.

sec@ora10g> col OWNER for a6
sec@ora10g> col OBJECT_NAME for a10
sec@ora10g> select OWNER,OBJECT_NAME,OBJECT_ID,OBJECT_TYPE from dba_objects where object_id = '15396';

OWNER  OBJECT_NAM  OBJECT_ID OBJECT_TYPE
------ ---------- ---------- -------------------
SEC    TABLE_SFU       15396 TABLE

4.另外新開啟一個session,執行以下修改任務
sec@ora10g> update table_sfu set a = 100 where a = 1;
OK,效果出現了,這裡出現了鎖等待現象,原因就是因為在第一個session中使用 Select For Update語句鎖定了第一行資料,不允許其他的session對它修改。

5.這時系統中鎖定情況如下,可 以看到第一個sessionsession id152)會話鎖定了第二個sessionsession id145)會話的事務
sec@ora10g> @lock

lock        lock
holder    holder         lock             lock request       blocked
username  sessid SERIAL# type    id1  id2 mode    mode BLOCK  sessid
-------- ------- ------- ---- ------ ---- ---- ------- ----- -------
SEC          145   11388 TM    15396    0    3       0     0
SEC          152   14985 TM    15396    0    3       0     0
SEC          152   14985 TX   327722 1790    6       0     1     145
             164       1 TS        3    1    3       0     0
             165       1 CF        0    0    2       0     0
             165       1 RS       25    1    2       0     0
             165       1 XR        4    0    1       0     0
             166       1 RT        1    0    6       0     0

8 rows selected.

6.因為僅僅是鎖定了第一條數 據,所以其他記錄可以順利的進行修改,如下
sec@ora10g> update table_sfu set a = 200 where a = 2;

1 row updated.

sec@ora10g> commit;

Commit complete.

7.解鎖方式:commit rollback後即完成鎖定的接觸

8. 反過來思考一下,如果Select For Update與要鎖定的行已經在其他session中完成了修改,再執行回出現什麼效果呢?這個很顯然,同樣的會出現鎖等待的現象,不過我想強調的 是,這裡可以使用nowaitwait選項來進行探測待鎖定行是否可被鎖定
實驗效果如下:
第一個session
sec@ora10g> update table_sfu set a = 100 where a = 1;

1 row updated.

第二個session
sec@ora10g> select * from table_sfu where a = 1 for update;
此處是鎖等待效果

sec@ora10g> select * from table_sfu where a = 1 for update nowait;
select * from table_sfu where a = 1 for update nowait
              *
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified
這裡提示了錯誤,原因就是已經探測到該行已經被別的事務鎖定,這裡無法對其進行鎖定操作。

sec@ora10g> select * from table_sfu where a = 1 for update wait 3;
select * from table_sfu where a = 1 for update wait 3
              *
ERROR at line 1:
ORA-30006: resource busy; acquire with WAIT timeout expired
這裡提示的錯誤內容與上面的一 樣,不過這裡wait 3表示,我等你三秒的時間,如果三秒過後還無法鎖定資源,就報錯。

9.更進一步,請參考Oracle官方文件中相關的描述
for_update_clause ::=
http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_10002.htm#i2126016
語法格式:
FOR UPDATE
[ OF [ [ schema. ]
       { table | view } . ]column
       [, [ [ schema. ]
            { table | view } . ]column
       ]...
]
[ NOWAIT | WAIT integer ]

同上述連線,搜尋關鍵字 “for_update_clause”可以得到每個選項的解釋資訊

Using the FOR UPDATE Clause: Examples
http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_10002.htm#i2130052

10.小結
上面的小實驗展示了一下 Select For Update行級鎖定的效果,Oracle的鎖定機制還是非常的靈活的,基於這個鎖定可以實現悲觀鎖定

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/26464953/viewspace-713614/,如需轉載,請註明出處,否則將追究法律責任。

相關文章