Posted on 2010-03-17 23:42
Prayer 閱讀(313)
評(píng)論(0) 編輯 收藏 引用 所屬分類:
數(shù)據(jù)庫(kù),SQL
Oracle的Select For Update語(yǔ)句可以實(shí)現(xiàn)在讀取數(shù)據(jù)后馬上鎖定相關(guān)資源,防止被其他session修改數(shù)據(jù)的目的。也就是我們常常談到的“悲觀鎖定”(現(xiàn)實(shí)應(yīng)用開(kāi)發(fā)中,使用悲觀鎖定的情況少之又少,也許是因?yàn)闃?lè)觀鎖定的實(shí)現(xiàn)更加靈活和便捷的緣故)。這個(gè)小文兒做一個(gè)小小的實(shí)驗(yàn),來(lái)看看Select For Update語(yǔ)句實(shí)現(xiàn)的行級(jí)鎖定1.創(chuàng)建實(shí)驗(yàn)表table_sfu,并初始化三條數(shù)據(jù)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 32.使用Select For Update語(yǔ)句得到第一條數(shù)據(jù)sec@ora10g> select * from table_sfu where a = 1 for update; A---------- 13.查看一下現(xiàn)在系統(tǒng)中的鎖定情況,152會(huì)話(即上面語(yǔ)句所在的會(huì)話)獲得了一個(gè)TX鎖和一個(gè)TM鎖了,鎖定的表就是TABLE_SFUsec@ora10g> @locklock lockholder holder lock lock request blockedusername sessid SERIAL# type id1 id2 mode mode BLOCK sessid-------- ------- ------- ---- ------ ---- ---- ------- ----- -------SEC 152 14985 TM 15396 0 3 0 0SEC 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 07 rows selected.sec@ora10g> col OWNER for a6sec@ora10g> col OBJECT_NAME for a10sec@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 TABLE4.另外新打開(kāi)一個(gè)session,執(zhí)行以下修改任務(wù)sec@ora10g> update table_sfu set a = 100 where a = 1;OK,效果出現(xiàn)了,這里出現(xiàn)了“鎖等待”現(xiàn)象,原因就是因?yàn)樵诘谝粋€(gè)session中使用Select For Update語(yǔ)句鎖定了第一行數(shù)據(jù),不允許其他的session對(duì)它修改。5.這時(shí)系統(tǒng)中鎖定情況如下,可以看到第一個(gè)session(session id是152)會(huì)話鎖定了第二個(gè)session(session id是145)會(huì)話的事務(wù)sec@ora10g> @locklock lockholder holder lock lock request blockedusername sessid SERIAL# type id1 id2 mode mode BLOCK sessid-------- ------- ------- ---- ------ ---- ---- ------- ----- -------SEC 145 11388 TM 15396 0 3 0 0SEC 152 14985 TM 15396 0 3 0 0SEC 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 08 rows selected.6.因?yàn)閮H僅是鎖定了第一條數(shù)據(jù),所以其他記錄可以順利的進(jìn)行修改,如下sec@ora10g> update table_sfu set a = 200 where a = 2;1 row updated.sec@ora10g> commit;Commit complete.7.解鎖方式:commit或rollback后即完成鎖定的接觸8.反過(guò)來(lái)思考一下,如果Select For Update與要鎖定的行已經(jīng)在其他session中完成了修改,再執(zhí)行回出現(xiàn)什么效果呢?這個(gè)很顯然,同樣的會(huì)出現(xiàn)“鎖等待”的現(xiàn)象,不過(guò)我想強(qiáng)調(diào)的是,這里可以使用nowait和wait選項(xiàng)來(lái)進(jìn)行“探測(cè)”待鎖定行是否可被鎖定實(shí)驗(yàn)效果如下:第一個(gè)session:sec@ora10g> update table_sfu set a = 100 where a = 1;1 row updated.第二個(gè)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這里提示了錯(cuò)誤,原因就是已經(jīng)“探測(cè)”到該行已經(jīng)被別的事務(wù)鎖定,這里無(wú)法對(duì)其進(jìn)行鎖定操作。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這里提示的錯(cuò)誤內(nèi)容與上面的一樣,不過(guò)這里wait 3表示,我等你三秒的時(shí)間,如果三秒過(guò)后還無(wú)法鎖定資源,就報(bào)錯(cuò)。9.更進(jìn)一步,請(qǐng)參考Oracle官方文檔中相關(guān)的描述《for_update_clause ::=》http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_10002.htm#i2126016語(yǔ)法格式:FOR UPDATE[ OF [ [ schema. ] { table | view } . ]column [, [ [ schema. ] { table | view } . ]column ]...][ NOWAIT | WAIT integer ]同上述連接,搜索關(guān)鍵字“for_update_clause”可以得到每個(gè)選項(xiàng)的解釋信息《Using the FOR UPDATE Clause: Examples 》http://download.oracle.com/docs/cd/B19306_01/server.102/b14200/statements_10002.htm#i213005210.小結(jié)上面的小實(shí)驗(yàn)展示了一下Select For Update行級(jí)鎖定的效果,Oracle的鎖定機(jī)制還是非常的靈活的,基于這個(gè)鎖定可以實(shí)現(xiàn)“悲觀鎖定”。