일반적인 트리거는 테이블에 이벤트 특정 한 개의 작업 (삭제 혹은 입력, 변경)을 하게 되어 있다.

그러나 9.7 FixPack4 부터는 여러 작업을 수행할 수 있도록 트리거 기능이 개선되었다.

업무에 따라, 회사마다 정책에 의해서 트리거를 쓸 수도 있고, 안쓸수도 있지만 “특정 이벤트에 여러 작업을 해야 되는 요건”이 있다면 multi action trigger를 검토할 필요성이 있을 것 같다.

1번 테이블에 데이터가 입력되거나 변경되는 경우, 2번 테이블에 insert 및 update 작업이 기록되도록 하여 multi action이 적용하는지를 테스트 해 보았다.

테이블 생성

db2 “create table t1 (c1 integer, c2 timestamp)
db2 “create table t2 (c1 varchar(10), c2 timestamp)

 

트리거 생성

db2 +p -td"@" -v << EOF

connect to sample @

CREATE OR REPLACE TRIGGER tr1
  BEFORE INSERT OR UPDATE ON t1
  FOR EACH ROW
begin
    IF (INSERTING) THEN
         insert into t2 values ('inserting',current timestamp);
    END IF;

    IF (UPDATING ) THEN
         insert into t2 values ('updating',current timestamp);
    END IF;
end
@
terminate @
EOF

1번 테이블에 데이터 입력 및 2번 테이블의 insert 실행기록 확인

$ db2 "insert into t1 values (1,current timestamp),(2,current timestamp)"
DB20000I  The SQL command completed successfully.

$ db2 "select * from t2"

C1         C2
---------- --------------------------
inserting  2011-10-19-16.19.27.047307
inserting  2011-10-19-16.19.27.075943

  2 record(s) selected.

 

1번 테이블의 데이터 변경 및 2번 테이블의 update 실행기록 확인

$ db2 "update t1 set c1=11 where c1 =1"
DB20000I  The SQL command completed successfully.

$ db2 "select * from t2"

C1         C2
---------- --------------------------
inserting  2011-10-19-16.19.27.047307
inserting  2011-10-19-16.19.27.075943
updating   2011-10-19-16.20.24.818192

  3 record(s) selected.

Offline Backup은 Database가 메모리에서 내려간 상태에서 받아진 것을 의미한다. 다른 관점에서는 Database에 접속이 이뤄지지 않는, 업무 서비스가 되지 않는 상황에서의 백업을 의미한다.

특정 DBMS에서는 이런 offline backup 개념이 없을 수도 있겠지만, DB2에서 백업은 트랜잭션을 기록하는 로그 관리 방식과 밀접한 관련을 갖는다.

순환로깅 방식을 사용하는 경우 백업은 offline 상태에서 진행되고, 아카이브 로깅 방식(사용한 트랜잭션 로그를 버리지 않고 보관)을 사용하는 경우는 offline, online 백업이 가능해 진다.

대부분의 고객사에서는 서비스가 중지되는 시간을 줄이기 위해 Archive 로깅 모드로 DB를 운영한다. 이런 상황에 offline backup을 못하는 것은 아니지만, 받아 놓은 offline backup을 restore 하다보면 약간 당황스러운 상황이 발생한다.

DB2 걸음마 시절, 고객사에서 갑작스럽게 restore 작업을 하다가 탐탁치않게 보던 시선을 느꼈던 순간이 기억난다..

1. 로깅 방식 확인

   V8 버전 이하의 경우, 혹은 전문 백업 솔루션을 사용하는 경우 좀 더 상세히 살펴봐야 하지만 보통은 아래 변수의 설정값을 통하여 Circular 모드인지 아닌지를 확인할 수 있다.

$ db2 get db cfg for sample | grep -i logarchmeth1

First log archive method                 (LOGARCHMETH1) = OFF
Options for logarchmeth1                  (LOGARCHOPT1) =

LOGARCHMETH1 값이 설정되지 않은 경우 Circular 모드로 운영 중임을 의미한다.

이런 경우는 offline backup 을 restore 하면 바로 db 접속이 가능해 진다.

$ db2 backup db sample to /instance/inst97 compress
Backup successful. The timestamp for this backup image is : 20120423104058

$ db2 drop db sample
DB20000I  The DROP DATABASE command completed successfully.

$ db2 restore db sample from /instance/inst97
DB20000I  The RESTORE DATABASE command completed successfully.

$ db2 connect to sample

  Database Connection Information

Database server        = DB2/LINUXX8664 9.7.4
SQL authorization ID   = INST97
Local database alias   = SAMPLE

그러나 아카이빙 로그 모드로 운영되는 경우 offline backup 이미지를 복원하는 경우 바로 접속되지 않는다.

$ db2 get db cfg for sample | grep -i logarchmeth1

