오라클 퍼포먼스 튜닝

2024년 2월 7일 4교시

병아리 엔지니어 2024. 2. 7. 14:31

for 현쪽이

 

오전에 했던 부분을 다시한번 복습해보자.

 

1. latch: redo copy

(체인지 벡터를 리두로그 버퍼 안에 카피할 때 잡아야 하는 래치,

카피가 다 끝날 때까지 잡고 있어야 한다. 복사 과정을 처음부터 끝까지 주관하는 래치)

2. latch: redo allocation

(체인지 벡터가 리두로그 버퍼 안에 카피되려면 공간이 필요한데

리두로그 버퍼 안의 공간을 확보하기 위해 잡아야 하는 래치가 latch: redo allocation)
3. latch : redo writing

(리두로그 버퍼 안에서 redo allocation latch 로 공간을 찾는데 > 없으면

> LGWR 에게 리두로그 버퍼에 있는 리두 엔트리들을 커런트한 리두로그 파일 안에 쓰라고 시키

> 그러려면 로그라이터래치를 잡아야 한다.)

- 이 래치를 잡는 순간 log buffer space 라는 wait event 발생

  (log buffer space 는 리두 로그를 기록하기 위해 사용되는 로그 버퍼 공간이 부족한 경우에 발생하는 대기이벤트)

- log file witch completion wait event 도 발생할 수 있다.

  (현재 리두로그 파일이 꽉 차서 로그스위치가 발생하는 경우 > LGWR 는 write 를 못함

   > 로그스위치가 완료될 때까지 LGWR는 기다려야 하는데

   > 그때 발생하는 대기이벤트log file switch completion wait event)

 

로그스위치가 완료되면 > LGWR 는 리두로그 버퍼에 있는 리두 엔트리들을 커런트 그룹에 쓰고

> 공간이 확보되면 > redo allocation 풀어주고

> 체인지 벡터를 리두로그 버퍼 안에 카피하고 > redo copy 래치 풀어준다.

 

그래서 래치가 잡히는 순서는 1 > 2 > 3

풀리는 순서는 3 > 2 > 1

 

그런데 이렇게 래치를 잡고 카피하고 공간이 있는지 체크하는 과정이 너무 번거롭다.

그래서 체인지 벡터를 PGA 에 만들지말고

아예 처음부터 private redo strand 를 리두로그 버퍼에 잡으면 (내 리두정보가 쌓이도록)

redo copy 래치와 redo allocation 래치는 잡을 필요가 없어진다.

(애초에 리두로그 버퍼에 private redo strand 를 만들므로 카피도 필요없고 공간 할당도 필요없어지기 때문)

 

그래서 10g 버전부터 나온 것이 10gR2인데

10gR2 부터는 private redo strands를 위한 공간이 리두로그 버퍼 내에 생성되고

_log_pivate_mul 에 지정된 비율만큼(5퍼센트)을 private redo strands 공간으로 사용한다.

카피를 하지 않기 때문에 'zero copy redo' 라고도 불린다.

 

(10gR1에서는 prs가 ShP 안에 만들어졌음, 단 리두로그 버퍼로 옮기지 않고 ShP 에서 바로 LGF에 내리는 방식

하지만 ShP의 부담이 너무 커서 더이상 쓰지 않는다)


 

SELECT a.ksppinm Parameter, b.ksppstvl Value
FROM x$ksppi a, x$ksppcv b
WHERE a.indx = b.indx
AND a.ksppinm in ('_log_parallelism_dynamic','_log_private_mul');

private redo strands 가 활성화되어 있는지 보기

 

 

SELECT a.ksppinm Parameter, b.ksppstvl Value
FROM x$ksppi a, x$ksppcv b
WHERE a.indx = b.indx
AND a.ksppinm in ('_log_parallelism_dynamic','_log_private_mul', '_log_private_parallelism');

히든 파라미터 하나를 추가해서 검색해봤는데 아예 결과를 보여주지도 않음...

아마도 기본값으로 셋업되어 있나 봄.

 

 

select a.ksppinm, b.ksppstvl
from x$ksppi a
join x$ksppsv b
on a.indx = b.indx
where a.ksppinm like '%log%'
and substr(a.ksppinm, 1, 1) ='_'
order by a.ksppinm;

 

히든 파라미터를 찾아봐도 (수행하면 아나콘다처럼 긴 목록이 나옴) 없다.

그냥 쟤는 없어진 듯... 기본값으로 설정되어 있다고 생각하자.

_log_private_mul 이 설정되었기 때문에 자동으로 설정되었거나

_log_parallel_dynamic 과 통합된 걸로 추측된다...


 

그럼 이제 시뮬레이션을 돌려보자.

 

★ 리두 모니터링

redo_select.txt
0.00MB

 

본문

더보기

select t.used_ublk, t.used_urec
from v$transaction t, v$session s
where s.sid = (select sid from v$mystat where rownum = 1)
and s.taddr = t.addr; 

select n.name, sum(s.value)
from v$sesstat s, v$statname n
where n.name in ('redo entries','redo size', 'redo synch writes','redo writes','redo blocks written','redo log space requests','redo log space wait time')
and s.statistic# = n.statistic#
and s.sid = (select sid from v$mystat where rownum = 1)
group by n.name;

 

