< oracle lock 걸린것 확인 하는 방법 >
select username un, osuser ou, s.sid sid , s.serial# ser, l.type ty,
decode(lmode,1,'NONE',2,'RS',3,'RX',4,'S',5,'RSX',6,'X') mh,
o.name ob, id1,
decode(request,1,'NONE',2,'RS',3,'RX',4,'S',5,'RSX',6,'X') mr
from v$lock l, v$session s, sys.obj$ o
where l.sid = s.sid
and l.id1 = o.obj#(+)
and username is not null
order by sid
************** 또 다른 방법 **************
oracle home/rdbms/admin/catblock.sql
utilblock.sql
===============================================================================================
* 다음 Query는 Lock과 관련된 transaction을 출력해준다.
column username format a10
column sid format 999
column lock_type format a15
column MODE_HELD format a11
column MODE_REQUESTED format a10
column LOCK_ID1 format a8
column LOCK_ID2 format a8
select a.sid,
decode(a.type,
'MR', 'Media Recovery',
'RT', 'Redo Thread',
'UN', 'User Name',
'TX', 'Transaction',
'TM', 'DML',
'UL', 'PL/SQL User Lock',
'DX', 'Distributed Xaction',
'CF', 'Control File',
'IS', 'Instance State',
'FS', 'File Set',
'IR', 'Instance Recovery',
'ST', 'Disk Space Transaction',
'IR', 'Instance Recovery',
'ST', 'Disk Space Transaction',
'TS', 'Temp Segment',
'IV', 'Library Cache Invalidation',
'LS', 'Log Start or Switch',
'RW', 'Row Wait',
'SQ', 'Sequence Number',
'TE', 'Extend Table',
'TT', 'Temp Table',
a.type) lock_type,
decode(a.lmode,
0, 'None', /* Mon Lock equivalent */
1, 'Null', /* N */
2, 'Row-S (SS)', /* L */
3, 'Row-X (SX)', /* R */
3, 'Row-X (SX)', /* R */
4, 'Share', /* S */
5, 'S/Row-X (SSX)', /* C */
6, 'Exclusive', /* X */
to_char(a.lmode)) mode_held,
decode(a.request,
0, 'None', /* Mon Lock equivalent */
1, 'Null', /* N */
2, 'Row-S (SS)', /* L */
3, 'Row-X (SX)', /* R */
4, 'Share', /* S */
5, 'S/Row-X (SSX)', /* C */
6, 'Exclusive', /* X */
to_char(a.request)) mode_requested,
to_char(a.id1) lock_id1, to_char(a.id2) lock_id2
from v$lock a
where (id1,id2) in
(select b.id1, b.id2 from v$lock b where b.id1=a.id1 and
b.id2=a.id2 and b.request>0);
( 위의 Query를 실행시키면 다음과 같은 내용이 출력된다.
SID LOCK_TYPE MODE_HELD MODE_REQUE LOCK_ID1 LOCK_ID2
--- --------------- ---------- ---------- -------- --------
5 Transaction Exclusive None 262172 90
6 Transaction None Exclusive 262172 90
9 Transaction None Exclusive 262172 90
SID 6과 9는 SID 5가 걸고 있는 Lock이 풀리기를 기다리고 있음을 알 수 있다.
* 다음 Query는 Lock과 관련된 테이블을 출력해 준다.
column username format a10
column lockwait format a10
column sql_text format a80
column object_owner format a14
column object format a15
select b.username username, c.sid sid, c.owner object_owner,
c.object object, b.lockwait, a.sql_text SQL
from v$sqltext a, v$session b, v$access c
where a.address=b.sql_address and
a.hash_value=b.sql_hash_value and
b.sid = c.sid and c.owner != 'SYS';
/
( 위의 Query를 실행하면 다음과 같은 결과가 출력된다.
USERNAME SID OBJECT_OWNER OBJECT LOCKWAIT
--------------- --- ------------- -------------- ----------
SQL
---------------------------------------------------------------
LTO2 6 LTO EMP C3D320F4
update lto.emp set empno =25 where empno=7788
LTO3 9 LTO EMP C3D320C8
delete from lto.emp where empno=7788
LTO 5 LTO DEPT
insert into lto.dept values (60,'PROGRAMMER','LOS ANGELOS')
여기서는 USERNAME에 나와있는 유저가 OBJECT에 나와있는 테이블을 수정하려고
함을 나타낸다. LT02,LT03는 LT0가 Commit,Rollback 하기를 기다리고 있음을 알
수 있다. 하지만 여기에는 가장 최근의 DML 명령 하나만 나와있기 때문에 여기
나온 명령이 반드시 Lock을 걸고 있는 명령이라고 단정지을 수는 없다.
관련된 프로세스
---------------
* 다음 Query를 실행해 보면 프로세스와 관련된 정보를 얻을 수 있다.
column "ORACLE USER" format a11
column SERIAL# format 9999999
column "OS USER" format a8
select substr(s.username,1,11) "ORACLE USER", p.pid "PROCESS ID",
s.sid "SESSION ID", s.serial#, osuser "OS USER",
p.spid "PROC SPID",s.process "SESS SPID", s.lockwait "LOCK WAIT"
from v$process p, v$session s, v$access a
where a.sid=s.sid and
p.addr=s.paddr and
s.username != 'SYS';
/
* 위의 Query를 실행하면 다음과 같은 결과가 출력된다.
ORACLE PROCESS SESSION SERIAL# OS USER PROC SESS LOCKWT
USER ID ID SPID SPID
------ ------- ------- ------- ------- ---- ---- ------
LTO 19 5 31 usupport 17312 17309
LTO2 25 6 43 usupport 17313 17310 C3D320F4
LTO3 26 9 1 usupport 17314 17311 C3D320D8
이 때는 다음과 같이 조치한다.
1. LTO에게 Commit,Rollback 할 것을 요구한다.
2. SQLDBA>ALTER SYSTEM KILL SESSION '5,31';
3. %kill -9 17309 (유닉스상의 Shadown Process)
stop/id=<SESS SPID> (PROC SPID=SESS SPID on vms running single task)
여기서 SYS 유저는 제외시켰는데 필요하다면 Query의 Where 조건에서
s.username != 'SYS' 부분을 삭제하면 된다.
CATBLOCK.SQL & UTLLOCKT.SQL
---------------------------
$ORACLE_HOME/rdbms/admin 디렉토리에 있는 스크립트 가운데 catblock.sql과
utlockt.sql을 사용하여서 Lock 상황을 쉽게 파악할 수 있다. 이들은 다음과
같이 실행한다.
%cd $ORACLE_HOME/rdbms/admin
%sqldba lmode=y (svrmgrl
SVRMGR>connect internal
SVRMGR>@catblock
결과는 다음 Query 문으로 알아 본다.
column waiting_session format a8
select lpad(' ',3*(level-1)) || waiting_session,
lock_type,
mode_requested,
mode_held,
lock_id1,
lock_id1,
lock_id2
from lock_holders
connect by prior waiting_session = holding_session
start with holding_session is null;
위의 Query에 의한 출력은 다음과 같다.
WAITING_ LOCK_TYPE MODE_REQUE MODE_HELD LOCK_ID1 LOCK_ID2
-------- ----------------- ---------- ---------- ---------- ----------
5 None
6 Transaction Exclusive Exclusive 262172 90
9 Transaction Exclusive Exclusive 262172 90
여기서 Session 6, Session 9가 Session 5를 기다리고 있음을 알 수 있다.
Lock & Hanging 문제를 추정하는 방법
-----------------------------------
프로그램 상에서 어느 부분이 Lock, Hanging 문제를 일으키는지 알아내기가
여의치 않을때 다음과 같은 방법을 사용해 보기 바란다.
1. init<SID>.ora의 sql_trace=ture로 세팅하면 연관된 SQL 명령이 출력될
것이다.
2. OS 상에서도 Process 상태를 점검하여 본다.
3. OS 상의 Debugging 기능을 사용하거나 만약 가능하다면 oradbx를 사용한다.
Platform 에 따라서 없을 수도 있다.
4. 여러가지 Monitoring 방법과 Locking/Blocking 스크립트를 이용한다.
PROCESS STACKS 확인
-------------------
때로는 Hanging Process나 리소스를 점유하고 있는 Process의 Process Stack을
점검해 보는 것이 문제 해결에 도움이 되는 경우가 있다.
1. OS Debugging 프로그램을 이용하여 Hangup 되기 전의 마지막 Call을 확인
한다.
ex)%truss -p <shadow pid>
2. oradbx(오라클 debugging 프로그램)은 Support,Development 시에만 사용
된다.
select substr(s.username,1,11) "ORACLE USER" ,
p.pid "PROCESS ID", s.sid "SESSION ID", s.serial#,
osuser "OS USER", p.spid "PROC SPID"
from v$session s, v$access a, v$process p
where a.sid=s.sid and
p.addr=s.paddr and
s.username != 'SYS';
/
위의 Query를 실행하면 다음과 같은 결과가 출력된다.
ORACLE PROCESS SESSION SERIAL# OS USER PROC SESS LOCKWT
USER ID ID SPID SPID
------ ------- ------- ------- ------- ---- ---- ------
LTO 19 5 31 usupport 17312 17309
LTO2 25 6 43 usupport 17313 17310 C3D320F4
LTO3 26 9 1 usupport 17314 17311 C3D320D8
만약 oradbx가 없다면 다음과 같이 해서 만들어 준다.
%cd $ORACLE_HOME/rdbms/lib
%make -f oracle.mk oradbx
LTO Process가 무엇을 하고 있는지 알고 싶으면 Process Stack을 보면 알수
있다.
ps -ef | grep 17312
usupport 17312 17309 0 Sep 15 ? 0:00 oracleV713(DESCRIPTION=(LOCAL=YE
type <oradbx>
debug 17312 (이 유저의 oracle shadow process)
dump stack
dump procstat
위에서 생성된 트레이스 화일(user_dump_dest 에 생성됨)을 이용하면 Hanging
문제를 해결하는데 큰 도움이 된다.
자주 발생하는 LOCK 문제들
-------------------------
1. Parent-Child 관계로 묶인 테이블에서 Child 테이블에 Index가 없는 상황
에서 Child 테이블을 수정하게 되면 Parent테이블에 TABLE LEVEL SHARE
LOCK이 걸리게 되어서 Parent 테이블에 대한 모든 Update가 금지된다.
2. 블럭의 PCTFREE가 매우 작다면 한 블럭에 여러개의 레코드가 들어 있기
때문에 한 블럭에 과도한 트랜잭션이 들어와서 블럭의 Transaction Layer가
Release 되기를 기다리게 되는 경우도 있다.
Ex)
create table test (a number) initrans 1 maxtrans 1;
SYSTEM: insert into test values (5); /* completed */
SCOTT: insert into SYSTEM.test values (10); /* Scott waits */
SID OWNER LOCK_TYPE MODE_HELD MODE_REQUE LOCK_ID1 LOCK_ID2
---- ----- ------------- ----------- ---------- -------- --------
7 System Transaction Exclusive None 196639 54
10 Scott Transaction None Share 196639 54
=======================================================================================
select sid, serial#,taddr,lockwait,그외기타정보컬럼 from v$session where
schemaname <> ''sys''
/
락이 걸리거나 의심되는 sid, serial#을
alter system kill session ''sid, serial#'';
해당명령으로 할당해제합니다.
다음내용참조하세요
1. v$session
주요 column
sid : session identifier
serial# : session serial number
username : 해당 session을 맺은 oracle username
lockwait : 대기중인 lock address
select sid, serial#, username, lockwait
from v$session ;
sid serial# username lockwait
------ --------- ----------- ----------
6 35 lto2 c2d2b3b4
8 70 system
12 15 lto
14 17 lto3 c2d2b438
15 30 sys
여기서 lockwait에 무언가가 기록 되어 있다면 해당 session은 특정
resource를 얻기 위해 대기중인 상태임
위의 예에서 lt02, lt03이 이에 해당함
2. v$lock
현재 system에 걸려 있는 lock들과 요구되어지는 lock들에 대한 정보
주요 column
sid : 해당 lock 또는 lock request의 소유 session
type : 현재 걸려있는 lock 또는 요구되는 lock의 type
주로 문제가 되고 관심을 가져야 하는 것은 tx type
(transaction)임
id1, id2 : 각 lock type별로 특수한 정보들이 기록됨
lock type이 tx일 경우 동일한 resource에 대한 lock을
요구하는 경우 각각의 id1, id2는 동일한 값을 갖는다.
lmode : 만약 해당 row가 걸려있는 lock에 대한 정보라면 lock mode가,
lock request에 대한 정보라면 none 이 들어 있음
request : 만약 해당 row가 걸려있는 lock에 대한 정보라면 none이,
lock request에 대한 정보라면 요구되는 lock mode가 들어 있음
* lock type, lock mode에 관한 자세한 내용은 ''oracle7 server concepts
manual'' chapter 10 data concurrency를 참조
select s.username, s.sid, s.serial#, l.type, l.id1, l.id2,
l.lmode, l.request
from v$session s, v$lock l
where s.sid = l.sid ;
username sid serial# type id1 id2 lmode request
--------- ---- -------- ----- ------- ------ ------- --------
lto2 6 35 tm 2294 0 rx none
lto2 6 35 tm 2295 0 rx none
lto2 6 35 tx 262167 87 none x
lto2 6 35 tx 327682 90 x none
lto 12 15 tm 2294 0 rx none
lto 12 15 tm 2295 0 rx none
lto 12 15 tx 262167 87 x none
lto3 14 17 tm 2294 0 rx none
lto3 14 17 tm 2295 0 rx none
lto3 14 17 tx 262167 87 none x
lto3 14 17 tx 196636 87 x none
* 다음 사용자들은 lock을 기다리고 있는 상태이다.
lto2 6 35 tx 262167 87 none x
lto3 4 17 tx 262167 87 none x
* 이들이 기다리고 있는 lock은 다음과 같다.
lto 12 15 tm 2294 0 rx none
lto 12 15 tm 2295 0 rx none
lto 12 15 tx 262167 87 x none
3. v$access
system에서 현재 lock이 걸려있는 object들과 이들을 access하고자 시도하는
session들에 대한 정보가 들어 있음
주요 column
sid : 현재 lock이 걸려있는 object를 access하고자 시도하는 session의 id
owner : lock이 걸려있는 object의 owner
object : lock이 걸려있는 object name
4. v$sqltext
주요 column들
address, hash_value : 특정 session이 수행하는 sql문을 확인하기 위해
v$session의 sql_address, sql_hash_value와 join한다.
sql_text : sql문
현재 sga영역에 존재하는 sql statement에 대한 정보가 들어있음
현재 특정 session이 수행하는 sql문을 조회하기 위해 다음 sql문을
이용한다.
select s.sid, s.serial#, s.username, a.sql_text
from v$sqltext a, v$session s
where s.sid = 11 and s.serial# = 9 -- session의 sid, serial#를 확인한
and a.address = s.sql_address -- 후 where조건에 기술
and a.hash_value = s.sql_hash_value ;
위에서 언급한 view들을 적절히 활용하여 문제의 lock을 걸고 있는 session을
찾아내어 alter system kill session ''sid, serial#'' ; 를 이용하여 해당
session을 kill시킨다.
시나리오 : lock이 걸린 table을 추측할 수 있을 경우
1. v$access 에서 해당 table에 lock을 잡고있는(요청하는) session
의 id를 확인
2. v$lock에서 위 1의 sid가 요청하는 resource를 잡고 있는 session을 확인
3. 필요하다면 v$sqltext를 보아서 실행중인 sql문을 확인
4. 위 2에서 확인된 session을 kill
'ORACLE > ADMIN' 카테고리의 다른 글
오라클 파라미터 관련 사이트 링크 (0) | 2007.12.13 |
---|---|
DATABASE LINK 사용법 (0) | 2007.12.07 |
ORACLE relink (0) | 2007.08.07 |
Oradebug Command (0) | 2007.08.04 |
10g SYSAUX tablespace 줄이기 (0) | 2007.08.02 |