First log archive method                 (LOGARCHMETH1) = DISK:/instance/inst97/archive/
Options for logarchmeth1                  (LOGARCHOPT1) =

$ db2 backup db sample to ~/archive compress

Backup successful. The timestamp for this backup image is : 20120423104901

$ db2 drop db sample

DB20000I  The DROP DATABASE command completed successfully.

$ db2 restore db sample from ~/archive

DB20000I  The RESTORE DATABASE command completed successfully.

$ db2 connect to sample

SQL1117N  A connection to or activation of database "SAMPLE" cannot be made
because of ROLL-FORWARD PENDING.  SQLSTATE=57019

위와 같이 SQL1117N 코드를 반환한다. 보통은 online backup을 복원 후, rollforward 작업을 하지 않는 경우에 발생하는 메시지이다.

위의 문제 해결을 2가지 방법이 존재한다.

$ db2 restore db sample from ~/archive

$ db2 rollforward db sample query status

                                Rollforward Status

Input database alias                   = sample
Number of nodes have returned status   = 1

Node number                            = 0
Rollforward status                     = DB  pending
Next log file to be read               = S0000001.LOG
Log files processed                    =  -
Last committed transaction             = 2012-04-23-02.09.42.000000 UTC



$ db2 rollforward db sample stop

                                 Rollforward Status

Input database alias                   = sample
Number of nodes have returned status   = 1

Node number                            = 0
Rollforward status                     = not pending
Next log file to be read               =
Log files processed                    =  -
Last committed transaction             = 2012-04-23-02.09.42.000000 UTC

DB20000I  The ROLLFORWARD command completed successfully.

혹은 다음과 같이 할 수도 있겠다.

$ db2 restore db sample from ~/archive without rolling forward
DB20000I  The RESTORE DATABASE command completed successfully.

$ db2 rollforward db sample query status


                                Rollforward Status

Input database alias                   = sample
Number of nodes have returned status   = 1

Node number                            = 0
Rollforward status                     = not pending
Next log file to be read               =
Log files processed                    =  -
Last committed transaction             = 2012-04-23-02.09.42.000000 UTC

 

만일 online backup 을 restore 하고 위와 같이 rollforward를 중지하도록 하는 경우, rollforward pending은 풀리지 않는다.

$ db2 rollforward db sample stop

SQL1276N  Database "SAMPLE" cannot be brought out of rollforward pending state
until roll-forward has passed a point in time greater than or equal to
"2012-04-23-02.20.40.000000 UTC", because node "0" contains information later
than the specified time

$ db2 rollforward db sample query status


                                Rollforward Status

Input database alias                   = sample
Number of nodes have returned status   = 1

Node number                            = 0
Rollforward status                     = DB  working
Next log file to be read               = S0000000.LOG
Log files processed                    =  -
Last committed transaction             = 2012-04-23-02.20.40.000000 UTC

$ db2 connect to sample

SQL1117N  A connection to or activation of database "SAMPLE" cannot be made
because of ROLL-FORWARD PENDING.  SQLSTATE=57019

온라인 백업은 백업 이미지에 포함된 archive log 를 추출하여 최소한의 시점 복구(rollforward)를 해 주어야 한다.

IBM에서 타 제조사의 DBMS를 DB2로 변경하는 경우, 관련 작업들을 편하고 자동화할 수 있도록  Tool을 제공한다. 한 때는 MTK(Migration Toolkit) 이라는 것을 제공했으나 현재는 V9.7과 같이 나온 DMT(Data Movement Tool) 이라는 것을 제공하고 있다.

어떤 면에서는 MTK가 좋은데, 또 어떤 면에서는 DMT가 낫다.

1. 비교

항목

MTK

DMT

DB연결방식 ODBC JDBC Type 4
운영체제 Windows, Linux, Unix Windows, Linux, Unix
원본 DBMS Oracle, MSSQL, Sybase ASE, MySQL Oracle,MSSQL, Sybase, Access, MySQL, Postgres, db2, db2 /z
목표 DBMS DB2, Informix DB2
장점 1.GUI 화면에서 선택적 추출
2.파일 대상으로 변환 가능
3.DBMS 고유 함수, 프로시저들을 java routine으로 제공
4.다양한 포맷방식으로 data 추출
1. DB접속을 위한 db client 불필요
2. object 와 제약조건이 분리되어 추출
3. 데이터 분할하여 추출
4. 데이터 추출, 적재작업의 병렬처리
5. 데이터 검증 등의 script 제공
단점 1.object DDL 문과 제약조건이 섞여서 추출됨
2. 추출/변환 시 사용자 요건에 맞는 변경이 제한적임
1. DB를 대상으로 추출/변환
2. MTK에 비해 GUI 기능이 약함
3. Oracle 과 DB2 V9.7에 최적화됨

 

2. MTK 화면

