Lock(二)解決Lock問題


本文介紹通過Toad、EM及SQL語句來處理數據庫產生的鎖。在這之前需要對v$lockv$session這兩個數據字典有一定的了解。

(一)使用Toad處理鎖

(1)使用Toad的session browser查看鎖情況

image

這里對每一個字段進行解釋:

欄位名稱 說明
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)
--exclusive(X,排它鎖。SQL操作有alter table、drop table、drop index、truncate table、lock exclusive等DDL操作)

Owner 被鎖定的對象的屬主
Object Type 被鎖定的對象類型
Object Name 被鎖定的對象名稱
Blocking 該session是否正在阻塞其他session對資源進行訪問。YES代表阻塞
Session Blocked 該會話是否正處於被阻塞的狀態,打勾代表該session正在被其他session阻塞
OS User 建立該session的用戶的OS名稱
Machine Name 建立該session的用戶的Machine名稱

 

(2)使用Toad解鎖

image

 

(二)使用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查看鎖情況,已經可以看到鎖的存在

image

 

(3)查看EM,從EM的top activity並不能看到鎖的情況

image

(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 ;

結果如圖:

image

 

由於執行了delete操作,將dept表也鎖了起來

image

 

(7)此時,再去觀察EM,可看到大量的Application阻塞。並且可以看到這個阻塞是有sid=54的session引起的

image

 

通過SQL ID查看具體執行的SQL語句

image

 

(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

至此鎖解除。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM