우리 회사 데이터베이스를 티베로로 변경하기
티베로 리플레이 수행 0 0 610

by 티베로 티베로 리플레이 Database Action Replay [2017.04.09]


1) 티베로 리플레이 바이너리

티베로 리플레이 수행을 위해 제공되는 파일들은 1. 외산 데이터베이스에서 수행 중인 SQL을 파일로 ‘저장’하기 위한 것과 2. 해당 파일을 통해 ‘재현’하기 위한 것 두 종류가 존재한다.

이를 위해 먼저 티베로 리플레이에서 제공하는 바이너리를 살펴보자. 별도의 설치 작업은 없으며 특정 경로에 압축을 해제하면 다음과 같은 디렉토리 구성을 확인할 수 있다

(리플레이 수행은 티맥스 엔지니어가 주도적으로 수행하게 될 것이므로 아주 상세히 살펴볼 필요는 없으나 운영 와스서버의 설정 변경이 필요하므로 기본적인 수행방법만 간단히 안내한다)

  • +player_dist
  • - bin : 부하 재현을 위한 실행 파일이 위치한 경로
  • - jdbc_wrapper : 부하 저장을 위한 JDBC Wrapper 드라이버가 존재하는 경로(JAVA 1.6 이상 : jdbc_wrapper.jar, JAVA 1.5 : jdbc_wrapper5.jar)
  • - lib : Replay 부하 재현에 필요한 Library file 경로(Replay를 이용해 부하 재현시 필요한 Library file과 Target DB 인 Tibero JDBC file이 위치할 경로)
  • - logs : Replay 부하 재현시 발생되는 로그가 생성되는 경로
  • - replayplan : Replay plan file이 생성되는 경로(jwl 파일들을 분석하여 부하를 재현할 수 있도록 내부 로그들이 정리된 Plan 파일들이 생성되는 경로)
  • - reports : Replay 수행결과 리포트가 생성되는 경로 (저장된 부하들이 재현된 시간, 수행 SQL 건수 및 실패 횟수 등이 기록)

2) 리플레이 SQL 부하 저장(Logging to jwl 파일)

리플레이를 통해 SQL 부하 저장을 위해서는 먼저 와스서버에서 현재 사용 중인 JDBC 드라이버가 위치한 곳에 위 바이너리 파일의 jdbc_wrapper 경로에 존재하는 JDBC Wrapper 드라이버를 복사하여 저장해야 한다.

그리고 와스서버의 JDBC 관련 설정 파일에 JDBC Wrapper 드라이버를 사용할 수 있도록 수정을 진행하고 재가동하면 SQL 부하 저장이 시작된다. 다음의 소속 회사 설정 사례를 통해 조금 더 자세히 살펴보도록 하자(소속 회사의 와스서버는 JEUS6를 사용 중이다).

가. jdbc wrapper 드라이버 저장

>> $JEUS_HOME/lib/datasource 경로에 $REPLAY_HOME/lib/jdbc_wrapper.jar을 저장한다(JAVA 1.6 : jdbc_wrapper.jar, JAVA 1.5 :jdbc_wrapper5.jar).

나. jdbc 설정 변경

