DBMS의 기능 요건을 살피면 “사용자 실수에 의한 트랜잭션 복구” 요건을 보게 되곤 한다.

해당 요건은 ORACLE의 Flashback 기능을 이용한 “행 레벨”, “테이블 레벨” 혹은 “DB 레벨”의 시점 복구를 의미한다.

 

SQL 수행을 잘못해서 취소를 하고자 할 경우 oracle은 flashback을 통해서 SQL 수행 전 시점으로 되돌 릴 수 있다.

현재에도 DB2 에서는 해당되는 기능이 없는 것으로 알고 있기에  “어떤 대안이 있을까” 하는 고민을 하게 된다.

 

테이블공간 생성 시 (현재는 기본 옵션이지만) “삭제된 테이블 복구” 옵션을 주는 경우 삭제된 테이블의 DDL 추출과 백업 이미지를 통하여 데이터를 추출해 내어 복구 작업을 할 수 있다.

이외 Optim HPU(High Performance unload) 유틸리티를 통해서도 백업 이미지에서 특정 데이터를 추출이 가능해서 지워진 데이터 복구가 백업 시점까지는 가능하다.

 

만일 DB2에서 데이터가 변경된 시점의 데이터를 원래대로 되돌리고 싶다면?

데이터 변경 SQL 작업 시 변경 데이터를 별도로 저장을 하거나, V10에서 제공하는 시간 테이블을 통하여 데이터를 추출해서 변경하는 방법이 있을 듯 하다. 단, 명령어 한 줄로 간단히 수행이 아닌,  건건이 update, insert 문을 통해서 작업을 해야 되기 때문에 많이 번잡스러울 것 같다.

 

1) SQL를 통한 로그 작업

    데이터 변경 SQL에 대해서는 다음과 같이 SQL을 사용하여 “데이터 변경 이력”을 관리할 수 있을 것이다.

 

테스트 용 테이블

db2 "create table t1 (i integer, t timestamp, v varchar(10), c varchar(20))"

db2look -d sample -e -t t1 (테이블 DDL확인)

 

변경 전 데이터 조회

데이터 입력

db2 "insert into t1 values (4, current timestamp, 'DDD', 'final') "

데이터 변경하면서 변경 전 값 확인 (DDD –> DEF)

db2 "select * from old table (update t1 set v='DEF' where v='DDD')"

 

변경 전 값 결과

I           T                          V          C
----------- -------------------------- ---------- --------------------
          4 2013-02-14-11.05.49.619950 DDD        final

 

변경 후 데이터 조회 (DDD –> DEF)

db2 "select * from new table (update t1 set v='DEF' where v='DDD')"

 

변경 후 데이터

I           T                          V          C
----------- -------------------------- ---------- --------------------
          4 2013-02-14-11.05.49.619950 DEF        final

 

삭제된 데이터 조회

db2 "select * from old table (delete from t1 where v='DEF')"

 

결과 값

I           T                          V          C
----------- -------------------------- ---------- --------------------
          4 2013-02-14-11.05.49.619950 DEF        final

 

db2 "select * from t1"

I           T                          V          C
----------- -------------------------- ---------- --------------------
          1 2013-02-14-11.00.23.925648 AAA        before
          2 2013-02-14-11.00.28.735184 BBB        before
          3 2013-02-14-11.00.34.503851 CCC        before

  3 record(s) selected.

 

데이터 변경 이력을 관리하고자 한다면 위와 같이 SQL을 사용함으로서 가능할 듯 하다.

단 별도로 변경 이력을 관리하기 위한 저장소가 필요하므로 번잡스럽다.

 

이것을 조금 더 개선시킨 것이 V10에서 나온 Temporal Table 인 것 같다.

 

 

2) 시간 테이블을 통한 데이터 변경 이력 관리

   “시간” 중심으로 데이터 변경 이력을 관리하도록 만들어진 테이블로, “시간”을 “시스템” 혹은 “사용자 정의”  ,” 시스템+사용자 정의” 기준으로 이력 관리를 할 수 있도록 제공한다.

 

    “시스템 시간” 및 “사용자 정의 시간”(Business_Time) 은 특수 Register 변수를 통해서 설정이 가능하다.

 

설정 예

SET CURRENT TEMPORAL BUSINESS_TIME = CURRENT TIMESTAMP - 1 MONTH
SET CURRENT TEMPORAL BUSINESS_TIME = NULL
SET CURRENT TEMPORAL SYSTEM_TIME = CURRENT TIMESTAMP - 1 MONTH

 

위 설정으로 current date, current timestamp 값이 영향을 주지 않으면, 트잭잭션 rollback 시에도 영향을 주지 않는 것으로 정보 센터에는 언급되어 있다.

(참고) http://pic.dhe.ibm.com/infocenter/db2luw/v10r1/index.jsp?topic=%2Fcom.ibm.db2.luw.sql.ref.doc%2Fdoc%2Fr0057360.html

 