제품 다운로드: http://www.ibm.com/developerworks/data/downloads/migration/mtk/

 

3. DMT 화면

제품 다운로드: http://www.ibm.com/developerworks/data/library/techarticle/dm-0906datamovement/

 

자세한 사용법은 위 URL을 통하여 확인하고 다운받아 사용해보면 될 것 같다.

원본 서버에 접속할 수 없는 환경이여서 고객쪽에서 text 파일로 ddl문을 제공하는 경우는 MTK를 적용하여 이관 작업을 진행할 수 밖에 없을 것이다.

반면 테이블의 데이터가 대용량인 경우, MTK가 실행되는 file system 공간이 여유가 없다면 DMT를 이용하여 데이터를 나눠 추출하여 대용량 데이터를 이관해야되는 상황도 있을 것이다. 또는 원본 DBMS의 클라이언트를 다운받아 설치할 수 없어, 접속이 힘든 경우에도 DMT를 사용해야 될 것이다.

지금 시점에는 V9.7에 최적화된 DMT를 사용하는 것이 일반적이겠지만, DMT 사용을 할 수 없는 경우엔 MTK를 사용을 고려해 봐야 될 듯 하다.

시스템을 관리하다가 오류가 발생해서, 아니면 갑작스럽게 DB 시스템이 느려지거나 heavy한 SQL이 있나 해서 수행 중인 SQL모을 확인해 보고자 하는 경우가 있을 것이다.

IBM에서 무료로 제공하는 모니터링 도구 중 잘 사용되는 것이 db2pd와 db2top 2가지가 있다.

db2pd는 informix의 onstat 의 메커니즘을 적용한 도구로 DB2가 사용하는 메모리에서 정보를 수집하게 해주는 도구이다. 장점은 DB 접속 절차가 없어서 db가 hang이 발생하는 순간에도 DB의 정보 수집이 가능하다는 점일 것이다. 단점은 많은 정보가 추출되고, Text 기반으로 출력 형식이 정해져 있어서 보고자 하는 정보를 찾거나 보기가 불편하다는 점일 것이다.

반면, db2top은 (v9.5부터 제품 설치 시 제공되어짐, 하위 버전의 경우는 최신 fixpack에 포함되어제공됨)  snapshot 함수를 이용한 방식으로 telnet 등의 서버 레벨에서 정보를 보기 편하게 제공한다. (linux의 top이나 aix의 topas 같은 Text 기반 GUI ?)

단점은 DB 서버에 부하가 심하거나 하는 경우 수집이 잘 되어지지 않는다. DB에  접속을 해서 정보를 수집하기에 “성능 부하” 문제로 정보를 모니터링 하기에는 조금 힘든 면이 있다. Text 기반으로 정보를 보여주어도 보기 편하게 제공을 하기 때문에 편의성은 좋다고 할 수 있겠다.

이 중 db2top을 이용하여 실행 중인 SQL을 확인해 보는 방법을 살펴보고자 한다.

DB2 서버에 telnet 으로 접속(db2 사용자 계정) 을 하여 수행한다. (DB명: sample)

명령어
> db2top –d sample

대문자 D키를 누르고,

대문자 L 키를 눌러 보고자 하는 SQL의 Hash Value 입력

실행 중인 SQL 전체 구문을 얻을 수 있다. Dynamic SQL 경우에는 (jsp 등에서 ? 처리해서 동적 변수가 실행되는 SQL) 변수 값이 ?로 처리되서 들어오는 문제점은 있다.

db2pd를 통해서 SQL을 확인한다면

> db2pd –d sample –dynamic

Database Partition 0 -- Database SAMPLE -- Active -- Up 0 days 00:06:46 -- Date 03/12/2012 13:17:07

Dynamic Cache:
Current Memory Used           912084
Total Heap Size               1271398
Cache Overflow Flag           0
Number of References          184
Number of Statement Inserts   26
Number of Statement Deletes   8
Number of Variation Inserts   18
Number of Statements          18

Dynamic SQL Statements:
Address            AnchID StmtUID    NumEnv     NumVar     NumRef     NumExe     Text
0x00002B8015F1FD60 111    1          1          1          1          1          SELECT POLICY FROM
    SYSTOOLS.POLICY WHERE MED='DB2TableMaintenanceMED' AND DECISION='TableRunstatsDecision' AND NAME='TableRunstatsPolicy'
0x00002B8015E4F440 164    1          1          1          3          3          SELECT COLNAME, TYPENAME FROM
     SYSCAT.COLUMNS WHERE TABNAME='POLICY' AND TABSCHEMA='SYSTOOLS'
