本文介紹通過Toad、EM及SQL語句來處理數據庫產生的鎖。在這之前需要對v$lock和v$session這兩個數據字典有一定的了解。
(一)使用Toad處理鎖
(1)使用Toad的session browser查看鎖情況
這里對每一個字段進行解釋:
| 欄位名稱 | 說明 |
| SID | session ID,每一個session都會產生一個sid,用於標識會話 |
| User | 產生鎖的數據庫用戶 |
| Lock Type | 鎖的類型,常見的有: --DML鎖 --Transaction鎖(事物鎖)等 |
| Mode Held | session保持鎖的模式: --none --null(NULL) --row-S(SS,行級共享鎖。其它session只能查詢這些數據行。SQL操作有select for update、lock for update、lock row share) --row-X(SX,行級排它鎖。在提交前不允許做DML操作。SQL操作有insert、update、delete、lock row share) --share(S,共享鎖。SQL操作有create index,lock share) --S/Row-X(SSX,共享行級排它鎖。SQL操作有lock share row exclusive) |
| Owner | 被鎖定的對象的屬主 |
| Object Type | 被鎖定的對象類型 |
| Object Name | 被鎖定的對象名稱 |
| Blocking | 該session是否正在阻塞其他session對資源進行訪問。YES代表阻塞 |
| Session Blocked | 該會話是否正處於被阻塞的狀態,打勾代表該session正在被其他session阻塞 |
| OS User | 建立該session的用戶的OS名稱 |
| Machine Name | 建立該session的用戶的Machine名稱 |
(2)使用Toad解鎖
(二)使用SQL命令處理鎖
(1)查看鎖信息
select se.machine, se.sid, se.serial#, se.seconds_in_wait, se.paddr, lo.block from v$lock lo, v$session se where lo.sid = se.sid and lo.block > 0; --bloc>0代表這個會話阻塞了其他會話
(2)查看哪個數據庫對象被鎖
select lo.sid, do.owner, do.object_name from v$lock lo, dba_objects do where lo.id1 = do.object_id and lo.sid = 23; --這里23是例子,我們需要根據上一步得到的sid來查看具體對象
(3)Kill Session
alter system kill session 'sid,serial#'; --sid,serial從第1步中得到
(4)如果利用上面的命令殺死一個進程后,進程狀態被置為"killed",但是鎖定的資源很長時間沒有被釋放,那么可以在os一級再殺死相應的進程(線程),首先執行下面的語句獲得進程(線程)號:
select pr.spid, --我們要的 se.osuser, se.program from v$session se, v$process pr where se.paddr=pr.addr and se.sid=24 --sid從第1步得到
(5)在OS級別Kill Process
(5.1) 在unix上,用root身份執行命令:
su - root #kill -9 spid --即第步查詢出的spid
(5.2)在windows(unix也適用)用orakill殺死線程,orakill是oracle提供的一個可執行命令,語法為:
orakill sid thread
sid:表示要殺死的進程屬於的 實例名 ,與上面的session id不同
thread:是要殺掉的線程號,即第4步查詢出的spid
例:c:>orakill orcl 12345
(三)模擬鎖的產生及處理
(1)對scott.emp表進行行更新,但是不提交
SQL> select * from scott.emp; EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO ----- ---------- --------- ----- ----------- --------- --------- ------ 7369 SMITH CLERK 7902 1980/12/17 800.00 20 7499 ALLEN SALESMAN 7698 1981/2/20 1600.00 300.00 30 … … … 14 rows selected SQL> update scott.emp set job = 'SALESMAN' where empno = 7369; 1 row updated
(2)使用Toad查看鎖情況,已經可以看到鎖的存在
(3)查看EM,從EM的top activity並不能看到鎖的情況
(4)查看V$lock。V$lock記錄了當前數據庫中存在的全部鎖,鎖是Oracle的一種正常的機制,但從這個視圖並不能看出什么。對於用戶而言,最關心的是TM和TX鎖,結合上面Toad的結果,我們可以看到session id = 46的會話已經持續了454s。
SQL> select * from v$lock; ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK ---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ---------- ... ... 000000008D45B1C0 000000008D45B218 53 AE 100 0 4 0 436 0 00007F2A9960F420 00007F2A9960F480 46 TM 73201 0 3 0 454 0 000000008C105C90 000000008C105D08 46 TX 458781 1379 6 0 454 0
對於TM鎖(表級鎖),ID1代表的是被鎖定的object_id,ID2為0,通過dba_object可以查看到正在被鎖的對象的名稱。
SQL> select owner,object_name,object_id,object_type from dba_objects where object_id = 73201; OWNER OBJECT_NAME OBJECT_ID OBJECT_TYPE ------ ------------ ---------- ------------ SCOTT EMP 73201 TABLE
(5)再來查看v$session視圖,SECOND_IN_WAIT字段代表會話處於等待的時間。
SQL> select se.SADDR,se.SID,se.SERIAL#,se.PADDR,se.USERNAME,se.MACHINE,se.SECONDS_IN_WAIT from v$session se; SADDR SID SERIAL# PADDR USERNAME MACHINE SECONDS_IN_WAIT ---------------- ---------- ---------- ---------------- ------------------------------ --------------------------- --------------- 000000008DF74F68 46 13 000000008DC9F4D0 LIJIAMAN WORKGROUP\DESKTOP-TKAPD8E 1585 000000008DF720F8 47 235 000000008DCA0510 DBSNMP localhost.localdomain 11 ... ... ...
(6)在同一個session中執行delete操作,在新開的session中執行update操作。通過Toad,我們可以看到,在sid=46的session上,存在2個DML鎖,值得一提的是,在我們對表emp進行操作時,由於其外鍵在dept表上,也將dept表鎖住了。三個DML鎖都是SX鎖,即行級排它鎖,46上還有一個x鎖,即排它鎖。
SQL> delete from scott.emp where emp.empno = 7369; SQL> update scott.emp set emp.sal = sal + 200 where emp.empno = 7369 ;
結果如圖:
由於執行了delete操作,將dept表也鎖了起來
(7)此時,再去觀察EM,可看到大量的Application阻塞。並且可以看到這個阻塞是有sid=54的session引起的
通過SQL ID查看具體執行的SQL語句
(8)此時查看v$lock。從紅色部分可以看到, session46與session54對object id = 73201的對象產生了表級鎖競爭,並且目前session46正在占用該表,導致該session阻塞了session54。
SQL> select * from v$lock; ADDR KADDR SID TYPE ID1 ID2 LMODE REQUEST CTIME BLOCK ---------------- ---------------- ---------- ---- ---------- ---------- ---------- ---------- ---------- ---------- 00007F2A9960C378 00007F2A9960C3D8 54 TM 73201 0 3 0 1510 0 00007F2A9960C378 00007F2A9960C3D8 46 TM 73201 0 3 0 3707 0 00007F2A9960C378 00007F2A9960C3D8 46 TM 73199 0 3 0 1798 0 000000008C105C90 000000008C105D08 46 TX 458781 1379 6 0 3707 1
(9)Kill Session
SQL> alter system kill session '46,13'; System altered
至此鎖解除。