(테스트) 시스템 시간 기준 데이터 이력 관리

db2 "create table t1 (i integer, t timestamp, v varchar(10), c varchar(20), sys_start timestamp(12) not null generated always as row begin,

sys_end timestamp(12) not null generated always as row end,

ts_id timestamp(12) not null generated always as transaction start id,

period system_time(sys_start,sys_end))"

 

이력 테이블 생성

db2 "create table t1_hist (i integer, t timestamp, v varchar(10), c varchar(20),

sys_start timestamp(12) not null,

sys_end timestamp(12) not null,

ts_id timestamp(12) not null)"

 

이력테이블 연결 작업

db2 "alter table t1 add versioning use history table t1_hist"

 

데이터 입력

db2 "insert into t1 values (1, current timestamp, 'AAA', 'before')"

(참고) 데이터 입력 후, 이력 테이블(t1_hist) 를 조회하면 값이 출력되지 않는다.

         저장된 데이터의 변경(삭제 포함) 이력만 관리하기 때문이다.

db2 "select * from t1"
I           T                          V          C                    SYS_START                        SYS_END                          TS_ID
----------- -------------------------- ---------- -------------------- -------------------------------- --------------------------------

--------------------------------
          1 2013-02-14-13.29.20.186109 AAA        before               2013-02-14-13.29.20.186107000000 9999-12-30-00.00.00.000000000000 2013-02-14-

13.29.20.186107000000

db2 "select * from t1_hist"

 

데이터 변경 (AAA –> ABC)

db2 "update t1 set v='ABC'"

db2 "select * from t1"
I           T                          V          C                    SYS_START                        SYS_END                          TS_ID
----------- -------------------------- ---------- -------------------- -------------------------------- --------------------------------

--------------------------------
          1 2013-02-14-13.29.20.186109 ABC        before               2013-02-14-13.31.03.853468000000 9999-12-30-00.00.00.000000000000 2013-02-14-

13.31.03.853468000000

db2 "select * from t1_hist"

I           T                          V          C                    SYS_START                        SYS_END                          TS_ID
----------- -------------------------- ---------- -------------------- -------------------------------- --------------------------------

--------------------------------
          1 2013-02-14-13.29.20.186109 AAA        before               2013-02-14-13.29.20.186107000000 2013-02-14-13.31.03.853468000000 2013-02-14-

13.29.20.186107000000

 "붉은 색" 글씨는 변경된 데이터 시점의 시간을 의미한다.

 

* 사용자 정의 시간 기준 이력 관리 테이블(Application-period temporal tables)

   시스템과는 다르게 “generated always” 옵션이 제외되었고, 사용자가 지정하여 시간을 넣기 때문에 중복 값이 발생하지 않도록 “고유 키” 를 생성한다.

create table 테이블명 ( 컬럼명 컬럽타입,

bus_start DATE NOT NULL,

bus_end DATE NOT NULL,

period business_time (bus_start, bus_end))

create unique index idx_테이블명

   on 테이블명 (컬럼명 컬럼타입, business_time without overlaps);

 

 

* 시스템 + 사용자 정의 시간 기준 이력 관리 (Bi-temporal table)

db2 +p -tv << EOF
create table t1 (i integer, t timestamp, v varchar(10), c varchar(20),
                 bus_start  DATE NOT NULL,
                 bus_end    DATE NOT NULL,
                 sys_start  timestamp(12) not null generated always as row begin,
                 sys_end    timestamp(12) not null generated always as row end,
                 ts_id      timestamp(12) not null generated always as transaction start id,
                 period business_time (bus_start, bus_end),
                 period system_time(sys_start,sys_end))
;

create table t1_hist like t1 ;
alter table t1 add versioning use history table t1_hist;
create unique index idx_t1 on t1(i,business_time without overlaps) ;
EOF

 

(참고) http://pic.dhe.ibm.com/infocenter/db2luw/v10r1/index.jsp?topic=%2Fcom.ibm.db2.luw.admin.dbobj.doc%2Fdoc%2Fc0058476.html

 

데이터 이력관리는 “데이터 변경 작업이 발생하는” 업무적으로 중요한 테이블이 대상이 되어야 할 것이다.

속성 상, 데이터가 많이 쌓이기 때문에 데이터 저장소의 크기 관리가 중요한 관리 요건이 된다.

월 혹은 년 기준으로 파티션 테이블을 만들어서, 특정 기간 이후의 이력 데이터는 제거(purge)하는 식으로 사용한다면 데이터가 비대해지는 것은 예방할 수 있지 않을까 싶다.

pureScale에 구성된 인스턴스 상태를 보기 위해서 db2instance –list 를 수행하면 진단로그에 다음과 같은 메시지가 기록된다.