0x00002B8015F2CB80 167    1          1          1          1          1          SELECT IBM.TID, IBM.FID FROM
    SYSIBM.SYSTABLES AS IBM, SYSTOOLS.HMON_ATM_INFO AS ATM WHERE ATM.STATS_FLAG <> 'Y' AND IBM.TYPE IN ( 'S', 'T' ) AND
    ATM.CREATE_TIME = IBM.CTIME AND ATM.SCHEMA = IBM.CREATOR AND ATM.NAME = IBM.NAME ORDER BY IBM.FID, IBM.TID WITH UR
0x00002B8015E423C0 185    1          1          1          1          1          select * from emp
0x00002B8015F279A0 332    1          1          1          1          1          UPDATE SYSTOOLS.HMON_ATM_INFO
    AS ATM SET STATS_FLAG = 'N', REORG_FLAG = 'N' WHERE (ATM.SCHEMA, ATM.NAME) IN   (SELECT IBM.CREATOR,           IBM.NAME
    FROM SYSIBM.SYSTABLES AS IBM    WHERE IBM.TYPE = 'N' )
0x00002B8015EF7400 340    1          1          1          2          2          SELECT TABNAME FROM
    SYSCAT.TABLES  WHERE TABNAME='HMON_ATM_INFO' AND  TABSCHEMA='SYSTOOLS'
0x00002B8015E8CFE0 450    1          1          1          3          3          SELECT TRIGNAME FROM
    SYSCAT.TRIGGERS WHERE TABNAME='POLICY' AND TABSCHEMA='SYSTOOLS'
0x00002B8015F01E80 462    1          1          1          156        156        SELECT CREATE_TIME FROM
    SYSTOOLS.HMON_ATM_INFO WHERE SCHEMA = ? AND NAME = ? FOR UPDATE
0x00002B8015E469A0 513    1          1          1          1          1          select * from staff
0x00002B8015E4B640 580    1          1          1          3          3          CALL
    SYSPROC.SYSINSTALLOBJECTS('POLICY','V','','')
0x00002B8015F1B4E0 639    1          1          1          1          1          DELETE FROM
    SYSTOOLS.HMON_ATM_INFO AS ATM WHERE NOT EXISTS ( SELECT * FROM SYSIBM.SYSTABLES AS IBM WHERE ATM.NAME = IBM.NAME AND
    ATM.SCHEMA = IBM.CREATOR AND ATM.CREATE_TIME = IBM.CTIME ) WITH UR
0x00002B8015F23D80 734    1          1          1          1          1          UPDATE SYSTOOLS.HMON_ATM_INFO
    AS ATM SET ATM.STATS_FLAG = 'Y'
0x00002B8015E91DC0 735    1          1          1          2          2          CALL SYSINSTALLOBJECTS(
    'DB2AC', 'V', NULL, NULL )
0x00002B8015F016E0 766    1          1          1          1          1          SELECT CREATOR, NAME, CTIME
    FROM SYSIBM.SYSTABLES WHERE TYPE='T' OR TYPE='S' OR TYPE='N' WITH UR
0x00002B8015E91160 809    1          1          1          3          3          SET CURRENT LOCK TIMEOUT 5
0x00002B8015EFF380 876    1          1          1          1          1          UPDATE SYSTOOLS.HMON_ATM_INFO
    SET STATS_LOCK = 'N', REORG_LOCK = 'N'
0x00002B8015EFB680 886    1          1          1          2          2          SELECT TABNAME FROM
    SYSCAT.TABLES  WHERE TABNAME='HMON_COLLECTION' AND  TABSCHEMA='SYSTOOLS'
0x00002B8015F2EF00 1014   1          1          1          1          1          SELECT POLICY FROM
    SYSTOOLS.POLICY WHERE MED='DB2CommonMED' AND DECISION='NOP' AND NAME='CommonPolicy'

Dynamic SQL Environments:
Address            AnchID StmtUID    EnvID      Iso QOpt Blk
0x00002B8015F1FF20 111    1          1          CS  5    B
0x00002B8015E4F5C0 164    1          1          CS  5    B
0x00002B8015F2CDA0 167    1          1          CS  5    B
0x00002B8015E42500 185    1          1          CS  5    B
0x00002B8015F27BA0 332    1          1          CS  5    B
0x00002B8015EF7580 340    1          1          CS  5    B
0x00002B8015E8D160 450    1          1          CS  5    B
0x00002B8015F174A0 462    1          1          CS  5    B
0x00002B8015E46AE0 513    1          1          CS  5    B
0x00002B8015E4B7A0 580    1          1          CS  5    B
0x00002B8015F1B6C0 639    1          1          CS  5    B
0x00002B8015F23EE0 734    1          1          CS  5    B
0x00002B8015EF3CA0 735    1          1          CS  5    B
0x00002B8015F01860 766    1          1          CS  5    B
0x00002B8015E912A0 809    1          1          CS  5    B
0x00002B8015EFF4E0 876    1          1          CS  5    B
0x00002B8015EFB800 886    1          1          CS  5    B
0x00002B8015F2F080 1014   1          1          CS  5    B

