Oracle 데이터베이스 에서 잠 금 대기 방법 을 빠르게 찾 습 니 다.

일반적으로 대형 데이터베이스 시스템 에서 데이터 의 일치 성 을 확보 하기 위해 데이터베이스 에 있 는 데 이 터 를 조작 할 때 시스템 은 데이터 에 해당 하 는 잠 금 을 한다.
이 잠 금 에는'읽 기 전용 잠 금','열 잠 금','열 잠 금 공유'등 다양한 유형 이 있 으 며,유형 마다'줄 잠 금'(한 번 에 하나의 기록 을 잠 그 는 것),'페이지 잠 금'(한 번 에 한 페이지 를 잠 그 는 것,즉 데이터베이스 에 기록 되 어 있 는 최소 할당 가능 한 단원),'표 잠 금'(전체 표를 잠 그 는 것)이 있다.'줄 급 잠 금'이 라면 잠 겨 있 는 이 줄 을 제외 하고 이 표 의 다른 줄 은 다른 사용자 에 의 해 수정(업데이트)되 거나 삭제(delete)작업 을 할 수 있 습 니 다.'표 급 잠 금'이 라면 모든 사용 자 는 이 표 에 대해 조회(select)작업 을 할 수 있 을 뿐 그 어떠한 기록 도 수정 하거나 삭제 할 수 없습니다.프로그램 이 수정 사항 을 제출(commt)하거나 스크롤 백(rollback)하면 잠 긴 자원 이 방출 되 어 다른 사용자 가 작업 할 수 있 습 니 다.
그러나 일부 상황 에서 프로그램의 일부 특수 한 원인 으로 인해 자원 을 잠 근 후 장시간 작업 을 제출 하지 않 았 습 니 다.또는 사용자 의 원인 으로 인해 수정 해 야 할 데 이 터 를 추출 한 후에 제때에 수정 하고 제출 하지 않 고 옆 에 두 어야 합 니 다.또는 클 라 이언 트 서버 방식 에서 클 라 이언 트 가'다운'되 었 지만 서버 측 에서 감지 되 지 않 아 잠 겨 있 는 자원 이 제때에 방출 되 지 않 아 다른 사용자 의 조작 에 영향 을 주 는 상황 이 발생 했다.
따라서 자원 을 잠 근 사용 자 를 신속하게 진단 하고 잠 금 을 해결 하 는 것 이 데이터베이스 관리자 의 도전 이다.
데이터 베이스 응용 시스템 이 갈수 록 복잡 해 지기 때문에 잠 금 자원 이 제때에 방출 되 지 않 는 상황 이 발생 하면 같은 표 에 대해 조작 을 하 는 대량의 사용자 들 이 조작 을 하지 못 해 시스템 의 사용 에 영향 을 줄 수 있다.이때 DBA 는 최대한 빨리 문 제 를 해결 해 야 한다.단,Oracle 8.0.x 에서'잠 금 자원 을 기다 리 고 있 는 사용자 이름 가 져 오기'를 실행 하기 때문에

select a.username, a.sid, a.serial#, b.id1
 from v$session a, v$lock b
 where a.lockwait = b.kaddr
매우 느 립 니 다.(Oracle 7.3.4 에서 빠르게 실 행 됩 니 다)그리고'다른 사용자 의 프로 세 스 를 막 는 검색 어 찾기'를 실행 합 니 다.

  select a.username, a.sid, a.serial#, b.id1
   from v$session a, v$lock b
   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 b.request = 0
 집행 도 더디다.따라서 v$session 의 상 태 를'inactive'(활동 하지 않 음)로 만 들 고 마지막 으로 조작 시간 이 현재 20 분 이상(lastcall_et>20*60 초)의 사용자 프로 세 스 를 제거 한 후에 야 문 제 를 해결 할 수 있 습 니 다.
 그러나 이런 일률적으로 자 르 는 방법 은 사실상'아 기 를 더러 운 물 과 함께 뿌리 는 것'이다.일부 사용자 의 프로 세 스 는'inactive'이 고 오랫동안 활동 하지 않 았 지만 잠 금 대기 상태 에 있 기 때 문 입 니 다.
 그래서 필 자 는 해결책 을 생각 해 냈 다.즉,문제 가 발생 했 을 때의 v$lock,v$session 보기에 있 는 관련 기록 을 자신 이 만 든 표 에 저장 하고 이 표를 조회 하면 속도 가 크게 향상 되 어 문 제 를 신속하게 발견 할 수 있 습 니 다.실제 사용 을 통 해 효과 가 매우 좋다.사용자 의 반응 을 받 은 후 몇 초 만 에 자원 이 잠 겨 있어 다른 사용자 의 프로 세 스 에 영향 을 미 치 는 지 알 아내 고 해당 하 는 처 리 를 할 수 있 습 니 다.
 우선,dba 신분(꼭 system 이 아 닙 니 다)으로 데이터베이스 에 로그 인하 여 세 개의 기본 표를 만 듭 니 다:mysession,my_lock, my_sqltext,검색 할 열 에 해당 하 는 색인 을 만 듭 니 다.문장 은 다음 과 같다.
 remi v$session 보기에 서 관심 필드 를 꺼 내 my 를 만 듭 니 다.session 표,검색 에 사용 할 필드 에 색인 을 만들어 검색 속 도 를 빠르게 합 니 다.

drop table my_session;
create table my_session
as
select a.username, a.sid, a.serial#,
a.lockwait, a.machine,a.status,
a.last_call_et,a.sql_hash_value,a.program
 from v$session a
 where 1=2 ;