2012-10-02-08.34.14.156718+540 E14601321A556        LEVEL: Error
PID     : 26148990             TID : 65120          PROC : db2sysc 0

FUNCTION: DB2 UDB, high avail services, sqlhaGetInfoForClusterObject, probe:4596
RETCODE : ECF=0x9000053E=1879046850=ECF_SQLHA_RESOURCE_NOT_FOUND

              Resource not found

2012-10-02-08.34.14.158708+540 I14601878A671        LEVEL: Error
PID     : 26148990             TID : 65120          PROC : db2sysc 0


FUNCTION: DB2 UDB, high avail services, sqlhaCheckMountResourcesOnHost, probe:4115
RETCODE : ECF=0x9000053E=-1879046850=ECF_SQLHA_RESOURCE_NOT_FOUND
          Resource not found

2012-10-02-08.34.14.556145+540 E14603779A977        LEVEL: Error
PID     : 26148990             TID : 65120          PROC : db2sysc 0


FUNCTION: DB2 UDB, high avail services, sqlhaGetObjectAttribute2, probe:1200
MESSAGE : ECF=0x90000552=-1879046830=ECF_SQLHA_OBJECT_DOES_NOT_EXIST
          Cluster object does not exist

 

위의 메시지는 DB2 V10.1 FixPack0 에서 발생하였고, 고객사 환경에서만 나오는 메시지였다.

IBM LAB에서는 다음과 같은 답변을 주었다.

It indicates "not find dependencies for this resource" and it is a just information, and this message type is changed from "Error" to "Information" on V10.1fp1.

V10.1 FixPack1 에서 위의 메시지는 “Error”에서 “Info”로 변경되었으며, 위의 메시지는 무시해도 되는 메시지로확인되었다.

1. Primary 서버나 Standby 서버 둘중 아무데서나 TSA를 수정하기 위해서 다음의 환경변수를 설정함

 

export CT_MANAGEMENT_SCOPE=2

 

2. Public Network가 죽었을 때, Private Network가 살아있어서 Takeover가 안되는 경우를 방지하기 위해서 다음과 같이 TSA 옵션을 설정함

 

lsrsrc -Ab IBM.NetworkInterface

 

  • CommGroup 목록 확인

 

chrsrc -s "CommGroup=='???'" IBM.NetworkInterface HeartbeatActivate=0

 

  • ??? : Public CommGroup 제외한 나머지 모든 CommGroup

db2 "VALUES(NEXT VALUE FOR 시퀀스_스키마.시퀀스_)"

 

NEXT VALUE 이용하여 값을 발행하여 조회함!

 

db2 "ALTER SEQUENCE 시퀀스_스키마.시퀀스_ RESTART WITH [ 명령의 결과로 나온 ]"

 

위에서 값을 조회하기 위해서 새로 발행하였으므로 다시 원상복귀 시킴!

 

WITH n 앞으로 발행될 값을 n으로 설정함!

 

Cache 사용하지 않은 Sequence 현재 값은 다음과 같이 있음

 

db2 "SELECT NEXTCACHEFIRSTVALUE, CACHE FROM SYSCAT.SEQUENCES WHERE SEQSCHEMA='시퀀스_스키마' AND SEQNAME='시퀀스_'"

 

CACHE값이 1이면 NO CACHE!

 

CACHE값이 1 , NEXTCACHEFIRSTVALUE값이 앞으로 발행될 값을 의미함!

DB2 HADR을 TSA 없이 설정할 경우, 프라이머리서버 상태를 모니터링하기 위해 필요한 스크립트

#!/bin/ksh

 

while true

do

  rsh 프라이머리서버명 /home/db2inst1/sqllib/bin/db2gcf -i db2inst1 -s | grep DB2 | awk '{ print $4 }' | read STATUS

  if [[ $STATUS != "Available" ]]

  then

    hadr_start.ksh

    exit 0

  fi

  sleep 60

Done

 

※ 위 스크립트는 스탠바이서버에서 nohup등을 사용하여 백그라운드로 실행시킴!

 

※ 위 스크립트를 그냥 실행시키면 잘 수행되지만, 만약 nohup으로 실행시킬 때 정지되는 경우가 발생하면 다음과 같이 스크립트의 수정이 필요!

 

) [1] + Stopped (SIGTTIN)        nohup ./hadr_monitor_loop.ksh &

 

해결책)

 

#!/bin/ksh

 

while true

do

  rsh 프라이머리서버명 -n /home/db2inst1/sqllib/bin/db2gcf -i db2inst1 -s | grep DB2 | awk '{ print $4 }' | read STATUS

  if [[ $STATUS != "Available" ]]

  then

    hadr_start.ksh

    exit 0

  fi

  sleep 60

Done

 

 HACMP 기본 Cluster Process ( "/etc/inittab" 에 등록되어 있는 프로세스 ) 확인
 