Dynamic SQL Variations:
Address            AnchID StmtUID    EnvID      VarID      NumRef     Typ Lockname                   Val Insert Time                Sect Size

DAS 에 대한 블로그 글에 Windows 작업 스케줄러에서 DB2 자동화 방법에 대한 문의가 있었다. 최근 Windows 용 DB2를 설치했던 고객사에서도 관련하여 문의가 왔었다. 인터넷에서 관련 자료 검색이 잘 안되었나 하는 생각이 들기도 하여 블로그에 남겨 본다.

Windows XP에서 작업 스케줄러를 설정하는 것과 Windows 7 혹은 Vista 혹은 2008 Server에서 설정하는 방법이 약간 다르다.

DB2 관련 작업을 자동화하기 위해 개인적으로 2개의 파일을 만들어서 설정을 했다.

### XP  및 Windows 2003 서버의 경우 ####

1. cmd 파일 (파일명 예:  backup.cmd)

db2cmd /w /c /i db2 -tf backup.sql >> bak.txt

작업 스케줄러에서  backup.cmd 파일을 등록해서 실행시키면 된다.

실행여부는 bak.txt 로그 파일을 통해 수행 여부를 확인하면 된다.

 

2. db2 파일 (파일명 예: backup.db2)

    파일 확장자는 임의적이다.

!db2 "connect to sample" ;

!db2 "quiesce db immediate force connections" ;

!db2 "terminate" ;

!db2 "backup db sample to 'C:\'" ;

!db2 "connect to sample" ;

!db2 "unquiesce db" ;

!db2 "terminate" ;

위 명령어는 Offline Backup을 받기 위해서 DB에 접속된 연결을 강제 제거하여 DB를 비활성화(offline)시킨 후 백업을 수행하도록 쓰여졌다. (! 는 OS 레벨에서 수행되도록 하기 위한 DB2 환경에서의 escape 문자이다)

 

### Vista 이상  및 Windows 2008 서버의 경우 ####

작업 스케줄러 등록 방식이 바뀌었다.

시작 > 관리도구 > 작업 스케줄러 > 작업만들기 (창의 오른쪽 패널의 “작업”에 “작업 만들기” 선택)

* 동작 Tab  > 새로만들기

   - 프로그램/스크립트

“C:\Program Files (x86)\IBM\SQLLIB\BIN\db2cmd.exe

   - 인수 추가

db2 –tvf listdb1.db2

listdb1.db2 Script
!db2 "list db directory" >> db2list1.txt ;

   - 시작 위치   : listdb1.db2 위치

IBM에서는 V9.5부터 DB2_COMPATIBILITY_VECTOR 라는 레지스트리 변수를 통하여 ORACLE의 특수 기능을 동일하게 사용하도록 지원하기 시작하였다.

ORACLE에서 DB2로 object들을 변환 작업할 때, 도움이 많이 되지만 DBMS가 다른 만큼 동일하게 작용하지 않는 부분이 존재한다. 개인적으로는 “오라클 호환성” 기능은 ORACLE 적인 SQL 등을 내부적으로 DB2 기능으로 mapping 혹은 변환시켜주는 기능이지 “Oracle SQL”을 직접 수행하는 기능은 아니라고 생각하고 있다.

보통은 DB2 V9.7에서 오라클 호환성을 사용하기 위해서는 레지스트리 변수를 DB2_COMPATIBILITY_VECTOR=ORA 로 설정을 한 후 DB를 생성하도록 안내를 한다. 면밀하게 살펴보지는 않았으나 ORACLE의 시스템 관리 뷰들의 생성 유무 차이가 있다.

일반적인 기능은 DB 생성 후에도 “오라클 호환성 변수”를 적용해도 (db2 restart는 필요함) 되는 것으로 알려져 있는데, 다음과 같이 “미묘한 차이”가 발생을 한다.

1. 오라클 호환성을 적용한 후 DB 생성한 경우

테이블 생성
> db2 "create table t1(c1 date, c2 timestamp)"

테이블 DDL 생성
> db2look -d test -e -z "INST97" -t "T1"

결과 확인

CREATE TABLE "INST97 "."T1" (

"C1" TIMESTAMP(0) ,

"C2" TIMESTAMP )

IN "USERSPACE1" ;

테이블 삭제

db2 drop table t1

 

오라클 호환성 제거

db2set DB2_COMPATIBILITY_VECTOR=

db2stop

db2start

 

테이블 생성

db2 "create table t1(c1 date, c2 timestamp)"

 

테이블 DDL문 생성

db2look -d test -e -z "INST97" -t "T1"

 

결과 확인

CREATE TABLE "INST97 "."T1" (

"C1" TIMESTAMP(0) ,

"C2" TIMESTAMP )

IN "USERSPACE1" ;

db2 "select * from t1"

C1                           C2

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

