1. HWM을 여러 프로세스가 동시에 변경하는 것을 막기 위한 락이다
2. HW락을 획득하는 과정에서 경합이 발생하면 enq HW - contention 대기 이벤트 발생한다.
3. 대부분 대량 insert에 의해 발생한다.
4. 대량 update시 언두세그먼트의 급속한 확장이 필요하기 때문에 언두세그먼트에서 HW락 경합 현상 발생한다.
5. HW락의 ID1값은 테이블스페이스 번호, ID2값으 세그먼트 헤더블록의 DBA이다.
6. 세그먼트 공간관리기법을 FLM을 사용라는 경우에 FREELISTS 속성의 기본값이 1로 세팅되기 떼문에 HW락 경합이 발생할 가능성이 높다.
언두 데이터를 undo segment가 아닌 shared pool내의 KTI-UNDO 영역에 저장하는 기능으로, 오라클 10g 이상에서 추가되었다.
KTI-UNDO 영역에 저장된 언두 데이터는 주기적으로 언드세그먼트에 플러시된다.
이로 인해 언두 세그먼트 확장에 의한 HW락 경합이 줄어드는 효과가 있으며, 언두 블록을 읽고 쓰는 작업이 줄어들었다.
그러나, 아직 IMU에 대한 성능이슈가 알려주 있지 않다고 한다.
{code} SYS@TEST3 >select * from v$version; |
BANNER
SYS@TEST3 >show parameter db_block_size;
NAME TYPE VALUE
Tablespace created.
LKWTEST@TEST3 >create table hwm_test (
2 name1 char(2000) default ' ',
3 name2 char(2000) default ' ',
4 name3 char(2000) default ' ',
5 name4 char(1500) default ' ') tablespace hwm_test_tbs;
Table created.
LKWTEST@TEST3 >create or replace procedure massive_insert
2 is
3 begin
4 for idx in 1 .. 10000 loop
5 insert into hwm_test(name1) values(' ');
6 commit;
7 end loop;
8 end;
9 /
Procedure created.
5개 세션에서 수행
LKWTEST@TEST3 >exec massive_insert;
PL/SQL procedure successfully completed.
LKWTEST@TEST3 >@lkw_sess_event.sql
EVENT TOTAL_WAITS TIME_WAITED
|
h2. 4. HW락 경합을 줄이는 방법
1. 9i이상일 경우 ASSM을 사용한다. 8i이하라면 FREELISTS값을 적절하게 설정하고, 필요한 경우 _BUMP_HIGHWATER_MARK_COUNT 파라메터값을 충분하게 지정하여 HWM의 이동을 최소화한다.
2. 적절한 크기의 익스텐트를 사용한다.
3. 8i이상일 경우 LMT를 사용한다.
h3. 4-1. FREELISTS, _BUMP_HIGHWATER_MARK_COUNT 설정 변경
|
SYS@TEST3 >set linesize 120
SYS@TEST3 >col ksppinm format a30
SYS@TEST3 >col "Session Value" format a20
SYS@TEST3 >select a.ksppinm, b.ksppstvl as "Session Value"
2 from x$ksppi a, x$ksppsv b
3 where a.indx=b.indx
4 and a.ksppinm like '%highwater%';
KSPPINM Session Value
LKWTEST@TEST3 >drop table hwm_test;
Table dropped.
LKWTEST@TEST3 >create table hwm_test (
2 name1 char(2000) default ' ',
3 name2 char(2000) default ' ',
4 name3 char(2000) default ' ',
5 name4 char(1500) default ' ')
6 storage ( freelists 6 )
7 tablespace hwm_test_tbs;
Table created.
LKWTEST@TEST3 >create or replace procedure massive_insert
2 is
3 begin
4 for idx in 1 .. 10000 loop
5 insert into hwm_test(name1) values(' ');
6 commit;
7 end loop;
8 end;
9 /
Procedure created.
LKWTEST@TEST3 >alter session set "_bump_highwater_mark_count"=50;
Session altered.
LKWTEST@TEST3 >exec massive_insert;
PL/SQL procedure successfully completed.
LKWTEST@TEST3 >@lkw_sess_event.sql
EVENT TOTAL_WAITS TIME_WAITED
|
h3. 4-2. ASSM
|
SYS@TEST3 >create tablespace hwm_test_tbs2 datafile '/data01/oradata/TEST3/hwm02.dbf' size 100M
autoextend on
extent management local uniform size 1M
segment space management auto;
Tablespace created.
LKWTEST@TEST3 >create table hwm_test2 (
2 name1 char(2000) default ' ',
3 name2 char(2000) default ' ',
4 name3 char(2000) default ' ',
5 name4 char(1500) default ' ') tablespace hwm_test_tbs2;
Table created.
LKWTEST@TEST3 >create or replace procedure massive_insert
2 is
3 begin
4 for idx in 1 .. 10000 loop
5 insert into hwm_test2(name1) values(' ');
6 commit;
7 end loop;
8 end;
9 /
Procedure created.
LKWTEST@TEST3 >exec massive_insert;
PL/SQL procedure successfully completed.
LKWTEST@TEST3 >@lkw_sess_event.sql
EVENT TOTAL_WAITS TIME_WAITED
|
h2. 5. HWM 위치 파악
: dbms_space.unused_space 사용
|
SYS@TEST3 >create or replace procedure show_space
2 ( p_segname in varchar2,
3 p_owner in varchar2 default user,
4 p_type in varchar2 default 'TABLE',
5 p_partition in varchar2 default NULL )
6 as
7 l_free_blks number;
8
9 l_total_blocks number;
10 l_total_bytes number;
11 l_unused_blocks number;
12 l_unused_bytes number;
13 l_LastUsedExtFileId number;
14 l_LastUsedExtBlockId number;
15 l_LAST_USED_BLOCK number;
16 procedure p( p_label in varchar2, p_num in number )
17 is
18 begin
19 dbms_output.put_line( rpad(p_label,40,'.') || p_num );
20 end;
21 begin
22 for x in ( select tablespace_name
23 from dba_tablespaces
24 where tablespace_name = ( select tablespace_name
25 from dba_segments
26 where segment_type = p_type
27 and segment_name = p_segname
28 and owner = p_owner )
29 )
30 loop
31 dbms_space.free_blocks
32 ( segment_owner => p_owner,
33 segment_name => p_segname,
34 segment_type => p_type,
35 partition_name => p_partition,
36 freelist_group_id => 0,
37 free_blks => l_free_blks );
38 end loop;
39
40 dbms_space.unused_space
41 ( segment_owner => p_owner,
42 segment_name => p_segname,
43 segment_type => p_type,
44 partition_name => p_partition,
45 total_blocks => l_total_blocks,
46 total_bytes => l_total_bytes,
47 unused_blocks => l_unused_blocks,
48 unused_bytes => l_unused_bytes,
49 LAST_USED_EXTENT_FILE_ID => l_LastUsedExtFileId,
50 LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId,
51 LAST_USED_BLOCK => l_LAST_USED_BLOCK );
52
53 p( 'Free Blocks', l_free_blks );
54 p( 'Total Blocks', l_total_blocks );
55 p( 'Total Bytes', l_total_bytes );
56 p( 'Total MBytes', trunc(l_total_bytes/1024/1024) );
57 p( 'Unused Blocks', l_unused_blocks );
58 p( 'Unused Bytes', l_unused_bytes );
59 p( 'Last Used Ext FileId', l_LastUsedExtFileId );
60 p( 'Last Used Ext BlockId', l_LastUsedExtBlockId );
61 p( 'Last Used Block', l_LAST_USED_BLOCK );
62 end;
63 /
Procedure created.
SYS@TEST3 >SET SERVEROUTPUT ON
SYS@TEST3 >exec show_space('TEST','LKWTEST','TABLE',NULL);
Free Blocks.............................1
Total Blocks............................128
Total Bytes.............................1048576
Total MBytes............................1
Unused Blocks...........................127
Unused Bytes............................1032192
Last Used Ext FileId....................46
Last Used Ext BlockId...................10121
Last Used Block.........................1
PL/SQL procedure successfully completed.
SYS@TEST3 >insert into lkwtest.test values (1);
1 row created.
SYS@TEST3 >exec show_space('TEST','LKWTEST','TABLE',NULL);
Free Blocks.............................1
Total Blocks............................128
Total Bytes.............................1048576
Total MBytes............................1
Unused Blocks...........................126
Unused Bytes............................1032192
Last Used Ext FileId....................46
Last Used Ext BlockId...................10121
Last Used Block.........................2
PL/SQL procedure successfully completed.
SYS@TEST3 >select header_file, header_block from dba_segments where segment_name = 'TEST' and owner = 'LKWTEST';
HEADER_FILE HEADER_BLOCK
SYS@TEST3 >alter system dump datafile 46 block 10121;
System altered.
--dump file 내용
Extent Control Header
|
h2. 참고 LMT & DMT
Oracle use the data dictionary (tables in the SYS schema) to track allocated and free extents for tablespaces that is in "dictionary managed" mode.
Free space is recorded in the SYS.FET$ table, and used space in the SYS.UET$ table.
Whenever space is required in one of these tablespaces, the ST (space transaction) enqueue latch must be obtained to do inserts and deletes agianst these tables.
As only one process can acquire the ST enque at a given time, this often lead to contention.
Using LMT, each tablespace manages it's own free and used space within a bitmap structure stored in one of the tablespace's data files. Each bit corresponds to a database block or group of blocks.
h2. 문서에 대하여
* 최초작성자 : [~kwlee55]
* 최초작성일 : 2011년 01월 06일
* 이 문서는 [오라클클럽|http://www.gurubee.net] [코어 오라클 데이터베이스 스터디|5차 코어 오라클 데이터베이스 스터디] 모임에서 작성하였습니다.
* {color:blue}{*}이 문서의 내용은 (주)엑셈에서 출간한 'PRACTICAL OWI IN ORACLE 10G'와 'Advanced OWI in Oracle 10g'를 참고하였습니다.*{color}