[root@unix1:/]# ps -ef |grep cluster

    root 168102 196748   0 10:57:39      -  0:00 /usr/es/sbin/cluster/clstrmgr

    root 250032 196748   0 10:57:36      -  0:00 /usr/es/sbin/cluster/clcomd -d

 

[root@unix2:/]# ps -ef |grep cluster

    root 168102 196748   0 10:57:39      -  0:00 /usr/es/sbin/cluster/clstrmgr

    root 250032 196748   0 10:57:36      -  0:00 /usr/es/sbin/cluster/clcomd -d

 

 HACMP 서비스 프로세스 상태 확인
 

[root@unix1:/]# lssrc -g cluster

Subsystem         Group            PID          Status

 clstrmgrES       cluster          205034       활성

 clinfoES         cluster          491562       활성

 

[root@unix2:/]# lssrc -g cluster

Subsystem         Group            PID          Status

 clstrmgrES       cluster          205034       활성

 clinfoES         cluster          491562       활성

 

 HACMP 시작
 

[root@unix1:/]# smitty clstart

                                              Start Cluster Services

 

입력 필드에 값을 입력하거나 선택하십시오.

원하는 것을 모두 변경한 , Enter 키를 누르십시오.

 

                                                        [입력 필드]

* Start now, on system restart or both                now                                                      +

  Start Cluster Services on these nodes              [unix1,unix2]                                             +

* Manage Resource Groups                              Automatically                                            +

  BROADCAST message at startup?                       true                                                     +

  Startup Cluster Information Daemon?                 true                                                     +

  Ignore verification errors?                         false                                                    +

  Automatically correct errors found during           Yes                                                      +

  cluster start?

 

 HACMP 시작완료 확인
 

[root@unix1:/]# tail -f /tmp/hacmp.out

                        HACMP Event Summary

Event: /usr/es/sbin/cluster/events/check_for_site_up_complete unix2 

Start time: Mon Jul 13 17:27:32 2009

 

End time: Mon Jul 13 17:27:32 2009

 

Action:         Resource:                       Script Name:

----------------------------------------------------------------------------

No resources changed as a result of this event

----------------------------------------------------------------------------

 

[root@unix1:/]# ps -ef|grep cluster

    root 225520 163958   0  17:26:20      -  0:00 /usr/es/sbin/cluster/clinfo

    root 233650 163958   0  17:07:34      -  0:00 /usr/es/sbin/cluster/clcomd -d

    root 245932 163958   0  17:07:37      -  0:00 /usr/es/sbin/cluster/clstrmgr

    root 385094 221188   0  17:30:29  pts/0  0:00 grep cluster

    root 479476 163958   0  17:26:11      -  0:00 haemd HACMP 1 cluster1 SECNOSUPPORT

    root 483574 163958   0  17:26:15      -  0:00 harmad -t HACMP -n cluster1

 

 HACMP 정상 종료
 

[root@unix1:/]# smitty clstop

 

                                              Stop Cluster Services

 

입력 필드에 값을 입력하거나 선택하십시오.

원하는 것을 모두 변경한 , Enter 키를 누르십시오.

 

                                                        [입력 필드]

* Stop now, on system restart or both                 now                                                      +

  Stop Cluster Services on these nodes               [unix1,unix2]                                             +

  BROADCAST cluster shutdown?                         true                                                     +

* Select an Action on Resource Groups                 Bring Resource Groups Offline                            +

 

 HACMP 강제 종료 (unix1)
 

[root@unix1:/]# smitty clstop

                                              Stop Cluster Services

 

입력 필드에 값을 입력하거나 선택하십시오.

원하는 것을 모두 변경한 , Enter 키를 누르십시오.

 

                                                        [입력 필드]

* Stop now, on system restart or both                 now                                                      +

  Stop Cluster Services on these nodes               [unix1]                                                   +

  BROADCAST cluster shutdown?                         true                                                     +

* Select an Action on Resource Groups                 Unmanage Resource Groups                                 +

 

 HACMP 강제 종료 (unix2)
 

[root@unix1:/]# smitty clstop

                                              Stop Cluster Services

 

입력 필드에 값을 입력하거나 선택하십시오.

원하는 것을 모두 변경한 , Enter 키를 누르십시오.

 

                                                        [입력 필드]

* Stop now, on system restart or both                 now                                                      +

  Stop Cluster Services on these nodes               [unix2]                                                   +

  BROADCAST cluster shutdown?                         true                                                     +

* Select an Action on Resource Groups                 Unmanage Resource Groups                                 +

 

 HACMP Takeover (unix1 à unix2)
 

[root@unix1:/]# smitty clstop

 

                                              Stop Cluster Services

 

입력 필드에 값을 입력하거나 선택하십시오.

원하는 것을 모두 변경한 , Enter 키를 누르십시오.

 

                                                        [입력 필드]