2011-10-26-16.47.38   2011-10-26-16.47.38.548792

  테스트 결과에서 보듯이, date 값이 timestamp(0) 으로 변환됨을 알 수 있다.

반면, 오라클 호환성을 적용하지 않고 DB를 생성한 경우 date 컬럼 속성은 변경되지 않았다.

 

2. 오라클 호환성을 적용하지 않고 DB 생성 후 오라클 호환성 적용한 경우

오라클 호환성 적용
db2set DB2_COMPATIBILITY_VECTOR=ORA

db2stop
db2start

테이블 생성
db2 "create table t1(c1 date, c2 timestamp)"

테이블 DDL 생성
db2look -d test -e -z "INST97" -t "T1"

CREATE TABLE "INST97 "."T1" (

"C1" DATE ,

"C2" TIMESTAMP )

IN "IBMDB2SAMPLEREL" ;


데이터 값 조회
db2 "select * from t1"

C1              C2

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

2011-10-26   2011-10-26-16.57.49.963273

오라클 호환성을 적용하지 않고 DB 생성한 후에는 오라클 호환성 적용과 상관없이 date 형변환은 발생하지 않았다.

만일, 오라클 호환성을 DB를 생성한 상태에서 date 컬럼의 형 변환 막을 방법은 없을 것 같다. 다만 Application에서 값을 가공 처리할 수는 있을 것 같다.

개인적으로는 오라클 호환성을 적용한 경우, SQL 해석기를 DB2로 할 것인지, Oracle로 할 것인지 사용자가 선택할 수 있는 장치가 마련되어야 하지 않은가 하는 생각이 든다.

IBM 기술지원센터에 문의를 해 보지 않아서 bug 여부는 확인하지 않았다.

위 함수는 V9.7 FixPack4에서 새롭게 소개된 함수이다. 특정 컬럼 기준으로 그룹의 문자열 값 세트를 하나의 문자열로 집계하도록 하는 기능을 한다.

고객사쪽에서 문의가 와서 고민하다 위 함수가 생각이 나서 소개를 해 주었는데, 나름 의미가 있을 듯 해서 블로그에도 남겨 본다.

저장된 데이터

C1          C2          C3
----------- ----------- ---
          1           1 A
          1           1 B
          1           1 C
          1           2 D
          1           3 E

 

원하는 결과값

C1          C2          C3_SUM
----------- ----------- ------------
          1           1 A,B,C
          1           2 D
          1           3 E

 

LISTAPP() 함수를 쓰면 다음과 같이 간단한 SQL로 구현된다.

select c1,
         c2,
         substr(listagg(c3,',') within group(order by c3),1,12) as c3_sum
from t1
group by c1, c2

결과값

C1          C2          C3_SUM
----------- ----------- ------------
          1           1 A,B,C
          1           2 D
          1           3 E

 

만일 V9.7 FixPack4 미만이라 사용할 수 없는 경우라면?

본 SQL 경우에는 3개의 문자를 붙이는 경우가 최대라고 가정하고 구현된 SQL이다. Stored Procedure 나 사용자 함수(UDF)를 만들어서 구현한다면 조금은 간단한 SQL 되지 않을까 싶다.

select a.c1, a.c2, a.c5||','|| b.c3 c3
from t1 b,
(select a.c1, a.c2, a.c3, t1.c3 c4, a.c3 || ',' || t1.c3 c5
from t1,
    (select a.c1, a.c2, b.c3
           from (select c1,c2,count(c3) cnt from t1 group by c1, c2 having count(c3) > 1 ) a,
                (select c1,c2,c3 from t1)b
     where a.c1=b.c1 and a.c2=b.c2 fetch first 1 rows only) a
where a.c1 = t1.c1 and a.c2 = t1.c2 and a.c3 <> t1.c3  fetch first 1 rows only) a
where a.c1=b.c1 and a.c2=b.c2 and b.c3 <> a.c3 and b.c3 <> a.c4

union all

select c1, c2, max(c3) c3 from t1 group by c1,c2 having count(c3) = 1

결과값

C1          C2          C3
----------- ----------- -----------
          1           2 D
          1           3 E
          1           1 A,B,C

  3 record(s) selected.

 

테스트한 table 및 insert 문

db2 "create table t1 (c1 integer, c2 integer, c3 varchar(3))"
db2 "insert into t1 values (1,1,'A'),(1,1,'B'),(1,1,'C'),(1,2,'D'),(1,3,'E')"

DBMS마다 데이터베이스가 가지는 자원들은 차이가 난다.

ORACLE 경우는 인스턴스와 DB가 붙어있어서 자원 구분이 불분명하지만, DB2의 경우는 DB 하위에 독립적인 트랜잭션 로그, 메모리(버퍼풀), 테이블 공간등을 지정하고 관리를 한다.