>> JEUSMain.xml 설정 변경(DatabaseSource 부분

* 변경 전 설정

...
    OriginalDataSourceName
    ConnectionPoolDataSource
    OriginalDataSourceName
...

* 변경 후 설정

...
    com.tmax.replay.jdbc.ConnectionPoolDataSourceWrapper 
    <-- 기존 JDBC 클래스 이름을 제거하고wrapper string을 입력한다.
    ConnectionPoolDataSource
    com.tmax.replay.jdbc.ConnectionPoolDataSourceWrapper 
    <-- 기존 JDBC 클래스 이름을 제거하고 wrapper string을 입력한다.
    ...
    
        OriginalDataSourceClassName
        java.lang.String
        OriginalDataSourceName 
        <-- OriginalDataSourceClassName property에 기존 JDBC string을 입력한다.
    
    
        loggingDurationInMinute
        java.lang.Integer
        660 <-- 와스 재기동 이후 11시간 동안 부하를 저장한다.
    
    
        jwlFileArchiveSizeInMegabytes
        java.lang.Long
        500 <-- 500MByte 단위로 나누어서 저장한다.
    
    
        jwlDirectory
        java.lang.String
        /jwlog <-- jwl 파일이 저장될 경로를 지정한다.
    
    
        jwrapperDataSourceName
        java.lang.String
        ReplayTest 
        <-- 해당 was의 datasource를 통해 저장된 jwl 파일은 ReplayTest라는 이름이 포함된다.
    
...

소속 회사의 사례에서 보는 바와 같이 설정 파일의 를 wrapper 드라이버의 이름으로 교체하고 를 통해 기존에 사용한 JDBC 및 부하 저장 옵션을 기록하면 필요한 모든 수정이 완료되므로 걱정했던 것만큼 설정이 복잡하지 않음을 확인할 수 있다.

또한 SQL 부하 저장이 끝이 나더라도 에 정의한 JDBC 동작은 계속 수행되므로 부하저장 이후 별도로 필요한 설정도 존재하지 않는다.

그리고 가장 걱정했던 SQL 저장으로 인해 추가적으로 와스서버에 가해지는 부하도 거의 없었으므로 와스서버 재기동을 제외하고는 큰 어려움 없이 부하 저장이 가능했다는 것을 확인할 수 있을 것이다.

  • 참고1) 소속 회사의 경우 부하 저장 시 와스서버에 추가되는 부하는 거의 없었으나 다음과 같은 작업으로 인해 부하가 발생할 수 있으므로 리플레이 수행시 와스서버의 세심한 모니터링이 필요할 것이다.
  • - Logging 스레드(Thread)가 Datasource 별로 생성되는 부하
  • - Servlet 수행 Thread 에 SQL , Bind 정보 등을 로깅 스레드에 넘겨주는 부하
  • - 로깅 스레드가 File write하는 부하

  • 참고 2) 부하 저장에는 다음과 같은 SQL 제약 사항이 존재함을 인지해야 한다.
  • - 부하 로깅 시 외부 링크 정보(DB Link , External Table) 등이 Source DB에 포함되어 있었을 경우 Target DB인 티베로에도 사전 설정 필요
  • - Logging Column이나 LOB Column의 경우 로깅을 지원하지 않으나 CLOB의 경우 리플레이 재현 시 부하가 낮게 재현 될 수 있어 랜덤 문자열을 넣어 수행한다.

  • [참고 2-2] 2리플레이 항목(출처 : 티맥스 연구소)
  • No. Property Name Type Detail
    1 OriginalDataSource ClassName java.lang.String 실제 데이터 소스(WAS Connection Pool) 에서 사용하는 벤더의 JDBC Diver Class Name(FQCN) * 필수 Property
    2 loggingDuration InMinute java.lang.Integer WAS Connection Pool 생성 시각을 기준으로 얼마동안 부하를 로깅하여 jwl 파일을 기록할 지 결정하는 값이다.
    기본값은 360(6시간)분이다. 설정 시간 이후에는 로깅하지 않고 Original JDBC의 동작만 수행한다.
    모든 DS가 같은 시각에 종료되는 것을 보장하기 위해 최초 생성된 DS의 duration을 기준으로 그 후 생성된 DS의 로깅duration 시간이 생성된 시각으로 비교되어 분단위로 줄어든다.
    또한 0으로 설정할 경우 로깅을 하진 않고 JDBC 동작만 수행한다. (Default : 360 /Min)
    3 loggingEndTime java.lang.String loggingDurationInMinute과 비슷하게 로깅의 종료 시점을 설정하기 위한 값이다.
    해당 기능이 추가된 이유는 WAS 재부팅 후 loggingDurationInMinute에 의해 로깅되는 시간이 제어가 되는데 여러 DS들을 동시에 Boot할 수 없어 종료 시각이 DS마다 다른 것이 문제이다.
    이후 같은 WAS 내에서는 loggingDurationInMinute만 사용해도 종료 시각이 DS마다 같아지게 패치되었지만, 다른 WAS의 DS간의 종료 시각을 맞출 때에는 loggingDurationInMinute 설정으로는 해결이 매우 불편하다.
    loggingDurationInMinute과 같이 설정되어 있을 경우 해당 Property가 우선순위이며 기본 값은 없다.
    해당 Property의 경우 Replay 정식 제품의 정책에 따라 Deprecate될 수도 있다.
    4 jwlFileArchiveSizeIn Megabytes java.lang.Long 하나의 Datasource 마다 생성되는 jwl 파일을 특정 사이즈로 나눠서 로깅하기 위한 옵션이다.
    각 파일의 사이즈가 클 경우 jwl 파일을 읽어 rpf 파일을 만드는 과정에서 OOM(Out of Memory) 및 파일이 위치한 디렉터리의 여유 공간이 없을 경우 먼저 생성된 파일을 다른 디렉터리로 옮겨서 Free 0%를 방지하기 위해 필요한 프로퍼티이다.
    단위는 MB이며 해당 프로퍼티로 ‘0’ 또는 설정하지 않으면 기본적으로 동작하지 않기 때문에 무한대로 파일 사이즈를 확장한다.
    * 참고로 설정한 사이즈 값을 철저하게 지키는 것이 아니라 버퍼에 있는 것을 다 파일에 쓴 다음 파일 사이즈가 설정값을 넘어가면 Archive하기 때문에 약간 차이가 있을 수 있다.
    5 jwlDirectory java.lang.String jwl 파일을 저장할 디렉터리를 설정하는 프로퍼티이며 절대 경로로 지정한다. 설정하지 않으면 기본적으로는 OS User Home에 저장한다.
    이 값을 설정할 경우 ‘jwlDirectory’ 아래에 새로운 디렉터리를 만들어서 아카이빙을 하고 디렉터리 이름은 jwl 파일에서 확장자가 없는 이름과 동일하다. (Default : $HOME)
    6 jwrapperData SourceName java.lang.String DataSourceWrapper 인스턴스를 구분하기 위한 ID로 jwl 파일 이름 등에 사용된다.
    7 streamLogging LengthLimit java.lang.Integer PrepareStatement.setAsciiStream(int parameterIndex , java.io.InputSream x , int length)와 같이 Stream 형식의 데이터에 대해 length 정보와 함께 bind할 경우 기본적으로는 type 정보만 로깅하고 x에 있는 Stream 데이터는 로깅하지 않는다.
    Stream 데이터를 로깅하려면 byte array를 생성해서 읽어놓고 PrepareStatement.execute()를 호출할 때까지 들고 있어야 하므로 상황에 따라 OutOfMemoryError를 유발할 수 있기 때문이다.
    Stream 데이터 로깅이 필요할 경우에는 이를 적절한 값으로 설정한다. 이 값을 설정하더라도 PrepareStatement.setAsciiStream(int parameterIndex , java.io.InputSream x)와 같이 length 정보가 없는 bind 호출에 대해서는 로깅하지 않는다.

  • [그림 2-10] 리플레이 부하 저장 경로 구성
  • 리플레이 부하 저장 경로 구성