* Stop now, on system restart or both                 now                                                      +

  Stop Cluster Services on these nodes               [unix1]                                                   +

  BROADCAST cluster shutdown?                         true                                                     +

* Select an Action on Resource Groups                 Move Resource Groups                                     +

 HACMP Takeover (unix2 à unix1)
 

[root@unix1:/]# smitty clstart

                                              Start Cluster Services

 

입력 필드에 값을 입력하거나 선택하십시오.

원하는 것을 모두 변경한 , Enter 키를 누르십시오.

 

                                                        [입력 필드]

* Start now, on system restart or both                now                                                      +

  Start Cluster Services on these nodes              [unix1]                                             +

* Manage Resource Groups                              Automatically                                            +

  BROADCAST message at startup?                       true                                                     +

  Startup Cluster Information Daemon?                 true                                                     +

  Ignore verification errors?                         false                                                    +

  Automatically correct errors found during           Yes                                                      +

  cluster start?  

 

[root@unix1:/]# smitty hacmp

                                                  HACMP for AIX

 

원하는 항목으로 커서를 이동시킨 , Enter 키를 누르십시오.

 

  Initialization and Standard Configuration

  Extended Configuration

  System Management (C-SPOC)

  Problem Determination Tools

 

[root@unix1:/]# smitty hacmp

                                              Extended Configuration

 

원하는 항목으로 커서를 이동시킨 , Enter 키를 누르십시오.

 

  Discover HACMP-related Information from Configured Nodes

  Extended Topology Configuration

  Extended Resource Configuration

  Extended Cluster Service Settings

  Extended Event Configuration

  Extended Performance Tuning Parameters Configuration

  Security and Users Configuration

  Snapshot Configuration

  Export Definition File for Online Planning Worksheets

 

  Extended Verification and Synchronization

  HACMP Cluster Test Tool

 

> Resource 정의 <

 

                                         Extended Resource Configuration

 

원하는 항목으로 커서를 이동시킨 , Enter 키를 누르십시오.

 

  HACMP Extended Resources Configuration

  Configure Resource Group Run-Time Policies

  HACMP Extended Resource Group Configuration

 

                                      HACMP Extended Resources Configuration

 

원하는 항목으로 커서를 이동시킨 , Enter 키를 누르십시오.

 

  Configure HACMP Applications Servers

  Configure HACMP Service IP Labels/Addresses

  Configure HACMP Tape Resources

  Configure HACMP Communication Adapters and Links

  Configure Custom Disk Methods

  Configure Custom Volume Methods

  Configure Custom Filesystem Methods

  Customize Resource Group and Resource Recovery

  Configure Resource Distribution Preferences

  

> Resource Group 정의 <

 

                                         Extended Resource Configuration

 

원하는 항목으로 커서를 이동시킨 , Enter 키를 누르십시오.

 

  HACMP Extended Resources Configuration

  Configure Resource Group Run-Time Policies

  HACMP Extended Resource Group Configuration

 

요즘처럼 가상화 시대, 클라우드 환경이 언급되는 상황에서는 “Virtual Memory”라는 용어는 색다르게 느껴질 수도 있을 듯 싶다.

고객사쪽에서 db2pd –osinfo를 통해서 보면 나오는 “Virtual Memory가 무엇이냐?”고 문의가 들어 왔었다. host DB2를 접하시는 분들에게는 특별한 기능처럼 여겨지는 듯 하다. (virtual memroy라고 별도로 설정하는게 있는?)

Linux, Unix & Windows 기반의 DB2에서는 물리적인 메모리와 디스크의 SWAP 공간을 통털어서 “Virtual Memory”라고 칭한다. 이렇게 표현된 데에는 DB2의 메모리 아키텍처에 따른 메모리 주소 관리 방식 때문이라고 할 수 있겠다.

DB2가 사용하는 메모리 주소 관리 방식은 VAS (Virtual Address Space) 이다. 즉 가상 주소 공간을 사용한다는 의미인데, 이것은 물리적인 메모리 주소와 다르게 DB2 만의 메모리 주소 체계를 가지고 메모리 자원을 사용한다고 할 수 있을 것이다.

이렇게 VAS를 사용하게 된 이유는 물리적인 주소 체계(Physical Address)를 가지게 되는 경우 실행할 때마다 다른 주소를 가지고 사용을 하게 되고, 수행 중 반납한 메모리 주소들이 발생하면서 메모리 단편화 현상이 심해질 수 있다. 따라서 보기와는 다르게 메모리가 부족해지는 문제가 생길 수 도 있고, 메모리 관련 오류 발생 시 분석이 어려울 수도 있게 되지 않을까 싶다.

이런 이유로 DB2는 시작될 때마다 “동일한 주소 체계”를 사용하기 위해서 “논리적으로 고정적인(물리적으로는 가변적인?)” 공간을 만들고 사용을 하도록 설계되었고 이런 메모리 관리 방식을 “가상 메모리”라고 표현을 한 것 같다.