create unique index my_session_u1 on my_session(sid);
create index my_session_n2 on my_session(lockwait);
create index my_session_n3 on my_session(sql_hash_value);

remi v$lock 보기에 서 필드 를 꺼 내 my 를 만 듭 니 다.lock 표,검색 에 사용 할 필드 에 색인 을 만들어 검색 속 도 를 빠르게 합 니 다.

drop table my_lock;
create table my_lock
as
select id1, kaddr, sid, request,type
 from v$lock
 where 1=2;

create index my_lock_n1 on my_lock(sid);
create index my_lock_n2 on my_lock(kaddr);

remi v$sqltext 보기에 서 필드 를 꺼 내 my 를 만 듭 니 다.sqltext 표,검색 에 사용 할 필드 에 색인 을 만들어 검색 속 도 를 빠르게 합 니 다.

drop table my_sqltext;
create table my_sqltext
as
select hash_value , sql_text
 from v$sqltext
 where 1=2;

create index my_sqltext_n1 on my_sqltext ( hash_value);

그리고 필요 할 때 SQL*Plus 에서 직접 호출 할 수 있 도록 SQL 스 크 립 트 파일 을 만 듭 니 다.그 중에서 먼저 truncate table 표 이름 명령 으로 표 의 기록 을 삭제 합 니 다.delete 명령 이 아 닌 truncate 명령 을 사용 하 는 이 유 는 delete 명령 을 실행 할 때 재연 기록 이 생 겨 속도 가 느 리 고 색인 이 차지 하 는 공간 이 진정 으로 방출 되 지 않 기 때 문 입 니 다.insert 와 delete 를 반복 하면 색인 이 차지 하 는 공간 이 계속 증가 하고 조회 속도 도 느 려 집 니 다.한편,truncate 명령 은 재연 기록 이 생기 지 않 고 속도 가 delete 보다 빠 르 며 색인 공간 이 상응 하 게 방출 됩 니 다.기록 을 삭제 한 후 세 개의 보기 에 있 는 관련 기록 을 자신 이 만 든 세 개의 표 에 삽입 합 니 다.마지막 으로 이 를 조회 할 때 색인 이 있 고 삽입 할 때 조건 이 걸 러 진 후에 기록 수가 상대 적 으로 적기 때문에 조회 속도 가 빠 르 고 곧 그 결 과 를 볼 수 있다.
이 때 다른 사용자 프로 세 스 를 막 는 프로 세 스 가 정상 적 인 작업 인 것 을 발견 하면 이 사용자 에 게 제출 하 라 고 알려 잠 금 자원 을 방출 하 는 목적 을 달성 할 수 있 습 니 다.정상적으로 작 동 하지 않 으 면 그 상 태 는'inactive'이 고 last 입 니 다.call_et 이 얼마나 되 었 는 지 다음 문 구 를 실행 하여 이 프로 세 스 를 제거 할 수 있 습 니 다.시스템 은 자동 으로 스크롤 백 을 해서 잠 긴 자원 을 방출 합 니 다.

alter system kill session 'sid, serial#'; 

SQL 스 크 립 트 는 다음 과 같 습 니 다.

set echo off
set feedback off
prompt '     .....'
truncate table my_session;
truncate table my_lock;
truncate table my_sqltext;

prompt '    .....'
insert into my_session
select a.username, a.sid, a.serial#,
    a.lockwait, a.machine,a.status,
    a.last_call_et,a.sql_hash_value,a.program
 from v$session a
 where nvl(a.username,'NULL')< >'NULL;

insert into my_lock
select id1, kaddr, sid, request,type
 from v$lock;

insert into my_sqltext
select hash_value , sql_text
 from v$sqltext s, my_session m
 where s.hash_value=m.sql_hash_value;

column username format a10
column machine format a15
column last_call_et format 99999 heading "Seconds"
column sid format 9999

prompt "         "
select a.sid, a.serial#, 
a.machine,a.last_call_et, a.username, b.id1
 from my_session a, my_lock b
 where a.lockwait = b.kaddr;

prompt "      "
select a.sid, a.serial#, 
a. machine, a.last_call_et,a.username,
b. b.type,a.status,b.id1
 from my_session a, my_lock b
 where b.id1 in
   (select distinct e.id1
     from my_session d, my_lock e
    where d.lockwait = e.kaddr)
  and a.sid = b.sid
  and b.request=0;

prompt "    sql "
select a.username, a.sid, a.serial#,
 b.id1, b.type, c.sql_text
 from my_session a, my_lock b, my_sqltext c
 where b.id1 in
    (select distinct e.id1
     from my_session d, my_lock e
     where d.lockwait = e.kaddr)
  and a.sid = b.sid
  and b.request=0
  and c.hash_value =a.sql_hash_value;
 
상기 사고방식 은 Informix,Sybase,DB2 와 같은 다른 대형 데이터베이스 시스템 에 도 사용 할 수 있다.이 스 크 립 트 를 사용 하면 시스템 의 현재 잠 금 대기 상황 을 크게 향상 시 켜 데이터베이스 응용 시스템 의 잠 금 대기 문 제 를 신속하게 해결 할 수 있 습 니 다.그리고 실제로 프로그램 이름과 해당 하 는 sql 문 구 를 꺼 냈 기 때문에 사후 기록 을 개발 자 에 게 맡 겨 분석 하고 근본적으로 해결 할 수 있다.

좋은 웹페이지 즐겨찾기