참고) 소속 회사와 같이 나스 스토리지 등을 활용하여 여러 대의 와스서버가 동일한 디렉터리를 사용할 수 있도록 구성하면 각 서버에서 생성된 로깅 파일들을 플레이 서버로 전송하는 등의 작업을 줄일 수 있어 편리하다.

3) 리플레이 재현(Play) 수행

가. 재현을 위한 환경변수 설정

재현을 위해서는 먼저 수행할 서버의 OS User Profile에 다음과 같은 환경변수 설정이 필요하다.

  • - JAVA_HOME : [필수] JAVA 1.6 이상(예시: /usr/lib/jvm/jdk1.6.0_45)
  • - PLAYER_JDBC_DRIVER_PATH : [필수] Tibero JDBC Driver for JAVA 6(예시: /log/tibrunner/player_dist/lib/tibero6-jdbc.jar)
  • - PLAYER_MEM_SIZE : 플레이어 실행 시 필요한 최대 메모리(단위 MB, OutOfMemoryError발생 시 조절 필요하며 최대값이므로 항상 이 설정 만큼의 메모리를 사용하는 것은 아님)
  • - VM_OPTION : 부가적인 JVM 실행 옵션

재현 수행

재현(플레이) 명령어는 실행 파일, 맵 파일, jwl 파일의 경로와 이름만 명시하면 되므로 저장 프로세스와 마찬가지로 매우 간단히 수행이 가능하다.