select t.used_ublk, t.used_urec
from v$transaction t, v$session s
where s.sid = (select sid from v$mystat where rownum = 1)
and s.taddr = t.addr;

결과 하나도 안나옴.

 



select n.name, sum(s.value)
from v$sesstat s, v$statname n
where n.name in ('redo entries','redo size', 'redo synch writes','redo writes','redo blocks written','redo log space requests','redo log space wait time')   --- 괄호 안에 있는 것들 : 리두 통계정보
and s.statistic# = n.statistic#
and s.sid = (select sid from v$mystat where rownum = 1--- v$mystat: 현재 내 세션 보기 / 다른 유저 모니터링해야 할 때는 소괄호 대신 모니터링해야 하는 유저의 SID 를 넣으면 된다.
group by n.name;

 

모든 값이 다 0: 아직은 리두가 하나도 쌓이지 않았다.

 

 

★ 시나리오 1

 

<<sys>>

 

1. 테이블 만들기

SYS@ora11g> create table hr.redo_table(id number, name char(100));
Table created.

 

2. 대량의 데이터 부어넣기

SYS@ora11g> insert into hr.redo_table(id, name) select object_id, object_name from dba_objects;
86845 rows created.

86,845 건 대량의 데이터 부어넣기: 언두 발생 + 리두 엄청나게 많이 만들어짐

 

3. 현재 트랜잭션에서 사용한 언두블록 수와 언두블록 안의 레코드 수 보기

SYS@ora11g> select t.used_ublk, t.used_urec
from v$transaction t, v$session s
where s.sid = (select sid from v$mystat where rownum = 1)
and s.taddr = t.addr;

 

USED_UBLK  USED_UREC
------------------- --------------------
          44                 2489

 

4.  리두 통계정보 보기

SYS@ora11g> select n.name, sum(s.value)
from v$sesstat s, v$statname n
where n.name in ('redo entries','redo size', 'redo synch writes','redo writes','redo blocks written','redo log space requests','redo log space wait time')
and s.statistic# = n.statistic#
and s.sid = (select sid from v$mystat where rownum = 1)
group by n.name;

 

NAME                                                           SUM(S.VALUE)
---------------------------------------------------------------- ------------
redo entries                                                   7890
redo size                                                          10973296
redo log space requests                                           0
redo log space wait time                                          0
redo synch writes                                                 2
redo blocks written                                               0
redo writes                                                       0

7 rows selected.

 

리두 엔트리가 얼마나 만들어졌고, 리두 사이즈는 얼마이고... 하는 것이 보인다.

 

5. 롤백

SYS@ora11g> rollback;
Rollback complete.

 

6. 다시 리두정보 확인해보기

SYS@ora11g>

select n.name, sum(s.value)
from v$sesstat s, v$statname n
where n.name in ('redo entries','redo size', 'redo synch writes','redo writes','redo blocks written','redo log space requests','redo log space wait time')
and s.statistic# = n.statistic#
and s.sid = (select sid from v$mystat where rownum = 1)
group by n.name;

 

NAME                                                           SUM(S.VALUE)
-----------------------------------------------------------------------------
redo entries                                                         12394
redo size                                                           11680936
redo log space requests                                          0
redo log space wait time                                          0
redo synch writes                                                     3
redo blocks written                                                   0
redo writes                                                               0

7 rows selected.

 

리두가 생성되어 있는 것이 보인다. (롤백도 리두가 생성된다)

 

 

★ 리두 모니터링 통계정보 해석

 

NAME                                   SUM(S.VALUE)                                      해석
-----------------------------------------------------------------------------------------------------------------------------------
redo entries                               12394          --- 리두 엔트리가 리두로그 버퍼에 기록된 횟수
redo size                                11680936         --- 리두 사이즈 (바이트 단위)
redo log space requests               0                --- 리두로그버퍼의 리두엔트리들을 LGWR가 리두로그파일에 쓰려고 하는데

                                                                            로그파일이 꽉 차서 로그스위치가 발생한 횟수

redo log space wait time              0                 --- redo log space requests 에 소요된 시간, 1/100초
redo synch writes                         3                 --- 커밋 혹은 롤백으로 인해 일어난 redo write 수

                                                                            create table 은 내부적으로 딕셔너리를 갱신 조작하기 때문에

                                                                            DML 이 돌아감 > commit 과 rollback 발생
redo blocks written                       0                 --- 리두로그 파일에 write 된 리두로그 블록의 수
redo writes                                   0                 --- 로그라이터 수행 횟수

 

컨트롤파일과 리두로그파일은 OS 블록으로 만들어져 있다. 크기 8K 아님 (데이터파일만 크기가 8K)

OS 블록을 그대로 올리고 내리기 때문에 성능이 좋다.

그래서 리두로그 버퍼는 메모리 크기를 512 byte 의 배수단위로 설정한다.

 

그런데 redo writes (로그라이터의 수행 횟수) = 0 : 롤백을 했지만 아직 write 를 안했다는 뜻

 

다음 교시에서 이어진다...