當(dāng)程序?qū)λ龅男薷倪M(jìn)行提交(commit)或回滾后(rollback)后,鎖住的資源便會得到釋放,從而允許其它用戶進(jìn)行操作。
但是,有時,由于程序中的原因,鎖住資源后長時間未對其工作進(jìn)行提交;或是由于用戶的原因,如調(diào)出需要修改的數(shù)據(jù)后,未及時修改并提交,而是放置于一旁;或是由于客戶服務(wù)器方式中客戶端出現(xiàn)"死機",而服務(wù)器端卻并未檢測到,從而造成鎖定的資源未被及時釋放,影響到其它用戶的操作。
這時,我們需要迅速地診斷出鎖住資源的用戶并解決其鎖定。
1. 診斷系統(tǒng)中的鎖
為了找出系統(tǒng)中那些用戶鎖住資源以及那些用戶在等待相應(yīng)的資源,可使用以下語句(其中的/*+ NO_MERGE(..) */千萬不可省略, 否則會很慢):
-- looklock.sql
-- use the NO_MERGE hints can speed up the query
select /*+ NO_MERGE(a) NO_MERGE(b) NO_MERGE(c) */ 'Wait' "Status", a.username, a.machine, a.sid, a.serial#, a.last_call_et "Seconds", b.id1, c.sql_text "SQL"
from v$session a, v$lock b, v$sqltext c
where a.username is not null
and a.lockwait = b.kaddr
and c.hash_value =a.sql_hash_value
union
select /*+ NO_MERGE(a) NO_MERGE(b) NO_MERGE(c) */ 'Lock' "Status", a.username, a.machine, a.sid, a.serial#, a.last_call_et "Seconds", b.id1, c.sql_text "SQL"
from v$session a, v$lock b, v$sqltext c
where b.id1 in
(select /*+ NO_MERGE(d) NO_MERGE(e) */ distinct e.id1
from v$session d, v$lock e
where d.lockwait = e.kaddr)
and a.username is not null
and a.sid = b.sid
and b.request=0
and c.hash_value =a.sql_hash_value;
執(zhí)行后的結(jié)果如下所示:
Stat USERNAME MACHINE SID SERIAL# Seconds ID1
---- ------------------------------ ---------------- --------- --------- --------- ---------
SQL
----------------------------------------------------------------
Lock CIQUSR CIQ\DULMACER 12 966 245 131089
select * from c_trade_mode for update
Wait CIQUSR CIQ\DULMACER 10 735 111 131089
update c_trade_mode set x_name = 'zzz' where x_code='5'
Wait CIQUSR CIQ\DULMACER 15 106 1094 131089
select * from c_trade_mode for update
其中:
Status有兩種狀態(tài),LOCK表明該進(jìn)程鎖住了某個資源,WAIT表示該進(jìn)程正在等待某個資源。
Username, Machine分別為ORACLE用戶名及機器名
SID,SERIAL#可用于隨后的解鎖操作
Seconds表示該進(jìn)程最后一次進(jìn)行操作至當(dāng)前的時間(秒)
ID1, 鎖標(biāo)識。某個LOCK狀態(tài)的ID1與某個WAIT狀態(tài)的ID1相同,可說明鎖的正是另一個進(jìn)程等待的。
SQL: 鎖住資源的SQL語句
2. 解除鎖
診斷出鎖的狀態(tài)后,若發(fā)現(xiàn)該阻塞其它用戶進(jìn)程的進(jìn)程是正常操作中,則可通知該用戶對其進(jìn)行提交,從而達(dá)到釋放鎖資源的目的;若為非正常操作,即,其狀態(tài)為"inactive",且其Seconds已為較多長時間,則可執(zhí)行以下語句將該進(jìn)程進(jìn)行清除,系統(tǒng)會自動對其進(jìn)行回滾,從而釋放鎖住的資源。
alter system kill session 'sid, serial#';
例如: 對于上例中顯示的結(jié)果, 可用以下語句清除鎖住資源的進(jìn)程:
alter system kill session '12, 966';
關(guān)于你所說:在網(wǎng)絡(luò)斷掉(通過拔掉網(wǎng)線)或非正常終止進(jìn)程(通過task manager強行關(guān)閉sql*plus)時,oracle在有限的時間內(nèi)(我只觀查了5-10分)內(nèi),oracle未能對該進(jìn)程作任何處理。
這個處理與TCP協(xié)議有關(guān),因為SQL NET在使用TCP/IP協(xié)議進(jìn)行網(wǎng)絡(luò)連接時是一種短連接,當(dāng)ORACLE連接異常終止時,因為是異常終止,終止信號并沒有通過網(wǎng)絡(luò)通知server端,因此只有下次server有結(jié)果從服務(wù)器端返回需與client通信時,server才會發(fā)現(xiàn)此client已經(jīng)端掉。因此出現(xiàn)你前面所提ORACLE處理異常終止進(jìn)程延時情況.
死鎖:你可以試驗一條彼此存在依賴關(guān)系的update語句,ORACLE處理這種鎖時不是很好。
查鎖語句:查詢產(chǎn)生鎖的用戶鎖sql
select a.username username, a.sid sid, a.serial# serial,b.id1 id1, c.sql_text sqltext
from v$session a, v$lock b, v$sqltext c
where b.id1 in
(select distinct e.id1
from v$session d, v$lock e
where d.lockwait = e.kaddr)
and a.sid = b.sid
and c.hash_value = a.sql_hash_value
and b.request = 0;
死鎖:當(dāng)兩個事務(wù)需要一組有沖突的鎖,而不能將事務(wù)繼續(xù)下去的話,就 出現(xiàn)死鎖。
如事務(wù)1在表A行記錄#3中有一排它鎖,并等待事務(wù)2在表A中記錄#4 中排它鎖的釋放,而事務(wù)2在表A記錄行#4中有一排它鎖,并等待事務(wù) 1在表A中記錄#3中排它鎖的釋放,事務(wù)1與事務(wù)2彼此等待,因此就造 成了死鎖。死鎖一般是因拙劣的事務(wù)設(shè)計而產(chǎn)生
版權(quán)歸原作者和各發(fā)布網(wǎng)站所有,此文章僅供學(xué)習(xí)參考之用
天天學(xué)習(xí),好好向上——