Informix의 경우는 인스턴스 범위에서 트랜잭션 로그, 시스템(메타 테이블) 정보, DB 공간이 지정되고 관리가 된다. (어렴풋한 기억을 더듬어 보면 MS-SQL, Sybase 는 informix와 비슷하지 않을까 싶다.)

그 아키텍처가 제조사 별로 다르기 때문에 DB 크기 산정도 차이가 나겠지만, 그 기준이 되는 것은 “테이블 공간”들의 합일 것이다.

DB2에서는 프로시저를 실행함으로서 DB의 사용크기와 가용 크기를 확인할 수 있다. (단위는  byte)

명령어
        db2 “call sysproc.get_dbsize_info(?,?,?,-1)

참고

    - 첫번째 출력 변수: 실행된 시간소 값

    - 두번째 출력 변수: 데이터베이스의 크기

      (산정방식: dbsize = sum (used_pages * page_size) for each table space (SMS & DMS))

    - 세번째 출력 변수: 데이터베이스 가용 크기

      (산정방식: dbcapacity = SUM (DMS usable_pages * page size) + SUM (SMS container size + file system free size per container))

    - 네번째 입력 변수: 수집 시간 간격 (기본 값: –1)

     -1인 경우 30분 단위 수집을 의미하며, 입력 값은 “분” 단위임

 

 

실행 결과

출력 매개변수 값
--------------------------
매개변수 이름  : SNAPSHOTTIMESTAMP
매개변수 값 : 2004-02-29-18.33.34.561000

매개변수 이름  : DATABASESIZE
매개변수 값 : 22302720

매개변수 이름   : DATABASECAPACITY
매개변수 값 : 4684859392

리턴 상태 = 0

 

간단한 방법은 db2top을 통하여 확인할 수 있다.(옵션: t)

 

화면 아래 가운데 DB Size가 명시되어 있다. (현 크기/ 가용 크기)

유닉스의 “Cron”, 윈도우의 “예약된 작업”을 사용하여 DB2 관리 작업을 자동화 한다. 보통은 OS의 스케줄링 기능을 이용하는데, DB2 자체에서도 기능이 있는지 문의를 받는 경우가 있다.

기능은 있다. 그러나 권장하지는 않는다.(왜 권장하지 않는지는 글을 읽으면 알게 될 것이다.)

DB2 자체의 작업 스케줄링 기능을 어떻게 설정할 수 있는지 살펴 보자.

Windows에서도 DAS (DB2 Administration Server)라는 용도로 계정을 설치할 때 묻는다. Unix나 Linux 에서는 OS 계정으로 인스턴스나 DAS를 생성하기 때문에 설치 작업 하면서 DAS를 왜 만들어야 하는지 의문을 많이 가졌을 것이다.

이 DAS 가 하는 주 업무가 DB2의 작업 스케줄링을 해주는 것이라 보면 되겠다. 물론 DAS의 개념? 역할?은 이것으로 한정되지는 않는다.

1. 도구 카탈로그 설정

   인스턴스가 dbm cfg 라는 구성 변수를 가지고 있듯이 das도 자체 구성 변수를 가지고 있다. 앞으로 기술되는 명령어는 인스턴스 계정으로 실행하면 확인할 수 있다.

   아무런 설정 작업을 하지 않았다면 다음과 같이 결과가 나온다.

명령어 >>
$> db2 get admin cfg

결과  >>

Administration Server 구성

Location of Contact List (CONTACT_HOST) =

Execute Expired Tasks (EXEC_EXP_TASK) = NO

Scheduler Mode (SCHED_ENABLE) = OFF

SMTP Server (SMTP_SERVER) =

Tools Catalog Database (TOOLSCAT_DB) =

Tools Catalog Database Instance (TOOLSCAT_INST) =

Tools Catalog Database Schema (TOOLSCAT_SCHEMA) =

Scheduler User ID =

도구 카탈로그가 되었다면 다음처럼 몇 개의 변수에 값이 들어가 있을 것이다.

Administration Server 구성

문의처 목록 위치(CONTACT_HOST) =

실행 만기 태스크(EXEC_EXP_TASK) = NO

스케줄러 모드(SCHED_ENABLE) = ON

SMTP 서버(SMTP_SERVER) =

데이터베이스 카탈로그 도구(TOOLSCAT_DB) = TOOLSDB

데이터베이스 카탈로그 인스턴스 도구(TOOLSCAT_INST) = DB2

데이터베이스 카탈로그 스키마 도구(TOOLSCAT_SCHEMA) = SYSTOOLS

도구 카탈로그 작업을 하기 전에 다음처럼 해당 변수 값을 초기화 한다.

명령어 >>
db2 update admin cfg using SCHED_ENABLE off TOOLSCAT_DB null TOOLSCAT_INST null TOOLSCAT_SCHEMA null

결과  >>
DB20000I The UPDATE ADMIN CONFIGURATION command completed successfully.