DB2는 V9부터 64bit 운영체제만 지원하기 때문에 (Windows는 예외) 아래 소개하는 기술문서가 적합하지 않을 수 있으나, DB2 메모리 관리를 이해하는 데는 문제가 없을 것이라 생각한다.

 

다음은 db2pd –osinf를 통한 메모리 크기를 다음처럼 분석해 볼 수 있다. (AIX 환경)

$> db2pd –osinfo

Physical Memory and Swap (Megabytes):

TotalMem    FreeMem      AvailMem      TotalSwap       FreeSwap

15360         6359             n/a               512                 488

Virtual Memory (Megabytes):

Total          Reserved          Available      Free

15872         n/a                   n/a              6847

#> prtconf

Memory Size: 15360 MB
Good Memory Size: 15360 MB

db2pd –osinf 를 통해서 보여주는 메모리 크기는 OS 에서 인식되는 메모리 전체 크기라 할 수 있다. ( prtconf 명령어를 통한 메모리 값과 크기 동일)

"물리적 메모리”의 “TotalMem” 값과 “TotalSwap” 값의 합이 “가상 메모리”의 “Total” 값과 같음을 알 수 있고, “FreeMem” 값도 마찬가지로 같음을 알 수 있다.

 

참고 문서

http://www.ibm.com/developerworks/kr/library/dm-0406qi/index.html

http://www.kdug.kr/index.php?pgname=home/pds&brcode=pds_tech&mode=VV&wrno=1667&page&memberlogin=1

업무적으로 IFS 를 구성해서 사용하는 경우는 Data Migration 인 경우다. 데이터 이관 작업으로 일회성으로 사용을 하기에 IFS 관련 문제가 될 경우는 없었다.

그러나 오라클 IFS 환경에서 개발을 지원하다 보니 성능 문제가 된 적이 있었다.

db2top 에서 세션 정보를 모니터링 하거나, 스냅샷 뷰인 sysibmadm.applications 의 appl_status 상태가 “Wait for Remote” 인 경우가 발생을 한다. nickname 데이터 조회 시, data source에서 sql 처리가 진행 중으로 결과를 기다리는 상태라고 해석해 볼 수 있겠다.

데이터가 많은 테이블이면 별 문제가 되지 않겠지만, 데이터 건수가 얼마 되지 않는데도 이런 식으로 “대기 상태”에 놓여 있다면 SQL을 살펴볼 필요가 있다. (예를 들어 select count(*) from 닉네임 수행 결과는 빠른데, select count(*) from 닉네임 where 컬럼=’문자열’ 이 느린 상황)

해당 문제는 db2expln을 통하여 sql plan을 확인하면서 원인이 찾아졌다.

원본 SQL

select * from 닉네임 where 컬럼 = ‘문자열’

DB2 옵티마이저가 작성한 SQL

select * from  닉네임 A0 where RPAD(A0.컬럼,길이,’ ‘)=RPAD(‘문자열’,길이,’ ‘)

 

문제는 SQL이 data source쪽(오라클)에서 실행될 때, 형 변환이 발생하여 Index Scan을 하지 못하게 되는 것 이였다.

이 문제는 “가변길이 문자열”에 대한 “공백’을 어떻게 처리하는 가의 문제로 귀결되는데, oracle은 “문자열” 과 “문자열 “을 다르게 인식하는 반면, DB2는 “문자열”과 “문자열 “을 같은 문자열로 인식을 한다.

“문자열의 끝의 공백”을 의미있게 볼 것인지 아닌지는 업무 상황에 따라 달라지겠지만, 개인적으로 “동일한 문자열”로 보는게 좋지 않을까? 생각을 한다. (일부터 뒤에 공백을 넣어 문자열을 관리하는 것은 낭비처럼 보이기도 하고, 그렇게 데이터를 정의하는 경우는 드물다고 생각한다.)

나와 같은 생각일까? DB2는 그래서 다른 DataSource의 가변 문자열은 명시적으로 “공백을 채워서” 값을 처리하도록 한 것 같다.

이런 상황에 놓이지 않도록 IFS 옵션에 “varchar_no_trailing_blanks” 옵션을 제공한다.

변수를 번역해 보자면 “varchar에 공백을 끌리지 않게 하는? 남기지 않는?” 정도가 되지 않을지..

이 옵션은 IFS 서버 구성 시 설정할 수 도 있고, nickname 의 컬럼에 지정할 수도 있다.

alter server 서버명 optims(add varchar_no_trailing_blanks ‘Y’)
alter nickname 닉네임 alter column 컬럼명 options (add varchar_no_trailing_blanks ‘Y’)

 

이후 db2expln 으로 수집된 optimizer 실행 계획은 다음과 같을 것이다.