참고로 맵 파일은 SQL을 재현할 티베로 데이터베이스 접속 정보를 명시하는 파일로써 IP:Port:DBName으로 작성하여 저장하면 된다(예시: *=127.0.0.1:8888:tibero, 좌측(*)은 SQL이 수행된 외산 DBMS 접속 정보 혹은 *로 명시하면 된다).

참고1) 2.2장 리플레이 구조에서 설명한 것처럼 플레이어(player)는 플랜 파일(rpf file)을 생성하여 해당 파일로 재현을 수행하게 되므로 1차 재현 이후 반복해서 재현 테스트를 수행할 경우 jwl 파일이 아닌 플랜 파일을 명시하여 명령어를 수행하는 것이 효과적이다( 명령어: sh [player.sh 경로] -addrmap [map.txt 경로] -rpf [rpf 파일 경로]).

참고2) 특정 터미널에서 한 개의 jwl 파일을 읽어 부하를 재현할 수도 있지만 로깅된 모든 부하를 유사하게 재현하기 위해서는 여러 개의 재현 명령어를 크론 탭에 스케줄링하여 동시에 수행해야 한다.

참고3) 서로 다른 세션 사이의 Dependency가 있는 동작에 대해서는 보장하지 않으므로 주의해야 한다. 예를 들어, 세션 A에서 row X를 update하는 시각과 세션 B에서 row X 를 select하는 시각이 동일할 경우 (CPU Core 2개에서 concurrent하게 수행 시, JDBC 단에서 수행한 이력이 초 단위로 동일할 경우 등) 어느 쪽 세션의 작업이 먼저 수행되었는지 알 수 없어 부하 재현 시 세션에서 수행한 작업의 순서를 보장하지 않는다. 따라서 소속 회사는 데이터 검증이 아닌 SQL 성능 검증을 위해 주로 리플레이를 사용했다.

  • [참고 2-3] Player option
  • player.sh --help
    Usage : player [-addrmap < arg>] [-debug] -jwl < arg> | -rpf < arg>
        -addrmap < arg>  the absolute path of the address mapping file
        -debug          make log4j logger as debug level
        -jwl < arg>      the absolute path of the jwrapper log file
        -rpf < arg>      the absolute path of the replay plan file
        -timescale < arg> make player to run faster by n (must be greater than or equal to 1)
        -convertonly    make player to convert jwl to rpf and not to play the rpf(최신 버전에서 추가)
    

  • [그림 2-11] 리플레이 부하저장 & 재현 인프라 구성
  • 리플레이 부하저장 & 재현 인프라 구성

  • - 해당 강좌는 도서 " [우리 회사 데이터베이스를 티베로로 변경하기]"의 내용을 옮겼습니다.
  • - 해당 도서는 기간계 DBMS(DATABASE MANAGEMENT SYSTEM)를 티베로로 전환하는 실제 프로젝트를 수행한 실무자가 DBMS 전환 과정과 실제 적용 사례, 문제 해결 과정 등을 자세하게 설명하고 있습니다.

- 강좌 URL : http://www.gurubee.net/lecture/2973

- 구루비 강좌는 개인의 학습용으로만 사용 할 수 있으며, 다른 웹 페이지에 게재할 경우에는 출처를 꼭 밝혀 주시면 고맙겠습니다.~^^

- 구루비 강좌는 서비스 제공을 위한 목적이나, 학원 홍보, 수익을 얻기 위한 용도로 사용 할 수 없습니다.

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입