도구 카탈로그 작업을 한다.

- 스케줄링:ON

- 도구 카탈로그 DB명: sample

- 도구 카탈로그 인스턴스명: inst97

- 도구 카탈로그 스키마명: systools

명령어 >>
$> db2 update admin cfg using SCHED_ENABLE on TOOLSCAT_DB sample TOOLSCAT_INST inst97 TOOLSCAT_SCHEMA systools

$> db2admin stop       ( Unix, Linux 시스템에서는 das 계정으로 실행)
$> db2admin start       ( Unix, Linux 시스템에서는 das 계정으로 실행)
$> db2 get admin cfg

결과  >>

           Admin Server Configuration

Authentication Type DAS                (AUTHENTICATION) = SERVER_ENCRYPT

DAS Administration Authority Group Name  (DASADM_GROUP) =

DAS Discovery Mode                           (DISCOVER) = SEARCH
Name of the DB2 Server System               (DB2SYSTEM) = LOCALHOST

Java Development Kit Installation Path DAS   (JDK_PATH) = AUTOMATIC (/home/inst97/sqllib/java/jdk64)
Java Development Kit Installation Path DAS   (JDK_64_PATH) = AUTOMATIC (/home/inst97/sqllib/java/jdk64)

DAS Code Page                            (DAS_CODEPAGE) = 0
DAS Territory                           (DAS_TERRITORY) = 0

Location of Contact List                 (CONTACT_HOST) =
Execute Expired Tasks                   (EXEC_EXP_TASK) = NO
Scheduler Mode                           (SCHED_ENABLE) = ON
SMTP Server                               (SMTP_SERVER) =
Tools Catalog Database                    (TOOLSCAT_DB) = sample
Tools Catalog Database Instance         (TOOLSCAT_INST) = inst97
Tools Catalog Database Schema         (TOOLSCAT_SCHEMA) = systools
Scheduler User ID                                       =

“도구 카탈로그 작업”시 데이터베이스 선택은 원격지의 것이던, 운영되는 시스템의 것이던 상관없다. 이와 관련된 자세한 설정은 정보 센터를 참고하면 될 것 같다.

http://publib.boulder.ibm.com/infocenter/db2luw/v9r7/index.jsp?topic=/com.ibm.db2.luw.admin.cmd.doc/doc/r0008881.html

이 후의 작업은 GUI 도구인 “Task Center”를 이용하여 진행한다.

2. 작업 스케줄링 설정

(1) 태스크 센터에서 “새로 작성”을 선택한다.

(2) 태스크 이름, 명령어 유형 등등을 선택, 기입한다.

(3) 실행할 스크립트를 “명령 스크립트” 탭에 작성한다.

(4) 작업 스케줄링 설정

(5) 사용자 권한 설정 및 확인

(6) 생성한 task 실행 테스트

db2 백업 이미지가 생성되었다. 이제 시간 설정하여 주기적으로 실행되도록 설정만 하면 되겠다.

3. 작업 기록 확인하기

(1) 저널 실행

(2) 실행 기록 목록

(3) 실행 기록 확인

도구 카탈로그를 하는 이유는 “스케줄링 설정 정보”를 “기록”하고, 실행 이력을 관리할 저장소를 설정하는 작업이다.

가끔 GUI 기반으로 DB2 설치 작업을 하다 보면 “도구 카탈로그” 를 할 것이냐는 화면을 본 적이 있을 것이다. 만일 선택을 하게 되면 “TOOLSDB”라는 데이터베이스가 생성되고 이 데이터베이스는 이처럼 작업 스케줄링관련 정보를 저장하는 데이터베이스가 된다.

DB2를 사용하면서 TOOLSDB가 만들어진 경우를 봤을 것이다. 사용을 하던 하지 않던 설치 시 “도구 카탈로그” 선택하면서 생성이 되어진 결과이다.

운영 시스템에 “작업 스케줄링” 정보를 기록하도록 하는 경우는 없을 것 같다. 그렇다고 운영시스템에 이를 위한 별도의 TOOLSDB 데이터베이스를 생성하여 사용하지도 않을 것이다. (자원 낭비이기 때문에)

원격지에 DB2를 스케줄링 작업을 하는 용도로 사용한다고 해도, DB2 엔진이 설치되어져야 하고 데이터베이스가 있어야 한다. 스케줄링 하기 위해 작업을 많이 필요로 한다.

이런 번거로운 작업하느니 편하게  Cron이나 "예약된 작업”을 설정하여 OS상에서 실행되도록 하는 것이 번거로운 설정/구성 작업도 없고, 관리 포인트를 불 필요하게 가져가지 않는 것이 현명할 것이다. (해야 되고 관리해야 될 작업이 많은 DBA입장이라면 현실적으로 쓰지 못할 것이다.)

+ Recent posts