select * from  닉네임 A0 where A0.컬럼 = ‘문자열’

 

IFS의 매커니즘에 대해서 깊게는 모르지만, 위와 같은 옵션에서 nickname 을 조회하는 SQL이 data source(ORACLE)에서도 실행되어진다는 것을 전제한다는 생각이 든다. 

데이터를 가지고 와서  DB2에서 처리되는 것이 아닌..  물론 IO부하로 원하는 값만 DB2로 넘어오게 하는 것이 올바른 처리 방식일 것이다.

고객사에 지원을 하다 보면, 현재의 Database를 다른 곳으로 옮기거나 특정 tablespace의 위치를 바꿔야 하는 경우가 발생한다.

이유는 디스크 공간이 부족해서 여유있는 곳으로 옮겨야 하는 상황이 되었거나, 외장 스토리지의 IO 성능 개선 작업을 하면서 Container로 사용 중인 Raw device의 경로가 변경되거나, 사용자 실수로 데이터가 삭제되서 데이터 복구를 하고자 하는 경우 등이라 할 수 있겠다.

DB 백업 이미지로 위와 같은 작업을 하기에는 시간이 걸린다. 최종 백업을 받고 새로운 곳으로 restore를 해야 되므로 어느 정도 소요시간이 발생한다.

이런 경우 db2relocatedb 유틸리티를 사용하면 백업/복구 방법보다는 작업 시간을 단축할 수 있다.

작업은 db2 중지 후 진행한다.

db2relocatedb 수행을 위한 설정 파일

DB_NAME=데이터베이스명
DB_PATH=데이터베이스 홈 경로
INSTANCE=인스턴스명
NODENUM=0
LOG_DIR=oldDirPath,newDirPath
STORAGE_PATH=스토리지 경로
CONT_PATH=콘테이너경로

<시나리오>

데이터베이스 명 : sample –> test

데이터베이스 위치 : /instance/inst10 –> /database

트랜잭션 로그 경로 : /instance/inst10/inst10/NODE0000/SQL00001/LOGSTREAM0000/

                             -> /database/test/active/

스토리지 경로 : /instance/inst10 –> /database/test/data

 

설정 파일 (db2relo.cfg )

DB_NAME=sample,test
DB_PATH=/instance/inst10,/database
INSTANCE=inst10
NODENUM=0
LOG_DIR=/instance/inst10/inst10/NODE0000/SQL00001/LOGSTREAM0000/,

              /database/test/active/
STORAGE_PATH=/instance/inst10,/database/test/data

 

위치 변경되는 파일들을 옮긴다.

$> cp -R /instance/inst10/ins* /database
$> cp -R ./LOGSTREAM00*/ /database/test/active/NODE0000/LOGSTREAM0000/
$> cp -R NODE00* /database/test/data/inst10
$>mv /database/test/data/inst10/NODE0000/SAMPLE/
         /database/test/data/inst10/NODE0000/TEST/

DB 위치 변경

$>  db2relocatedb -f db2relo.cfg

Files and control structures were changed successfully.
Database was catalogued successfully.
DBT1000I  The tool completed successfully.

변경 확인

# db2 list db directory

System Database Directory

Number of entries in the directory = 1

Database 1 entry:

Database alias                       = TEST
Database name                        = TEST
Local database directory             = /database
Database release level               = f.00
Comment                              =
Directory entry type                 = Indirect
Catalog database partition number    = 0
Alternate server hostname            =
Alternate server port number         =


# db2 get db cfg for test | grep -i "path to log files"
Changed path to log files                  (NEWLOGPATH) =
Path to log files                                       = /database/test/active/NODE0000/LOGSTREAM0000/

 

# db2 connect to test

   Database Connection Information

Database server        = DB2/AIX64 10.1.1
SQL authorization ID   = INST10
Local database alias   = TEST

 

# db2pd -db test -storage

Storage Group Paths:
Address            SGID  PathID    PathState    PathName
0x0A00020010BC0000 0     0         InUse        /database/test/data

 

# db2 "select count(*) from emp"

1
-----------
         42

  1 record(s) selected.

 

* DB 홈 경로 및 트랜잭션 로그 경로, 스토리지 경로의 경우 DB 생성 시 DB2가 자동으로 생성하는 경로명들이 있기 때문에 번거로울 수 있다. 경우에 따라서는 파일 옮기는 작업이 복잡하기 때문에 주의가 필요하고, 특정 콘테이너 단위로 변경하는 작업 정도로 사용하는 것이 안전하다 할 수 있겠다. (위 작업 수행 시, 원본을 copy 해서 db2relocatedb 작업 후 문제없는 경우 원본을 삭제해야 할 것이다.)

 

db2relocatedb 작업 중 일부가 번거로운 경우, 경로재지정 복구를 통하여 수행할 수 있다.

