ORACLE/ADMIN2007. 8. 14. 00:17
반응형

< 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
Posted by [PineTree]