$> db2 backup db test to /work/backup compress
Backup successful. The timestamp for this backup image is : 20121109141428

 

경로 재지정 복구를 위한 복구 스트립트를 생성한다.

$> db2 restore db test from /work/backup taken at 20121109141428 redirect generate script db2redir.clp

 

복구 스트립트를 수정한다.

데이터베이스 명 : test –> sample

데이터베이스 위치 : /database –> /instance/inst10

트랜잭션 로그 경로 :  /database/test/active/ –> /instance/inst10/inst10/NODE0000/SQL00001/LOGSTREAM0000/

스토리지 경로 : /database/test/data –> /instance/inst10

RESTORE DATABASE TEST
FROM '/work/backup'
TAKEN AT 20121109141428
ON '/instance/inst10'
DBPATH ON '/instance/inst10'
INTO SAMPLE
NEWLOGPATH '/instance/inst10/inst10/NODE0000/SQL00001/LOGSTREAM0000/'
REDIRECT
WITHOUT ROLLING FORWARD
;
SET STOGROUP PATHS FOR IBMSTOGROUP
ON '/instance/inst10'
;

RESTORE DATABASE TEST CONTINUE;

restore 실행

$>  db2 -tvf db2redir.clp

RESTORE DATABASE TEST FROM '/work/backup' TAKEN AT 20121109141428 ON '/instance/inst10' DBPATH ON '/instance/inst10' INTO SAMPLE NEWLOGPATH '/instance/inst10/inst10/NODE0000/SQL00001/LOGSTREAM0000/' REDIRECT WITHOUT ROLLING FORWARD
SQL1277W  A redirected restore operation is being performed. During a table
space restore, only table spaces being restored can have their paths
reconfigured. During a database restore, storage group storage paths and DMS
table space containers can be reconfigured.
DB20000I  The RESTORE DATABASE command completed successfully.

SET STOGROUP PATHS FOR IBMSTOGROUP ON '/instance/inst10'
DB20000I  The SET STOGROUP PATHS command completed successfully.


RESTORE DATABASE TEST CONTINUE

DB20000I  The RESTORE DATABASE command completed successfully.

 

확인

$> db2 list db directory

Database 2 entry:

Database alias                       = SAMPLE
Database name                        = SAMPLE
Local database directory             = /instance/inst10
Database release level               = f.00
Comment                              =
Directory entry type                 = Indirect
Catalog database partition number    = 0
Alternate server hostname            =
Alternate server port number         =

$> db2 connect to sample

$> db2pd -db sample –storage

Storage Group Paths:
Address            SGID  PathID    PathState    PathName
0x0A00020010BC0000 0     0         InUse        /instance/inst10

에러라고 봐야할 지, 경고 성 메시지로 메시지를 봐야할 지 개인적으로도 아리송하지만, pureScale 환경에서 진단로그(db2diag.log)에 다음과 같음 메시지를 볼 수 있다.

2012-10-08-15.18.39.607132+540 I35440458A354 LEVEL: Error

PID : 13107340 TID : 1 PROC : db2havend

INSTANCE: db2inst1 NODE : 000

HOSTNAME: dbcni2

EDUID : 1

FUNCTION: DB2 UDB, high avail services, GPFSCluster::refreshVersionInfo, probe:5127

DATA #1 : String, 37 bytes

detected DB2_CFS_GPFS_NO_REFRESH_DATA

pureScale에 구성된 member와 CF의 상태 확인을 위해 보통 db2instance –list 명령어를 사용한다. 그런데 위 명령어가 결과를 반환하는데 약간의 시간이 걸린다. 약 3초 정도…

그래서 실행 시간을 빠르게 하기 위해 DB2_CFS_GPFS_NO_REFRESH_DATA=true 설정을 .profile에 할 수 있다.

위 변수에 대한 정보는 찾아 볼 수 없다. 다만, db2instance –list 를 수행하는 시점에 최신의 데이터를 수집해서 가져 오느냐? 아니면 이미 수집되어 있는(아마도 DB2 내부적으로 주기적으로 수집을 해 놓는 간격이 있어서) 데이터를 가져 오느냐? 의 차이로 짐작하고 있다.

개인적으로 체감하기에 신속한? 결과를 가져오는 것 같지는 않지만, 이 변수를 설정하고 나면 진단로그에 위와 같은 메시지가 기록이 된다. (V10.1 FixPack 0 기준)

여러 가지 테스트를 해 본 바, DB2_CFS_GPFS_NO_REFRESH_DATA 가 적용되는 시점은 db2start 시점은 아니고 db2instance –list 적용 시점에 반영이 된다.

테스트한 환경에서는 . .profile 등을 수행하여 환경 변수를 적용했을 때는 적용되지 못했고, 새롭게 인스턴스 계정으로 switch 한 경우 적용되었다.

+ Recent posts