Tibero RDBMS 애플리케이션개발자안내서 Tibero RDBMS 4 SP1 Copyright 2013 TIBERO Co., Ltd. All Rights Reserved.
Copyright Notice Copyright 2013 TIBERO Co., Ltd. All Rights Reserved. 대한민국경기도성남시분당구서현동 272-6 우 ) 463-824 Restricted Rights Legend All TIBERO Software (Tibero RDBMS ) and documents are protected by copyright laws and the Protection Act of Computer Programs, and international convention. TIBERO software and documents are made available under the terms of the TIBERO License Agreement and may only be used or copied in accordance with the terms of this agreement. No part of this document may be transmitted, copied, deployed, or reproduced in any form or by any means, electronic, mechanical, or optical, without the prior written consent of TIBERO Co., Ltd. 이소프트웨어 (Tibero RDBMS ) 사용설명서의내용과프로그램은저작권법, 컴퓨터프로그램보호법및국제조약에의해서보호받고있습니다. 사용설명서의내용과여기에설명된프로그램은 TIBERO Co., Ltd. 와의사용권계약하에서만사용이가능하며, 사용권계약을준수하는경우에만사용또는복제할수있습니다. 이사용설명서의전부또는일부분을 TIBERO의사전서면동의없이전자, 기계, 녹음등의수단을사용하여전송, 복제, 배포, 2차적저작물작성등의행위를하여서는안됩니다. Trademarks Tibero RDBMS is a registered trademark of TIBERO Co., Ltd. Other products, titles or services may be registered trademarks of their respective companies. Tibero RDBMS 는 TIBERO Co., Ltd. 의등록상표입니다. 기타모든제품들과회사이름은각각해당소유주의상표로서참조용으로만사용됩니다. Open Source Software Notice This product includes open source software developed and/or licensed by "OpenSSL," "RSA Data Security, Inc.," "Apache Foundation," "Jean-loup Gailly and Mark Adler," and "Paul Hsieh's hash". Information about the afore mentioned and the related open source software can be found in the "${INSTALL_PATH}/license/oss_licenses" directory. 본제품은 OpenSSL, RSA Data Security, Inc., Apache Foundation 및 Jean-loup Gailly와 Mark Adler 및 Paul Hsieh's hash 에의해개발또는라이선스된오픈소스소프트웨어를포함합니다. 관련상세정보는제품의디렉터리 ${INSTALL_PATH}/license/oss_licenses 에기재된사항을참고해주십시오. 안내서정보안내서제목 : Tibero RDBMS 애플리케이션개발자안내서발행일 : 2013-02-25 소프트웨어버전 : Tibero RDBMS 4 SP1 안내서버전 : 2.1.4
내용목차 안내서에대하여... ix 제1장 데이터타입의사용... 17 1.1. 개요... 17 1.2. 문자형... 18 1.3. 숫자형... 19 1.4. 날짜형... 20 1.5. 바이너리... 21 1.6. 내재형... 22 제2장 tbjdbc의사용... 23 2.1. JDK 설치... 23 2.2. JDBC의표준기능... 23 2.2.1. JDBC 1.0 및 JDBC 2.0... 24 2.2.2. JDBC 3.0... 26 2.3. 기본프로그래밍... 28 2.3.1. 접속... 29 2.3.2. 실행... 30 2.3.3. 호출... 32 2.3.4. 커밋과롤백... 33 2.3.5. 접속해제... 33 제3장 트리거의사용... 35 3.1. 개요... 35 3.1.1. 트리거의구성요소... 35 3.1.2. 트리거의타입... 36 3.2. 트리거의생성... 36 제4장 XA의사용... 39 4.1. 분산트랜잭션... 39 4.1.1. Two-phase commit... 39 4.1.2. In-doubt 트랜잭션... 41 4.2. XA API... 42 4.2.1. XA 함수... 42 4.2.2. xa_open 함수의속성... 43 4.2.3. XA 애플리케이션프로그래밍... 44 4.3. JDBC에서의 XA 지원... 47 4.3.1. XA 인터페이스... 47 4.3.2. XA 인터페이스프로그래밍... 48 4.4. TP-Monitor와 Tibero 연동... 53 4.4.1. Tmax 와 Tibero 연동... 53 4.4.2. Tuxedo 와 Tibero 연동... 58 Appendix A. tbjdbc 예제프로그램소스코드... 67 Tibero RDBMS iii
A.1. JdbcTest.class... 67 Appendix B. Tibero와 Tuxedo 연동예제프로그램소스코드... 71 B.1. tb_tux.env... 71 B.2. tb_tux.conf.m... 71 B.3. tmax32.fld... 72 B.4. trans_fml32.tbc... 73 B.5. builds.sh... 75 B.6. insert.c... 75 B.7. select.c... 77 B.8. buildc.sh... 79 B.9. create_table.sql... 79 B.10. run.sh... 79 색인... 81 iv Tibero RDBMS 애플리케이션개발자안내서
그림목차 [ 그림 4.1] Two-phase commit 의일반적인예... 40 [ 그림 4.2] In-doubt 트랜잭션이발생하는예... 41 Tibero RDBMS v
예목차 [ 예 2.1] tbjdbc를사용한기본프로그래밍... 28 [ 예 2.2] tbjdbc - 접속... 29 [ 예 2.3] tbjdbc - 실행... 30 [ 예 2.4] tbjdbc - 준비된문장의선언과파라미터바인딩... 31 [ 예 2.5] tbjdbc - 호출... 32 [ 예 2.6] tbjdbc - 접속해제... 33 [ 예 3.1] 트리거의생성... 37 Tibero RDBMS vii
안내서에대하여 안내서의대상 본안내서는 Tibero RDBMS ( 이하 Tibero RDBMS) 에서제공하는각종애플리케이션라이브러리를이용 하여프로그램을개발하려는애플리케이션프로그램개발자를대상으로기술한다. 안내서의전제조건 본안내서를원활히이해하기위해서는다음과같은사항을미리알고있어야한다. 데이터베이스의이해 RDBMS 의이해 Java 프로그래밍의이해 안내서의제한조건 본안내서는 Tibero RDBMS 를실무에적용하거나운용하는데필요한모든사항을포함하고있지않다. 따라서설치, 환경설정등운용및관리에대해서는각제품안내서를참고하기바란다. 참고 Tibero RDBMS 의설치및환경설정에관한내용은 "Tibero RDBMS 설치안내서 " 를참고한다. 안내서에대하여 ix
안내서구성 Tibero RDBMS 애플리케이션개발자안내서는총 4개의장과 Appendix로이루어져있다. 각장의주요내용은다음과같다. 제1장 : 데이터타입의사용 Tibero RDBMS에서제공하는데이터타입과이를사용하는방법을소개한다. 제 2 장 : tbjdbc 의사용 tbjdbc 를사용하는방법을기술한다. 제 3 장 : 트리거의사용 트리거를사용하는방법을기술한다. 제 4 장 : XA 의사용 분산트랜잭션처리에필요한 XA 를사용하는방법을기술한다. Appendix A.: tbjdbc 예제프로그램소스코드 tbjdbc 를이용하여작성한기본프로그램의전체소스코드를기술한다. Appendix B.: Tibero 와 Tuxedo 연동예제프로그램소스코드 Tibero 와 Tuxedo 연동예제프로그램의전체소스코드와각종스크립트를기술한다. x Tibero RDBMS 애플리케이션개발자안내서
안내서규약 표기 <AaBbCc123> <Ctrl>+C [Button] 진하게 " "( 따옴표 ) ' 입력항목 ' 하이퍼링크 > +---- ---- 참고 의미프로그램소스코드의파일명, 디렉터리 Ctrl과 C를동시에누름 GUI의버튼또는메뉴이름강조다른관련안내서또는안내서내의다른장및절언급화면 UI에서입력항목에대한설명메일계정, 웹사이트메뉴의진행순서하위디렉터리또는파일있음하위디렉터리또는파일없음참고또는주의사항 [ 그림 1.1] [ 표 1.1] AaBbCc123 그림이름 표이름 명령어, 명령어수행후화면에출력된결과물, 예제코드 { } [ ] 필수인수값 옵션인수값 선택인수값 안내서에대하여 xi
시스템사용환경 요구사항 Platform HP-UX 11i (PA-RISC, ia64) Solaris (SPARC 9/Solaris 9) AIX (PPC 5L/AIX 5.3) GNU (X86, 64, IA64) Linux kernel 2.6 이상 Hardware 최소 1.5GB 하드디스크공간 512MB 이상메모리공간 Compiler PSM (C99 지원필요 ) tbesql/c (C99 지원필요 ) xii Tibero RDBMS 애플리케이션개발자안내서
관련안내서 안내서 Tibero RDBMS 설치안내서 Tibero RDBMS tbcli 안내서 Tibero RDBMS External Procedure 안내서 Tibero RDBMS JDBC 개발자안내서 Tibero RDBMS tbesql/c 안내서 Tibero RDBMS tbesql/cobol 안내서 Tibero RDBMS tbpsm 안내서 Tibero RDBMS tbpsm 참조안내서 Tibero RDBMS 관리자안내서 Tibero RDBMS tbadmin 안내서 Tibero RDBMS 유틸리티안내서 Tibero RDBMS 설명설치시필요한시스템요구사항과설치및제거방법을기술한안내서이다. Call Level Interface인 tbcli의개념과구성요소, 프로그램구조를소개하고 tbcli 프로그램을작성하는데필요한데이터타입, 함수, 에러메시지를기술한안내서이다. External Procedure를소개하고이를생성하고사용하는방법을기술한안내서이다. Tibero RDBMS에서제공하는 JDBC 기능을이용하여애플리케이션프로그램을개발하는방법을기술한안내서이다. C 프로그래밍언어를사용해데이터베이스작업을수행하는각종애플리케이션프로그램을작성하는방법을기술한안내서이다. COBOL 프로그래밍언어를사용해데이터베이스작업을수행하는각종애플리케이션프로그램을작성하는방법을기술한안내서이다. 저장프로시저모듈인 tbpsm의개념과문법, 구성요소를소개하고, tbpsm 프로그램을작성하는데필요한제어구조, 복합타입, 서브프로그램, 패키지와 SQL 문장을실행하고에러를처리하는방법을기술한안내서이다. 저장프로시저모듈인 tbpsm의패키지를소개하고, 이러한패키지에포함된각프로시저와함수의프로토타입, 파라미터, 예제등을기술한참조안내서이다. Tibero RDBMS의동작과주요기능의원활한수행을보장하기위해 DBA 가알아야할관리방법을논리적또는물리적측면에서설명하고, 관리를지원하는각종도구를기술한안내서이다. SQL/PSM 처리와 DBA를위한시스템관리기능을제공하는 GUI 기반의툴인 tbadmin을소개하고, 설치및사용방법을기술한안내서이다. 데이터베이스와관련된작업을수행하기위해필요한유틸리티의설치및환경설정, 사용방법을기술한안내서이다. Tibero RDBMS를사용하는도중에발생할수있는각종에러의원인과해결방법을기술한안내서이다. 안내서에대하여 xiii
안내서 설명 에러참조안내서 Tibero RDBMS 참조안내서 Tibero RDBMS SQL 참조안내서 Tibero RDBMS의동작과사용에필요한초기화파라미터와데이터사전, 정적뷰, 동적뷰를기술한참조안내서이다. 데이터베이스작업을수행하거나애플리케이션프로그램을작성할때필요한 SQL 문장을기술한참조안내서이다. xiv Tibero RDBMS 애플리케이션개발자안내서
연락처 Korea TIBERO Co., Ltd 272-6 Tmax Building 3th floor, Seohyeon-dong, Bundang-gu, Seongnam-si, Gyeonggi-do, 463-824 South Korea Tel: +82-31-779-7113 Fax: +82-31-779-7119 Email: tibero@tibero.com Web (Korean): http://www.tibero.com 기술지원 : http://technet.tmaxsoft.com USA TmaxSoft, Inc. 560 Sylvan Avenue Englewood Cliffs, NJ 07632 U.S.A Tel: +1-201-567-8266 Fax: +1-201-567-7339 Email: info@tmaxsoft.com Web (English): http://www.tmaxsoft.com Japan TmaxSoft Japan Co., Ltd. 5F Sanko Bldg, 3-12-16 Mita, Minato-Ku, Tokyo, 108-0073 Japan Tel: +81-3-5765-2550 Fax: +81-3-5765-2567 Email: info@tmaxsoft.co.jp Web (Japanese): http://www.tmaxsoft.co.jp 안내서에대하여 xv
China TmaxSoft China Co., Ltd. Beijing Silver Tower, RM 1508, 2# North Rd Dong San Huan, Chaoyang District, Beijing, China, 100027 China Tel: +86-10-6410-6145~8 Fax: +86-10-6410-6144 Email: info.cn@tmaxsoft.com Web (Chinese): http://www.tmaxsoft.com.cn xvi Tibero RDBMS 애플리케이션개발자안내서
제 1 장데이터타입의사용 본장에서는각종애플리케이션라이브러리를사용하기앞서 Tibero RDBMS 가기본적으로제공하는데 이터타입을소개하고사용하는방법을설명한다. 1.1. 개요 데이터타입은데이터베이스에스키마객체를생성할때필요하며, 일반적인클라이언트프로그램에서도모든데이터타입에대응되는변수를사용할수있다. Tibero RDBMS에서제공하는데이터타입은다음과같다. 구분문자형숫자형날짜형 데이터타입 CHAR, VARCHAR, VARCHAR2, CLOB, LONG NUMBER DATE, TIMESTAMP, INTERVAL YEAR TO MONTH, INTERVAL DAY TO SECOND 설명문자열을표현하는데이터타입이다. 정수나실수의숫자를저장하는데이터타입이다. 시간이나날짜를저장하는데이터타입이다. 바이너리 내재형 RAW, BLOB, LONG RAW ROWID 대용량의바이너리데이터를저장하는데이터타입이다. 사용자가명시적으로선언하지않아도 Tibero RDBMS가자동으로삽입되는로우마다포함하는컬럼의타입이다. 참고 데이터타입에대한자세한내용은 "Tibero RDBMS SQL 참조안내서 " 를참고한다. 제 1 장데이터타입의사용 17
1.2. 문자형 본절에서는각데이터타입을사용하는방법을설명한다. CHAR CHAR 타입은일반문자열을저장하는데이터타입으로, 고정길이문자열이다. 사용방법은다음과같다. CHAR[(size)] 옵션 size 설명 size 는선택적으로사용할수있다. ( 최댓값 : 2,000byte) - size 를입력한경우 : size 만큼의고정길이를갖는다. - size 를입력하지않은경우 : 기본값인 1byte 의고정길이를갖는다. VARCHAR VARCHAR 타입은일반문자열을저장하는데이터타입으로, 가변길이문자열이다. 사용방법은다음과같다. VARCHAR(size) 항목 size 설명 size 에정의된만큼의길이를갖는다. ( 최댓값 : 4,000byte) VARCHAR2 VARCHAR2 타입은일반문자열을저장하는데이터타입으로, 가변길이문자열이다. 테이블생성시 VARCHAR 로표시된다. 사용방법은다음과같다. VARCHAR2(size) 18 Tibero RDBMS 애플리케이션개발자안내서
항목 size 설명 size 에정의된만큼의길이를갖는다. ( 최댓값 : 4,000byte) CLOB CLOB 타입은읽을수있는문자열을데이터베이스에저장하는데이터타입으로, 대용량데이터를저장 한다. 사용방법은다음과같다. CLOB 대용량데이터는 4GB 까지저장할수있다. LONG LONG 타입은대용량데이터를저장하기위한데이터타입이다. 단, Oracle과의호환성을위해서만사용한다. 그외에는 CLOB 타입을사용할것을권장한다. 사용방법은다음과같다. LONG 1.3. 숫자형 NUMBER NUMBER 타입은정수또는실수를저장하는데이터타입이다. 실제로데이터베이스에저장될때는숫자의크기에따라가변길이로저장된다. 사용방법은다음과같다. NUMBER[(precision precision, scale)] 옵션 precision scale 설명 정밀도이며, 정수의자릿수를설정한다. 스케일이며, 소수점의자릿수를설정한다. 제 1 장데이터타입의사용 19
1.4. 날짜형 DATE DATE 타입은년, 월, 일의날짜를저장하는데이터타입이다. 실제로데이터베이스에저장될때는고정길이로저장된다. 사용방법은다음과같다. DATE TIMESTAMP TIMESTAMP 타입은 DATE 타입을확장한것으로시간까지저장하는데이터타입이다. 실제로데이터베이스에저장될때는고정길이로저장된다. 사용방법은다음과같다. TIMESTAMP[(frac_sec_prec)] 옵션 frac_sec_prec 설명 시간값의소수초정밀도 (fractional second precision) 를설정한다. - 0 부터 9 까지사용할수있다. ( 기본값 : 6) INTERVAL YEAR TO MONTH INTERVAL YEAR TO MONTH 타입은년과월의차이를저장하는데이터타입이다. 실제로데이터베이스에저장될때는고정길이로저장된다. 사용방법은다음과같다. INTERVAL YEAR [(year_prec)] TO MONTH 옵션 year_prec 설명 year precision 를설정한다. - 0 부터 9 까지사용할수있다. ( 기본값 : 2) - 년의자릿수를제한할수있다. 20 Tibero RDBMS 애플리케이션개발자안내서
INTERVAL DAY TO SECOND INTERVAL DAY TO SECOND 타입은날짜와시간의차이를저장하는데이터타입이다. 실제로데이터베이스에저장될때는고정길이로저장된다. 사용방법은다음과같다. INTERVAL DAY [(day_prec)] TO SECOND [(frac_sec_prec)] 옵션 day_prec 설명 day precision 를설정한다. - 0 부터 9 까지사용할수있다. ( 기본값 : 2) frac_sec_prec TIMESTMAP 타입에정의된옵션과같다. 이타입은 day_prec 옵션과 frac_sec_prec 옵션을사용하여날짜의자릿수, 초이하의자릿수를제한할 수있다. 1.5. 바이너리 RAW RAW 타입은가변길이를갖는바이너리데이터를저장하는데이터타입이다. 사용방법은다음과같다. RAW(size) 항목 size 설명 size 에정의된만큼의길이를갖는다. ( 최댓값 : 2,000byte) BLOB BLOB 타입은대용량의바이너리데이터를저장하는데이터타입이다. 사용방법은다음과같다. BLOB 대용량의바이너리데이터는 4GB 까지저장할수있다. 제 1 장데이터타입의사용 21
LONG RAW LONG RAW 타입은대용량의바이너리데이터를저장하는데이터타입이다. 단, Oracle과의호환성을위해서만사용한다. 그외에는 BLOB 타입을사용할것을권장한다. 사용방법은다음과같다. LONG RAW 1.6. 내재형 ROWID ROWID 타입은데이터베이스테이블의컬럼주소를저장하는데이터타입이다. 실제로데이터베이스에저장될때는고정길이로저장된다. 사용방법은다음과같다. ROWID 22 Tibero RDBMS 애플리케이션개발자안내서
제 2 장 tbjdbc 의사용 Tibero RDBMS에서는 Java 프로그램안에서 SQL 문장을실행하기위해데이터베이스를연결해주는애플리케이션프로그램의인터페이스를제공한다. 이러한인터페이스를 tbjdbc(tibero의 Java database connectivity) 라한다. tbjdbc는 JDK 버전이 1.3 이상의환경에서동작한다. 단, JDK 버전이 1.3인경우에는 tibero4-jdbc-13.jar 파일의형태로제공되며, 그외나머지버전은 tibero4-jdbc.jar 파일의형태로제공된다. 참고 본안내서에서는 JDBC 프로그래밍에대해간략히설명한다. tbjdbc 에대한자세한내용은 "Tibero RDBMS JDBC 개발자안내서 " 를참고한다. 2.1. JDK 설치 tbjdbc 를사용하기위해서는 JDK 1.3 이상이반드시설치되어있어야한다. 다음위치에서 JDK 를다운로드할수있다. http://java.sun.com/javase/downloads/index.jsp 만약시스템이 Sun Microsystems 사의 JDK 를사용하지않는다면, 각각의시스템에적합한 JDK 를찾아 설치한다. 예를들어 HP-UX 는 HP, AIX 는 IBM 에서 JDK 를다운로드받아설치하면된다. 각시스템별 JDK 를설치하는방법은다음위치에서확인할수있다. http://java.sun.com/j2se/1.5.0/install.html 참고 벤더별 JDK 설치방법은각벤더에서제공하는설치안내서를참고한다. 2.2. JDBC 의표준기능 tbjdbc는 JDBC 3.0 표준을준수한다. 다만, 표준에벤더별로구현해도된다고명시한추가기능에대해서는지원하지않을수도있다. 본절에서는 tbjdbc에서구현되는표준기능을 JDBC 버전별로간략히설명한다. 보다자세한내용은 Sun Microsystems사에서발행한 JDBC 3.0 Specification 문서를참고한다. 제 2 장 tbjdbc 의사용 23
2.2.1. JDBC 1.0 및 JDBC 2.0 본절에서는 JDBC 1.0 및 JDBC 2.0 의표준기능을지원여부에따라각각설명한다. 지원하는기능 SQL-99 데이터타입 tbjdbc는 SQL-99에서새롭게추가된데이터타입중에 BLOB와 CLOB만을지원한다. 따라서이러한데이터타입을 Tibero RDBMS에서사용할때는다음과같은규칙을따른다. Blob, Clob 인터페이스는해당트랜잭션이수행중인동안만유효하다. Blob, Clob 인터페이스는위치지시자 (LOCATOR) 를통해구현된다. 위치지시자는데이터베이스서버에존재하는데이터의논리적인지시자 (POINTER) 이다. 인터페이스메소드 지원하는인터페이스메소드 (Interface Method) 는다음과같다. java.sql.driver java.sql.databasemetadata java.sql.resultsetmetadata java.sql.callablestatement java.sql.connection java.sql.preparedstatement java.sql.resultset java.sql.statement java.sql.blob java.sql.clob javax.sql.connectioneventlistener javas.sql.connectionpooldatasource 24 Tibero RDBMS 애플리케이션개발자안내서
javax.sql.datasource javax.sql.pooledconnection javax.sql.xaconnection javax.sql.xadatasource 정적초기화를구현한드라이버 java.sql.driver 인터페이스메소드를구현한드라이버클래스는정적초기화블록 (Static block) 에서 Drivermanager.registerDriver 메소드를호출함으로써, 새로생성한드라이버인스턴스를드라이버관리자 (Driver Manager) 에등록할수있다. SQL-92 Entry Level 의확장기능 DROP TABLE 과 ESCAPE 문을사용할수있다. 스칼라함수 (Scalar Functions) 데이터베이스서버에서지원하는모든스칼라함수를사용할수있다. 스칼라함수는 DatabaseMetaData 클래스를통해확인할수있다. 멀티스레딩 (Multithreading) 여러개의스레드가 java.sql 과 javax.sql 패키지내에존재하는객체에모든연산을동시에수행할수있 다. 스크롤가능한결과집합 (Scrollable ResultSet) 결과집합을전방향또는후방향으로탐색할수있다. 또한, 결과집합내에서상대적이거나절대적인 위치이동도할수있다. 수정가능한결과집합 (Updatable ResultSet) 결과집합을수정할수있다. 민감한결과집합 (Sensitive ResultSet) 결과집합의커서가열린후에발생하는데이터의변화를반영할수있다. 일괄수정작업 (batch updates) 여러번의수정작업을한꺼번에처리할수있다. 제 2 장 tbjdbc 의사용 25
지원하지않는기능 SQL-99 데이터타입 tbjdbc 는 SQL-99 데이터타입중에서 Array, Ref, Struct 를지원하지않는다 인터페이스메소드 지원하지않는인터페이스메소드는다음과같다. java.sql.array java.sql.ref java.sql.sqlinput java.sql.sqloutput java.sql.struct 잘린 (Truncated) 입력파라미터의값에대한예외상황 입력파라미터의값이잘린경우, JDBC 드라이버는 Data Truncation 이라는예외상황 (Exception) 을 발생시킨다. 위치설정을통한수정및삭제 (Positioned Updates and Deletes) 결과집합의커서에서설정한현재위치의레코드를수정하거나삭제하는기능이다. 이기능은수정가 능한결과집합이라는기능으로대체가가능하다. 2.2.2. JDBC 3.0 본절에서는 JDBC 3.0 의표준기능을지원여부에따라각각설명한다. 지원하는기능 인터페이스지원하는인터페이스는다음과같다. DatabaseMetaData ResultSetMetaData 파라미터메타데이터 26 Tibero RDBMS 애플리케이션개발자안내서
ParameterMetaData 인터페이스를구현한 JDBC 클래스는준비된문장 (Prepared Statement) 에서사 용한파라미터개수의정보를제공한다. 단데이터타입및속성 (Property) 에대한메타데이터 (metadata) 는제공하지않는다. 저장점 Savepoint 인터페이스를구현하여트랜잭션에대한저장점설정과커밋및롤백기능을제공한다. 단, 특정한저장점을해제하는 Connection.releaseSavepoint java.sql 메소드는제공하지않는다. 지원하지않는기능 결과집합의유지성 (ResultSet Holdability) 결과집합이열려있는동안에커밋이발생했을때, 결과집합을그대로유지할지아니면닫을지를설정한다. 준비된문장의풀링 (pooling) 애플리케이션서버를통해준비된문장의풀링을구현하고, 여러애플리케이션의접속이이를재사용 한다. 접속풀링 (connection pooling) 의설정 JDBC 3.0 에서는최대풀크기, 최소풀크기, 초기풀크기등과같이접속풀링에사용되는다양한파 라미터를설정할수있는 API 를제공한다. 자동생성키 SQL 문장을실행한후결과집합으로부터 getgeneratedkeys 함수를사용하여결과로우에대한키 를얻는다. 복수개의결과집합반환 JDBC 3.0 에서는한 SQL 문장이여러개의결과집합을열수있도록지원한다. 추가된데이터타입 java.sql.types.datalink URL 과같은외부리소스의접근을제공한다. java.sql.types.boolean BIT 타입과논리적으로동일하다. REF 객체에의해참조된객체의검색및수정 제 2 장 tbjdbc 의사용 27
REF 객체에의해참조된객체를검색하고, 수정할수있는기능을제공한다. BLOB 와 CLOB 객체에존재하는데이터의수정 BLOB 와 CLOB 객체에포함된일부데이터를수정하는기능을제공한다. BLOB 과 CLOB 과 ARRAY 및 REF 데이터타입의컬럼값수정 updateblob 와 updateclob 와 updatearray 및 updateref 를통해해당데이터타입의컬럼값을수정한 다. 그룹변환및데이터타입의매핑 JDBC API 를통해사용자정의데이터타입 (UDT:User Defined Types) 과 Java 클래스간의매핑관계를 설정할수있다. 그러나, Tibero RDBMS 에서는사용자정의데이터타입을지원하지않는다. 2.3. 기본프로그래밍 본절에서는 tbjdbc 에서제공하는인터페이스메소드를통해기본적인 Java 프로그램을작성하는방법 을설명한다. 참고 본절에서설명하고있는기본프로그램의전체소스코드는 Appendix A. tbjdbc 예제프로그램소 스코드 를참고한다. 다음은 public class가포함된 JdbcTest 클래스파일의일부이다. [ 예 2.1] tbjdbc를사용한기본프로그래밍 import java.sql.callablestatement; import java.sql.connection; import java.sql.drivermanager; import java.sql.preparedstatement; import java.sql.resultset; import java.sql.sqlexception; import java.sql.statement; import java.sql.types; public class JdbcTest { Connection conn; { public static void main(string[] args) throws Exception 28 Tibero RDBMS 애플리케이션개발자안내서
JdbcTest test = new JdbcTest(); } test.connect();... a... test.executestatement();... b... test.executepreparedstatement();... c... test.executecallablestatement();... d... test.disconnect();... e... } /*... 기능별멤버함수를구현한다. */ a JdbcTest 라는클래스를통해데이터베이스에접속한다. b ~ d 여러종류의멤버함수를수행한다. e 데이터베이스접속을해제하는작업을수행한다. 다음절부터는위예에서 a ~ e 사이에구현된멤버함수를각각설명한다. 2.3.1. 접속 connect 멤버함수는기본드라이버관리자를이용하여데이터베이스에접속 (connection) 하는기능 (a) 을수행한다. 단, 이멤버함수를사용하려면반드시 java.sql.drivermanager 인터페이스메소드가선언되어있어야한다. [ 예 2.2] tbjdbc - 접속 private void connect() throws SQLException, ClassNotFoundException { Class.forName("com.tmax.tibero.jdbc.TbDriver"); conn = DriverManager.getConnection( "jdbc:tibero:thin:@localhost:8629:tibero", "tibero", "tmax"); } if (conn == null) { System.out.println("connection failure!"); System.exit(-1); } System.out.println("Connection success!"); 구현된내용을차례대로설명하면다음과같다. 1. Class.forName 메소드를호출한다. 제 2 장 tbjdbc 의사용 29
com.tmax.tibero.jdbc.tbdriver 클래스를로드한다. 즉, 사용자가사용할기본드라이버가등록된다. 2. DriverManager.getConnection 메소드를호출한다. 등록된드라이버를통해데이터베이스접속을요청한다. 사용자는 DriverManager.getConnection 메소드의파라미터로접속할데이터베이스의 URL를입력한다. 이때 DriverManager 클래스는데이터베이스접속이가능한지드라이버를검사한다. 3. conn 객체에 getconnection 메소드로새로운데이터베이스접속을생성한다. 접속을해제할때는 close 멤버함수를사용한다. 2.3.2. 실행 tbjdbc에서는다른데이터베이스의클라이언트에서처럼문장 (statement) 에대한개념이존재한다. executestatement 멤버함수는이러한문장을실행 (execution) 하는기능 (b ) 을수행한다. [ 예 2.3] tbjdbc - 실행 private void executestatement() throws SQLException { String droptable = "drop table emp"; String createtable = "create table emp (id number, "+ " name varchar(20), salary number)"; String InsertTable = "insert into emp values(1000, 'Park', 5000)"; Statement stmt = conn.createstatement(); try { stmt.executeupdate(droptable); } catch(sqlexception e) { // if there is not the table } stmt.executeupdate(createtable); stmt.executeupdate(inserttable); } stmt.close(); 구현된내용을차례대로설명하면다음과같다. 1. droptable, createtable, InsertTable 를각각 String 객체참조형변수로만든다. 객체참조형변수에각각특정명령을실행할 SQL 문장을만든다. 30 Tibero RDBMS 애플리케이션개발자안내서
2. conn 객체의 createstatement 메소드로새로운문장을생성한다. 3. executeupdate(str) 메소드를이용하여특정명령을실행한다. 또한, 문장을생성한후에는파라미터를바인딩하여원하는작업을수행할수있다. executepreparedstatement 멤버함수는파라미터가바인딩이된질의를실행하는기능 (c) 을수행한다. [ 예 2.4] tbjdbc - 준비된문장의선언과파라미터바인딩 private void executepreparedstatement() throws SQLException { PreparedStatement pstmt = conn.preparestatement("select name from emp where id =?");... 1... pstmt.setstring(1, "1000"); ResultSet rs = pstmt.executequery(); while (rs.next()) { } System.out.println(rs.getString(1)); } pstmt.close(); 구현된내용을차례대로설명하면다음과같다. 1. PreparedStatement 클래스로준비된문장 (prepared statement) 를선언한다. 2. conn 객체의 preparestatement 메소드를이용하여 PreparedStatement 를생성한다. 이렇게생성된 준비된문장은 execute 로결과를얻을수있다. 3. setstring(bind_no, bind_value) 메소드를이용하여바인딩할파라미터의순서를정하여값 을설정한다. pstmt.setstring(1, "1000") 은준비된문장의첫번째파라미터 (1) 에대응되는 "1000" 이라는문자열을바인딩한다. 4. 파라미터의바인딩이완료된후 executequery 메소드를실행하면결과집합 (ResultSet) 를얻게된 다. 결과집합은개념적으로 tbcli 나 tbesql 의커서와동일하다. 결과집합에 getstring(result_no) 메소드를사용하면실행결과를문자열로확인할수있다. 제 2 장 tbjdbc 의사용 31
2.3.3. 호출 tbjdbc를이용하여작성한프로그램에서 PL/SQL를호출 (call) 할수있다. 이러한문장을호출가능문장 (callable statement) 이라고한다. executecallablestatement 멤버함수는호출가능문장을실행하는기능 (d) 을수행한다. [ 예 2.5] tbjdbc - 호출 private void executecallablestatement() throws SQLException { String callsql = " CREATE PROCEDURE testproc "+ " (ID_VAL IN NUMBER, SAL_VAL IN OUT NUMBER) as " + " BEGIN" + " update emp" + " set salary = SAL_VAL" + " where id = ID_VAL;" + " select salary into SAL_VAL" + " from emp" + " where id = ID_VAl;" + " END;"; String dropproc = "DROP PROCEDURE testproc"; Statement stmt = conn.createstatement(); try { stmt.executeupdate(dropproc); } catch(sqlexception e) { // if there is not the procedure } stmt.executeupdate(callsql); CallableStatement cstmt = conn.preparecall("{call testproc(?,?)}"); cstmt.setint(1, 1000); cstmt.setint(2, 7000); cstmt.registeroutparameter(2, Types.INTEGER); cstmt.executeupdate(); int salary = cstmt.getint(2); System.out.println(salary); } stmt.close(); cstmt.close(); 구현된내용을차례대로설명하면다음과같다. 32 Tibero RDBMS 애플리케이션개발자안내서
1. CREATE PROCEDURE 문장을이용하여프로시저를만든다. DDL 문장은다른문장처럼동일하게 executeupdate(query_str) 메소드를이용하여실행한다. 2. 호출가능문장은 CallableStatement 클래스를통해 conn 객체의 preparecall(str) 메소드를이용하여생성한다. 이렇게생성된호출가능문장은준비된문장과동일하게파라미터를바인딩한다. 파라미터를바인딩하는방법은 setint(bind_no, bind_value) 같은바인딩메소드 (binding method) 를사용한다. 즉 setint등의메소드를사용하고나서 executeupdate 메소드를호출하면된다. 3. CallableStatement 클래스의 registeroutparameter(bind_no, type) 메소드를이용하여바인딩된파라미터중에서출력파라미터를등록한다. 등록할출력파라미터는 1번에서생성된프로시저의두번째파라미터 (SAL_VAL IN OUT NUMBER) 이다. 이파라미터는입출력용으로선언되었으므로출력파라미터로등록할수있다. 4. executeupdate 메소드를호출하여문장을실행한후, 출력파라미터의타입에맞는메소드로실행 결과를가져온다. 프로시저의출력파라미터는 integer 타입으로 CallableStatement 클래스의 getint(bind_no) 메소드를이용하여 salary 에결과값을출력한다. 2.3.4. 커밋과롤백 트랜잭션은하나이상의 SQL 문장으로이루어져있다. SQL 문장이실행되면서전체가커밋 (Commit) 되든지롤백 (Rollback) 된다. tbjdbc는 Connection 객체에서트랜잭션을설정할수있다. 기본값은 auto-commit으로설정되어있다. 트랜잭션의처리모드를변경하려면다음과같이소스코드를추가해야한다. conn.setautocommit(false); conn.rollback(); conn.commit(); conn.settransactionisolation(connection.transaction_read_uncommited) 2.3.5. 접속해제 disconnect 멤버함수는데이터베이스접속을해제하는기능 (e) 을수행한다. [ 예 2.6] tbjdbc - 접속해제 private void disconnect() throws SQLException { if (conn!= null) 제 2 장 tbjdbc 의사용 33
} conn.close(); conn 객체가존재하는경우, close 멤버함수를사용하여데이터베이스접속을해제할수있다. 34 Tibero RDBMS 애플리케이션개발자안내서
제 3 장트리거의사용 본장에서는트리거의기본개념과이를생성하는방법을설명한다. 3.1. 개요 트리거 (Trigger) 는스키마객체의일종으로, 데이터베이스가미리정해놓은특정조건이만족되거나어떤동작이수행되면자동으로실행되도록정의한동작이다. 예를들어데이터베이스에특정한이벤트가발생되거나사용자가설정한 DDL 문장이수행될때트리거가실행될수있다. 트리거의내용은 PSM으로이루어져있다. 트리거는이미정의된 PSM 객체를호출하여사용하거나트리거를생성할때이름없는블록을함께선언해주는방식을모두이용할수있다. 3.1.1. 트리거의구성요소 트리거는다음과같은세가지구성요소를갖춰야만생성할수있다. 트리거가실행될조건이되는문장이나이벤트 실행조건의제약 실행될내용 다음은 alarm_for_balance 라는트리거를생성하는예이다. CREATE OR REPLACE TRIGGER alarm_for_balance BEFORE INSERT OR UPDATE ON balance_tab... a... FOR EACH ROW WHEN (new.balance < 3000).. b... CALL alarm_for_balance_fn().. c... a 테이블 balance_tab의 balance 컬럼에로우가삽입되거나수정이발생했을때 b로이동한다. b 해당로우의값이 3000 이하인지를검사한다. c 검사한결과가맞으면 alarm_for_balance_fn 함수를호출하고, 함수에정의한동작이실행된다. 제 3 장트리거의사용 35
3.1.2. 트리거의타입 트리거의타입은다음과같이나눌수있다. 로우 (row) 및문장 (statement) 타입 로우 설명 테이블에 INSERT, UPDATE, DELETE 가발생하는로우마다트리거의내용이실 행되는타입이다. 이타입의트리거는각로우에연산이발생할때마다연산직전또는직후에트리 거가실행된다. 문장 로우의개수에상관없이문장단위로한번만실행되는타입이다. BEFORE 및 AFTER 타입 BEFORE AFTER 설명 조건문장이실행되기전에트리거의내용이실행되는타입이다. 조건문장이실행된후트리거의내용이실행되는타입이다. 트리거는두종류의타입중에서하나씩을각각가질수있다. 즉, BEFORE 로우 (BEFORE row), BEFORE 문장 (BEFORE statement), AFTER 로우 (AFTER row), AFTER 문장 (statement) 의타입으로생성할수 있다. 3.2. 트리거의생성 트리거를생성하는방법은다음과같다. CREATE [OR REPLACE] TRIGGER 트리거 _ 이름 {BEFORE AFTER} {INSERT UPDATE DELETE} ON 테이블 _ 이름 [FOR EACH ROW] WHEN ( 조건 _ 제약 ) {[ 선언부 ] BEGIN... END;} CALL 함수 _ 혹은 _ 프로시저 _ 이름 참고 트리거의문법에대한자세한내용은 "Tibero RDBMS SQL 참조안내서 " 를참고한다. 36 Tibero RDBMS 애플리케이션개발자안내서
다음은로우타입의트리거로, 테이블 DECK_TBL의 COUNT 컬럼에로우값이 1000을초과할때마다로그를기록하도록작성한예이다. [ 예 3.1] 트리거의생성 CREATE OR REPLACE TRIGGER Log_overflow AFTER UPDATE ON Deck_tbl FOR EACH ROW WHEN (new.count > 1000) BEGIN INSERT INTO Deck_log (Deck_id, Timestamp, New_count, Action) VALUES (:new.deck_no, SYSTIMESTAMP, :new.count, 'overflow'); END; CREATE 문장은 Tibero RDBMS 내부에서는 BEGIN END 사이의부분을 PSM 으로인식한다. 이문장 이컴파일되면 PSM 스키마객체가생성되고이를데이터베이스에저장한다. 만약컴파일에러가발생한 다면정적뷰를통해에러의내용을확인할수있다. 제 3 장트리거의사용 37
제 4 장 XA 의사용 본장에서는분산트랜잭션 (distributed transaction) 를처리하는데사용되는 XA 를설명한다. 4.1. 분산트랜잭션 하나의데이터베이스인스턴스내에서는한트랜잭션으로묶인여러개의 SQL 문장이모두커밋되거나롤백된다. 네트워크로연결된여러개의데이터베이스인스턴스가참여하는트랜잭션에서도마찬가지로각각다른데이터베이스인스턴스에서수행한 SQL 문장이모두동시에커밋되거나롤백될수있는방법이필요하다. 이렇게여러개의노드또는다른종류의데이터베이스가참여하는하나의트랜잭션을분산트랜잭션 (distributed transaction) 이라한다. 참고 분산트랜잭션에대한자세한내용은 "Tibero RDBMS 관리자안내서 " 를참고한다. 4.1.1. Two-phase commit Tibero RDBMS는 X/Open DTP(Distributed Transaction Processing) 규약의 XA를지원한다. XA는 Twophase commit를이용하여분산트랜잭션을처리한다. 분산환경에서트랜잭션의무결성을보장하기위해서사용하는커밋방법은 Two-phase commit이다. 보통두개이상의노드가특정트랜잭션을함께수행하고있다면, 일반적으로사용자의요청을받아트랜잭션을시작한노드가코디네이터가된다. TP-Monitor가있는시스템일경우에는 TP-Monitor가그역할을한다. 제 4 장 XA 의사용 39
다음은 Two-phase commit 의일반적인예를나타내는그림이다. [ 그림 4.1] Two-phase commit 의일반적인예 Two-phase commit mechanism은크게두단계로작업이이루어진다. 위예제를기준으로 Two-phase commit를설명하자면다음과같다. 1. First Phase ( 또는 prepare phase) 커밋을준비하는단계로다음의세부과정으로실행된다. 단계 send "prepare" reply "prepared" 설명각노드는코디네이터노드로부터커밋을준비하라는메시지를받는다. 각노드는메시지를받은후복구를위해로그등에서커밋이가능한지를검사한다. 또는필요에따라자체적으로롤백을한다. 만약커밋이가능하다면최종으로커밋한로그를제외한모든작업을수행한후, 커밋이준비되었다는메시지를코디네이터노드로전달한다. 2. Second Phase ( 또는 commit phase) 실제로커밋한기록을저장하는단계로 Second Phase 은다음의세부과정으로실행된다. 단계 send "commit" reply "committed" 설명코디네이터노드는모든노드에서커밋이되었다는메시지를전달받는다. 이를확인한후실제로커밋을실행하라는메시지를각노드에보낸다. 각노드는커밋을기록한후커밋이완료되었다는메시지를코디네이터노드로전달한다. 40 Tibero RDBMS 애플리케이션개발자안내서
4.1.2. In-doubt 트랜잭션 Two-phase commit mechanism에의해첫번째 prepare 메시지를받으면데이터베이스는분산트랜잭션에해당하는리소스를잠금을설정하거나로그를남김으로써커밋할준비를한다. 그런데 prepare까지마친상태에서네트워크의이상으로다음메시지 ( 커밋혹은롤백 ) 를받지못하는경우가발생할수있다. 이경우에데이터베이스는해당트랜잭션을커밋해야할지롤백해야할지판단할수없다. 따라서다음메시지가올때까지 prepare된리소스에잠금설정을한채로기다리게된다. 이렇게 prepare 는되었는데그다음메시지를받지못한채리소스만소유하고기다리고있는트랜잭션을 In-doubt 트랜잭션이라한다. 예를들어, First Phase에서코디네이터노드가커밋을준비하라는메시지를보냈음에도불구하고어떤특정노드의서버가다운되었거나네트워크상태가불안정하여그메시지를못받았거나또는메시지는받았지만커밋이준비되었다는답변을받지못했을때 In-doubt 트랜잭션이발생한다. 이러한경우코디네이터노드는다른모든노드의응답을받았어도한노드의응답을받지못했으므로, 이트랜잭션을 In-doubt 트랜잭션으로표시하고, 모든노드에 Second Phase의커밋명령을실행하라는메시지를보내는대신에롤백하라는메시지를보낸다. 예를들면다음그림과같다. [ 그림 4.2] In-doubt 트랜잭션이발생하는예 또한, 모든노드에서커밋이준비되었다는메시지를받아서확인했더라도그이후에코디네이터노드가보낸 Second Phase의커밋명령을실행하라는메시지를특정노드가받지못했거나, 그노드가커밋명령은잘수행하였으나커밋이완료되었다는응답을코디네이터노드에전달하지못했을수도있다. 이와같은경우도마찬가지로 In-doubt 트랜잭션으로분류된다. 트랜잭션은커밋이나롤백이확정되지않은채로데이터베이스리소스에대해잠금 (Lock) 이설정된상태즉정체 (pending) 상태가된다. 따라서이를해결하려면첫번째경우처럼코디네이터노드가자동으로전체트랜잭션을롤백해준다거나 DBA가이러한트랜잭션을추출하여자체적으로판단하여수동으로처리할수있다. 제 4 장 XA 의사용 41
이때 DBA 가 In-doubt 트랜잭션을추출하기위해정보를볼수있는테이블과뷰로는 VT_XA_BRANCH 와 DBA_2PC_PENDING 이있다. 참고 VT_XA_BRANCH는현재데이터베이스서버에서활동중인모든 XA 트랜잭션브랜치 (XA transaction branch) 의정보를실시간으로볼수있는테이블이다. 그리고 DBA_2PC_PENDING은현재정체되고있는 XA 트랜잭션브랜치의정보를보여주는뷰이다. 이에대한자세한내용은각각 "Tibero RDBMS 참조안내서 " 와 "Tibero RDBMS 관리자안내서 " 를참고한다. 4.2. XA API TP-Monitor를이용하여분산트랜잭션을수행하기위해서는 XA API를사용해야한다. Tibero RDBMS는 X/Open DTP 규약의 XA를지원하기때문에표준에맞는 XA 애플리케이션프로그램을작성할수있다. 4.2.1. XA 함수 Tibero RDBMS에서는 XA를지원하기위해다음과같은 XA 함수를제공한다. 단, 이함수는 C 프로그래밍언어용으로만제공된다. 다음은 XA 함수를나열한표이다. 함수 xa_open xa_close xa_start xa_end xa_rollback xa_prepare 설명리소스매니저 (Resource Manager) 에접속한다. 리소스매니저에서데이터베이스접속을해제한다. XID에새로운트랜잭션을시작하거나, 이미존재하는트랜잭션에현재프로세스를연결한다. XID에서현재프로세스를분리한다 XID의트랜잭션을롤백한다. XID에커밋을준비한다. Two-phase commit 의 First Phase 이다. xa_commit XID 에커밋을완료한다. Two-phase commit 의 Second Phase 이다. xa_recover xa_forget prepare 상태인트랜잭션의목록을검사하여커밋이나롤백을수행한다. XID 의트랜잭션이이미처리된경우로그기록을삭제한다. 42 Tibero RDBMS 애플리케이션개발자안내서
4.2.2. xa_open 함수의속성 다음은 xa_open 함수를호출하는데필요한속성이다. 이름 필수 작성예 설명 user O user=tibero 접속할사용자의이름이다. pwd O pwd=1234 접속할사용자의패스워드이다. sestm O sestm=10 시스템에의해중단 (abort) 되기전까지의트랜잭션의 inactive time limit 이다. 클라이언트로부터한요청에대한답변을전달한후 그다음요청이오기전까지대기하는시간이다. 그 이상의시간이지나면클라이언트측에서문제가있 다고판단하고해당 xtb 를롤백한다. db X db=sample 접속할데이터베이스의 DSN 이름 (tbdsn.tbr 파일내의 DSN 이름 ) 이다. LogDir X LogDir=home/db/tibero/log XA API 가에러, 트레이스메시지를저장할디렉터리 의이름이다. Loose_Coupling O Loose_Coupling=false loosely coupling flag 로 true/false 설정한다. 다른브랜치이지만동일한글로벌트랜잭션끼리같 은리소스를사용하는지여부를설정한다. loose coupling 이면 (1,0) 과 (1,2) 는서로다른내부 리소스를사용한다. 예를들어 TX 가해당된다. 이와 는반대로 tight coupling 이면두 xtb 는하나의 TX 를 서로잠금처리를설정해가며공유하여사용한다. seswt X seswt=30 XA_RETRY 가반환되기전까지데이터베이스서버 가트랜잭션을기다리는대기시간이다. flag 내에 TMNOWAIT 이설정되어있지않을경우에 는클라이언트의요청을데이터베이스가곧바로처 리해줄수없을때해당리소스를사용할수있을때 까지기다린후에클라이언트에답변을주게된다. 이때데이터베이스가 sesswt 로설정한시간까지답 변을줄수없는경우 XARETRY 를반환한다. 제 4 장 XA 의사용 43
4.2.3. XA 애플리케이션프로그래밍 일반적으로 C 프로그래밍언어에서 XA 애플리케이션프로그램을작성할때 ESQL을이용하여개발하는예가많다. 다음은 Tibero RDBMS에서제공하는 tbesql를이용하여 XA 애플리케이션프로그램을작성한예이다. #define XA_CONN_STR_TIGHT "TIBERO_XA:user=tibero, pwd=tmax," \ "db=sample, sestm=60" /* 동일한글로벌트랜잭션에서다른브랜치로 xa_start했을경우 * Tight-Coupling */ void test_xa_2branch_2pc_tight() { int rc; XID xid1; XID xid2; struct xa_switch_t *tbxa = &XA_SWITCH_NAME; char *conn_str = XA_CONN_STR_TIGHT; /* tightly coupled */ long gtrid = _GTRID_BASE; long bqual = 1; EXEC SQL BEGIN DECLARE SECTION; int cnt; EXEC SQL END DECLARE SECTION; /* xa_open */ tbxa->xa_open_entry (conn_str, 0, TMNOFLAGS); xid1.formatid = 1; xid1.gtrid_length = sizeof(gtrid); xid1.bqual_length = sizeof(bqual); memcpy(&xid1.data[0], >rid, sizeof(gtrid)); memcpy(&xid1.data[sizeof(gtrid)], &bqual, sizeof(bqual)); bqual = 2; xid2.formatid = 1; xid2.gtrid_length = sizeof(gtrid); xid2.bqual_length = sizeof(bqual); memcpy(&xid2.data[0], >rid, sizeof(gtrid)); memcpy(&xid2.data[sizeof(gtrid)], &bqual, sizeof(bqual)); EXEC SQL DELETE FROM PERSON; EXEC SQL COMMIT WORK; /* (1, 1) 시작 */ 44 Tibero RDBMS 애플리케이션개발자안내서
/* xa_start -- sql statements starts */ tbxa->xa_start_entry (&xid1, 0, TMNOFLAGS); EXEC SQL INSERT INTO PERSON VALUES ('1', 'LEE'); EXEC SQL INSERT INTO PERSON VALUES ('2', 'KIM'); /* xa_end -- */ tbxa->xa_end_entry (&xid1, 0, TMSUCCESS); /* (1, 2) 시작 */ /* xa_start -- sql statements starts */ tbxa->xa_start_entry (&xid2, 0, TMNOFLAGS); EXEC SQL INSERT INTO PERSON VALUES ('2', 'PARK'); EXEC SQL INSERT INTO PERSON VALUES ('3', 'JAKE'); EXEC SQL INSERT INTO PERSON VALUES ('4', 'KID'); EXEC SQL INSERT INTO PERSON VALUES ('5', 'CHANHO'); /* xa_end -- */ tbxa->xa_end_entry (&xid2, 0, TMSUCCESS); /* xa_prepare */ tbxa->xa_prepare_entry (&xid1, 0, TMNOFLAGS); /* Tightly-Coupled 가정 */ /* xa_prepare */ tbxa->xa_prepare_entry (&xid2, 0, TMNOFLAGS); /* xa_commit */ tbxa->xa_commit_entry (&xid1, 0, TMNOFLAGS); /* xa_commit */ tbxa->xa_commit_entry (&xid2, 0, TMNOFLAGS); EXEC SQL SELECT COUNT(*) into :cnt FROM PERSON; CuAssertIntEq(tc, cnt, 6); } /* xa_close */ tbxa->xa_close_entry ("", 0, TMNOFLAGS); return; /* 같은 Global Trasaction의다른 Branch로 xa_start했을경우 * Loose-Coupling */ void test_xa_2branch_2pc_loose(cutest *tc) { int rc; XID xid1; XID xid2; 제 4 장 XA 의사용 45
struct xa_switch_t *tbxa = &XA_SWITCH_NAME; char *conn_str = XA_CONN_STR_LOOSE; long gtrid = _GTRID_BASE; long bqual = 1; EXEC SQL BEGIN DECLARE SECTION; int cnt; EXEC SQL END DECLARE SECTION; /* xa_open */ tbxa->xa_open_entry (conn_str, 0, TMNOFLAGS); xid1.formatid = 1; xid1.gtrid_length = sizeof(gtrid); xid1.bqual_length = sizeof(bqual); memcpy(&xid1.data[0], >rid, sizeof(gtrid)); memcpy(&xid1.data[sizeof(gtrid)], &bqual, sizeof(bqual)); bqual = 2; xid2.formatid = 1; xid2.gtrid_length = sizeof(gtrid); xid2.bqual_length = sizeof(bqual); memcpy(&xid2.data[0], >rid, sizeof(gtrid)); memcpy(&xid2.data[sizeof(gtrid)], &bqual, sizeof(bqual)); EXEC SQL DELETE FROM PERSON; EXEC SQL COMMIT WORK; /* (1, 1) 시작 */ /* xa_start -- sql statements starts */ tbxa->xa_start_entry (&xid1, 0, TMNOFLAGS); EXEC SQL INSERT INTO PERSON VALUES ('1', 'LEE'); EXEC SQL INSERT INTO PERSON VALUES ('2', 'KIM'); /* xa_end -- */ tbxa->xa_end_entry (&xid1, 0, TMSUCCESS); /* (1, 2) 시작 */ /* xa_start -- sql statements starts */ tbxa->xa_start_entry (&xid2, 0, TMNOFLAGS); EXEC SQL INSERT INTO PERSON VALUES ('2', 'PARK'); EXEC SQL INSERT INTO PERSON VALUES ('3', 'JAKE'); EXEC SQL INSERT INTO PERSON VALUES ('4', 'KID'); EXEC SQL INSERT INTO PERSON VALUES ('5', 'CHANHO'); /* xa_end -- */ tbxa->xa_end_entry (&xid2, 0, TMSUCCESS); 46 Tibero RDBMS 애플리케이션개발자안내서
/* xa_prepare */ tbxa->xa_prepare_entry (&xid1, 0, TMNOFLAGS); /* Loosely-Coupled 가정 */ /* xa_prepare */ tbxa->xa_prepare_entry (&xid2, 0, TMNOFLAGS); /* xa_commit */ tbxa->xa_commit_entry (&xid1, 0, TMNOFLAGS); /* xa_commit */ tbxa->xa_commit_entry (&xid2, 0, TMNOFLAGS); EXEC SQL SELECT COUNT(*) into :cnt FROM PERSON; CuAssertIntEq(tc, cnt, 6); } /* xa_close */ tbxa->xa_close_entry ("", 0, TMNOFLAGS); return; 4.3. JDBC 에서의 XA 지원 본절에서는 XA(Extended Architecture) 에서지원하는인터페이스와이를이용하여작성한프로그램에 대해기술한다. 4.3.1. XA 인터페이스 Tibero RDBMS 에서지원하는 JDBC 의 XA 인터페이스는다음과같다. XA Datasource Interface XA Connection Interface XA Exception Interface XA XID Interface 다음은 Tibero RDBMS 에서구현된 XA 인터페이스의목록이다. 표준 XA 인터페이스 (JDK 1.3) javax.sql.xadatasource Tibero RDBMS 의 XA 인터페이스 com.tmax.tibero.jdbc.ext.tbxadatasource 제 4 장 XA 의사용 47
표준 XA 인터페이스 (JDK 1.3) javax.sql.xaconnection javax.transaction.xa.xaexception javax.transaction.xa.xid Tibero RDBMS의 XA 인터페이스 com.tmax.tibero.jdbc.ext.tbxaconnection com.tmax.tibero.jdbc.ext.tbxaexception com.tmax.tibero.jdbc.ext.tbxid 4.3.2. XA 인터페이스프로그래밍 다음은 tbjdbc 환경에서 XA 인터페이스를이용하여프로그래밍한예이다. package test.com.tmax.tibero.cases; import com.tmax.tibero.jdbc.ext.*; import test.com.tmax.tibero.abstractbase; import javax.sql.xaconnection; import javax.transaction.xa.xaresource; import java.sql.*; public class TestXATwoBranch extends AbstractBase{ int formatid = 1; int row_count = 0; int pre1, pre2 = 0; byte[] gtid1 = new byte[1]; byte[] bq1 = new byte[1]; byte[] gtid2 = new byte[1]; byte[] bq2 = new byte[1]; public TestXATwoBranch (String name) { super(name); } /* Tightly Coupled 일때 */ public void test_xa_2branch_2pc_tight () throws Exception { debug("test_xa_2branch_2pc_tight " + this._getclassname()); create_table_for_xa(); gtid1[0] = (byte)1; bq1[0] = (byte)1; gtid2[0] = (byte)1; bq2[0] = (byte)2; TbXADataSource xads1 = new TbXADataSource(); xads1.seturl(getxaurl()); xads1.setuser(getxauser()); xads1.setpassword(getxapasswd()); 48 Tibero RDBMS 애플리케이션개발자안내서
TbXADataSource xads2 = new TbXADataSource(); xads2.seturl(getxaurl()); xads2.setuser(getxauser()); xads2.setpassword(getxapasswd()); XAConnection xacon1 = xads1.getxaconnection(); XAConnection xacon2 = xads2.getxaconnection(); Connection conn1 = xacon1.getconnection(); Connection conn2 = xacon2.getconnection(); XAResource xars1 = xacon1.getxaresource(); XAResource xars2 = xacon2.getxaresource(); /* XID (1.1) 생성 */ TbXid xid1 = new TbXid(formatID, gtid1,bq1 ); /* XID (1.2) 생성 */ TbXid xid2 = new TbXid(formatID, gtid2, bq2); try { /* (1.1) 시작 */ xars1.start(xid1, XAResource.TMNOFLAGS); PreparedStatement pstmt1; pstmt1 = conn1.preparestatement( "insert into author values (?,?)"); pstmt1.setint(1, 1); pstmt1.setstring(2, "FOSCHIA"); pstmt1.executeupdate(); pstmt1.setint(1,2); pstmt1.setstring(2, "AGNOS"); pstmt1.executeupdate(); /* (1.1) 종료 */ xars1.end(xid1, XAResource.TMSUCCESS); /* (1.2) 시작 */ xars2.start(xid2, XAResource.TMNOFLAGS); PreparedStatement pstmt2; pstmt2 = conn2.preparestatement( "insert into author values (?,?)"); pstmt2.setint(1, 3); pstmt2.setstring(2, "JELLA"); pstmt2.executeupdate(); 제 4 장 XA 의사용 49
pstmt2.setint(1,4); pstmt2.setstring(2, "THIPHILO"); pstmt2.executeupdate(); /* (1.2) 종료 */ xars2.end(xid2, XAResource.TMSUCCESS); /* (1,1) prepare */ pre1= xars1.prepare(xid1); assertequals(pre1, XAResource.XA_RDONLY); /* (1,2) prepare */ pre2 = xars2.prepare(xid2); assertequals(pre2, XAResource.XA_OK); /* (1.1) commit */ try { xars1.commit(xid1, false); } catch(tbxaexception e) {} /* (1.2) commit */ try { xars2.commit(xid2, false); } catch(tbxaexception e) {} Statement stmt1 = conn1.createstatement(); ResultSet rs1 = stmt1.executequery("select * from author"); while (rs1.next()) row_count ++; assertequals(4, row_count); rs1.close(); rs1 = null; stmt1.close(); stmt1 = null; pstmt1.close(); conn1.close(); xacon1.close(); pstmt2.close(); conn2.close(); xacon2.close(); } pstmt1= null; conn1= null; xacon1=null; pstmt2= null; conn2= null; xacon2=null; } catch (TbXAException e) {} /* Loosely Coupled 일때 */ 50 Tibero RDBMS 애플리케이션개발자안내서
public void test_xa_2branch_2pc_loose () throws Exception { debug("test_xa_2branch_2pc_loose " + this._getclassname()); create_table_for_xa(); gtid1[0] = (byte)1; bq1[0] = (byte)1; gtid2[0] = (byte)1; bq2[0] = (byte)2; TbXADataSource xads1 = new TbXADataSource(); xads1.seturl(getxaurl()); xads1.setuser(getxauser()); xads1.setpassword(getxapasswd()); TbXADataSource xads2 = new TbXADataSource(); xads2.seturl(getxaurl()); xads2.setuser(getxauser()); xads2.setpassword(getxapasswd()); XAConnection xacon1 = xads1.getxaconnection(); XAConnection xacon2 = xads2.getxaconnection(); Connection conn1 = xacon1.getconnection(); Connection conn2 = xacon2.getconnection(); XAResource xars1 = xacon1.getxaresource(); XAResource xars2 = xacon2.getxaresource(); TbXid xid1 = new TbXid(formatID, gtid1,bq1 ); TbXid xid2 = new TbXid(formatID, gtid2, bq2); try { xars1.start(xid1, TbXAResource.TBRTRANSLOOSE); PreparedStatement pstmt1; pstmt1 = conn1.preparestatement( "insert into author values (?,?)"); pstmt1.setint(1, 1); pstmt1.setstring(2, "FOSCHIA"); pstmt1.executeupdate(); pstmt1.setint(1,2); pstmt1.setstring(2, "AGNOS"); pstmt1.executeupdate(); 제 4 장 XA 의사용 51
xars1.end(xid1, XAResource.TMSUCCESS); xars2.start(xid2, TbXAResource.TBRTRANSLOOSE); PreparedStatement pstmt2; pstmt2 = conn2.preparestatement( "insert into author values (?,?)"); pstmt2.setint(1, 3); pstmt2.setstring(2, "JELLA"); pstmt2.executeupdate(); pstmt2.setint(1,4); pstmt2.setstring(2, "THIPHILO"); pstmt2.executeupdate(); xars2.end(xid2, XAResource.TMSUCCESS); pre1= xars1.prepare(xid1); assertequals(pre1, XAResource.XA_OK); pre2 = xars2.prepare(xid2); assertequals(pre2, XAResource.XA_OK); xars1.commit(xid1, false); xars2.commit(xid2, false); Statement stmt1 = conn1.createstatement(); ResultSet rs1 = stmt1.executequery("select * from author"); while (rs1.next()) row_count ++; assertequals(4, row_count); rs1.close(); rs1 = null; stmt1.close(); stmt1 = null; pstmt1.close(); conn1.close(); xacon1.close(); pstmt2.close(); conn2.close(); xacon2.close(); } } pstmt1= null; conn1= null; xacon1=null; pstmt2= null; conn2= null; xacon2=null; } catch (TbXAException e) {} 52 Tibero RDBMS 애플리케이션개발자안내서
4.4. TP-Monitor 와 Tibero 연동 TP-Monitor(Transaction Processing Monitor) 는각종프로토콜에서동작하는세션과시스템및데이터베이스사이의최소처리단위인트랜잭션을감시하여일관성있게보관및유지하는역할을하는트랜잭션관리미들웨어이다. 본절에서는대표적인상용 TP-Monitor인 Tmax와 Tuxedo를 Tibero RDBMS와연동하는예제를제시한다. 4.4.1. Tmax 와 Tibero 연동 Tmax는 Transaction Maximization의약어로트랜잭션처리극대화를의미한다. Tmax는시스템의분산환경에서이기종컴퓨터간의트랜잭션처리를완벽히보장하면서부하를분산시키고에러발생시적절한조치를담당하는 TP-Monitor이다. 트랜잭션의특성을지원하면서사용자에게는최적의개발환경을제공하고, 클라이언트 / 서버환경에서최적의솔루션을제공하며, 성능개선은물론모든장애에완벽하게대처한다. Tmax는분산트랜잭션프로세싱의국제표준인 X/Open DTP(Distributed Transaction Processing) 모델을준수하고국제표준기구인 OSI(Open Systems Interconnection group) 의 DTP 서비스에대한기능적분산과기능구성요소간 API 및시스템인터페이스정의에따라개발되었다. 또한, 분산환경에서이기종간의투명한업무처리및 OLTP(On-Line Transaction Processing) 를지원하고트랜잭션처리의 ACID(Atomic, Consistent, Isolated, Durable: transaction properties) 특성을만족하게한다. 아래에서소개할 Tmax 와 Tibero 연동예제프로그램을테스트해보기위해서는 Tmax와 Tibero가정상적으로설치되어있어야한다. 참고 1. 연동할 Tmax와 Tibero 가다른머신에설치된경우, Tmax가설치된머신에서 Tibero 클라이언트를따로설치하여 Tibero 서버에정상적으로접속할수있는환경이구축되어야한다. 2. Tmax 설치및관리에대한자세한내용은 "Tmax Installation Guide" 나 "Tmax Administration Guide" 를참조한다. Tibero 로설치및관리에관한자세한내용은 "Tibero RDBMS 설치안내서 " 와 "Tibero RDBMS 관리자안내서 " 를참고한다.. 여기서소개하는예제프로그램은 Tmax를설치할때인스톨러가기본으로제공하는것이다. 클라이언트가 Tmax 서버를통하여 Tibero DB를접속하여특정테이블의데이터를조회, 추가, 변경, 삭제하는작업을한다. 테스트환경과프로그램에사용된각종파일들은다음과같다. 테스트환경 파일 운영체제 쉘 설명 Ubuntu Linux 2.6.32-24-server x86-64 bash 제 4 장 XA 의사용 53
파일 $TMAXDIR 설명 Tmax 설치디렉터리 프로그램파일 파일 sample.m tms_tbr.mk tbrtest.c tbrtest.h Makefile.tbr compile tbr_main.c Makefile.c compile 설명 Tmax 환경설정파일 ($TMAXDIR/config) Tibero용 TMS makefile($tmaxdir/sample/server) 서버프로그램 tbesql/c 파일 ($TMAXDIR/sample/server) 서버프로그램헤더파일 ($TMAXDIR/sample/server) 서버프로그램 makefile ($TMAXDIR/sample/server) 서버프로그램빌드스크립트 ($TMAXDIR/sample/server) 클라이언트프로그램파일 ($TMAXDIR/sample/client) 클라이언트프로그램 makefile ($TMAXDIR/sample/client) 클라이언트프로그램빌드스크립트 ($TMAXDIR/sample/client) 다음에제시된순서대로따르면 Tmax와 Tibero가연동하는것을확인할수있다. 1. Tmax 기본환경설정 2. TMS 컴파일 3. TMS 컴파일 4. 서버프로그램컴파일 5. 클라이언트프로그램컴파일 6. DB 테이블생성 7. 예제프로그램실행 Tmax 기본환경설정 Tmax 시스템환경파일설정 $TMAXDIR/config 디렉터리에있는 sample.m은 Tmax를기동시킬때필요한각종정보들이들어있는 Tmax 시스템환경파일이다. ASCII 파일형태로작성하며, cfl 유틸리티로컴파일하여이진파일을생성한다. 생성된이진파일은 Tmax 기동및종료할때참조된다. Tibero 서버와연동하는서비스를활성화시키기위하여 sample.m 환경파일의 SVRGROUP 절, SERVER 절, SERVICE 절항목을아래와같이수정한다. 54 Tibero RDBMS 애플리케이션개발자안내서
### tms for Tibero ### svg4 NODENAME = "integrity", DBNAME = TIBERO, OPENINFO = "TIBERO_XA:user=tibero,pwd=tmax,sestm=60,db=tibero", TMSNAME = tms_tbr ### server for Tibero sample program ### tbrtest SVGNAME = svg4 ### services for tbrtest ### TBRINS SVRNAME = tbrtest TBRSEL SVRNAME = tbrtest TBRUPT SVRNAME = tbrtest TBRDEL SVRNAME = tbrtest SVRGROUP 절의 NODENAME은 Tmax 설치시에 hostname 값으로자동설정된다. DB 벤더를구분하기위한 DBNAME은 TIBERO로설정되어있다. OPENINFO는 XA 모드설정을위한 TIBERO_XA가앞쪽에쓰여있고그뒤에 4.2.2. xa_open 함수의속성 이나열되어있다.TMSNAME에는 XA를담당할모듈이름이설정되어있다. SERVER 절에는예제서버프로그램의이름인 tbrtest와예제서버프로그램이제공하는서비스 4가지가설정되어있다. 참고 1. 현재 Tibero에서는 xa_open 함수의속성중에 LogDir 속성을지원하지않고있다. TMSNAME에는 XA를담당할모듈이름이설정되어있다. 2. Tmax 시스템환경파일설정에대한자세한내용은 "Tmax Administration Guide" 를참조한다. Tmax 시스템환경파일컴파일 수정한 sample.m 파일을아래와같은명령으로컴파일한다. cfl -i sample.m 성공적으로컴파일된후에는다음과같은메시지가출력된다. CFL is done successfully for node(<nodename>) 서비스테이블생성서비스테이블은각각의 Tmax 시스템내서버프로세스가생성될때필요한파일로서각각의프로세스들이어떤서비스를처리하는지에대한정보가담겨있다. 아래와같은명령으로서비스테이블을생성한다. gst 성공적으로처리되면다음과같은메시지가출력된다. 제 4 장 XA 의사용 55
SVC tables are successfully generated GST is successfully done 구조체정의이진파일및필드키정의이진파일생성 서버나클라언트프로그램내에서구조체나필드키를쓰는경우이와관련된이진파일을생성해주어 야한다. 하지만이예제프로그램에서는구조체나필드키를사용하지않으므로그과정을생략한다. TMS 컴파일 TMS(Transaction Management Server) 는 Tmax 시스템의구성요소로서데이터베이스관리및분산트랜잭션처리를담당하는프로세스이다. Tibero용 TMS를컴파일하기전에 Tibero 관련환경변수 TB_HOME, TB_SID, LD_LIBRARY_PATH, PATH 등이제대로설정되었는지확인한다. 확인한다음아래와같이 $TMAXDIR/sample/server 디렉터리로이동하여 Tibero용 TMS makefile을이용하여 TMS를컴파일한다. cd $TMAXDIR/sample/server make f tms_tbr.mk all 서버프로그램컴파일 $TMAXDIR/sample/server 디렉터리로이동하여실제적으로서비스를제공하는서버프로그램을빌드스 크립트를이용하여컴파일한다. cd $TMAXDIR/sample/server./compile tbc tbrtest 클라이언트프로그램컴파일 $TMAXDIR/sample/client 디렉터리로이동하여서비스를요청하는클라이언트프로그램을빌드스크립 트를이용하여컴파일한다. cd $TMAXDIR/sample/client./compile c tbr_main DB 테이블생성 Tibero 서버에 tibero/tmax 계정으로접속하여아래와같은 emp 테이블을생성한다. tbsql tibero/tmax create table emp ( empno number, 56 Tibero RDBMS 애플리케이션개발자안내서
); ename char(16), job char(16), hiredate char(16), sal number 예제프로그램실행 Tmax 시스템기동 다음과명령으로 Tmax 를기동한다. tmboot 성공적으로기동되면다음과같은메시지가출력된다. TMBOOT for node(<nodename>) is starting: Welcome to Tmax demo system: it will expire 2012/3/11 Today: 2012/1/13 TMBOOT: TMM is starting: Fri Jan 13 14:18:31 2012 TMBOOT: CLL is starting: Fri Jan 13 14:18:31 2012 TMBOOT: CLH is starting: Fri Jan 13 14:18:31 2012 (I) CLH9991 Current Tmax Configuration: Number of client handler(minclh) = 1 Supported maximum user per node = 680 Supported maximum user per handler = 680 [CLH0125] TMBOOT: TLM(tlm) is starting: Fri Jan 13 14:18:31 2012 TMBOOT: TMS(tms_tbr) is starting: Fri Jan 13 14:18:31 2012 (I) TMS0211 General Infomation : transaction recovery will be started [TMS0221] (I) TMS0211 General Infomation : transaction recovery was completed [TMS0222] TMBOOT: TMS(tms_tbr) is starting: Fri Jan 13 14:18:31 2012 TMBOOT: SVR(tbrtest) is starting: Fri Jan 13 14:18:31 2012 클라이언트프로그램실행 클라이언트프로그램의명령옵션은다음과같다. Usage:./tbr_main empno loop_cnt ins_flag upt_flag del_flag flag : 1 0 원하는옵션을선택하여수행시키면아래와같은결과가출력된다../tbr_main 12 3 1 0 0 LOOP COUNT = 1 >> INSERT : COMMIT TEST [./tbr_main] [[TBRINS] emp Insert Success] [./tbr_main] [[TBRSEL] emp Select Success [1]] 제 4 장 XA 의사용 57
LOOP COUNT = 2 >> INSERT : COMMIT TEST [./tbr_main] [[TBRINS] emp Insert Success] [./tbr_main] [[TBRSEL] emp Select Success [2]] LOOP COUNT = 3 >> INSERT : COMMIT TEST [./tbr_main] [[TBRINS] emp Insert Success] [./tbr_main] [[TBRSEL] emp Select Success [3]] 4.4.2. Tuxedo 와 Tibero 연동 Tuxedo는분산트랜잭션처리를위한플랫폼으로서, C, C++ 및 COBOL로작성된소프트웨어를위한개방형의분산시스템을토대로메인프레임급확장성및성능을제공하며, 메인스트림하드웨어를토대로메인프레임애플리케이션을 리호스팅 할수있는플랫폼이다. Tuxedo는비용효과적인신뢰성과초당수십만건의트랜잭션을지원할수있는탁월한확장성을제공하는것은물론, SOA와같은혁신적아키텍처의일부로서기존 IT 자산의수명을연장함으로써투자보호의이점을제공한다. Oracle Tuxedo는 Oracle Fusion Middleware의전략적트랜잭션처리제품이다아래에서소개할 Tuxedo 와 Tibero 연동예제프로그램을테스트해보기위해서는 Tuxedo와 Tibero가정상적으로설치되어있어야한다. 참고 1. 연동할 Tmax와 Tibero 가다른머신에설치된경우, Tmax가설치된머신에서 Tibero 클라이언트를따로설치하여 Tibero 서버에정상적으로접속할수있는환경이구축되어야한다. 2. Tuxedo 설치및관리에대한자세한내용은 "Tuxedo Documenation" 참조한다. Tibero 로설치및관리에관한자세한내용은 "Tibero RDBMS 설치안내서 " 와 "Tibero RDBMS 관리자안내서 " 를참고한다. 여기서소개하는예제프로그램은클라이언트가 Tuxedo 서버를통하여 Tibero DB를접속하여특정테이블의데이터를조회, 추가하는작업을한다. 테스트환경과프로그램에사용된각종파일들은다음과같다. 편의상테스트서버는 tux_machine이라는호스트네임을가지고있으며, Tibero와 Tuxedo는각각 path/to/tibero와 /path/to/tuxedo에설치되어있다고가정한다. 그리고예제프로그램파일들이작업디렉터리 /path/to/example에있다고가정한다. 테스트환경 구분 운영체제 호스트네임 설명 AIX tux_machine 58 Tibero RDBMS 애플리케이션개발자안내서
구분쉘 Tibero 설치홈디렉터리 Tuxedo 설치홈디렉터리예제프로그램홈디렉터리 설명 bash /path/to/tibero /path/to/tuxedo /path/to/example 프로그램파일 파일 tb_tux.env tb_tux.conf.m tmax32.fld trans_fml32.tbc builds.sh insert.c select.c buildc.sh create_table.sql run.sh 설명시스템환경변수설정파일 Tuxedo 환경설정파일필드테이블파일서버프로그램 tbesql/c 파일서버프로그램빌드스크립트 INSERT 클라이언트프로그램파일 SELECT 클라이언트프로그램파일클라이언트프로그램빌드스크립트테스트를위한 DB 테이블생성파일 Tuxedo 시스템기동스크립트 참고 본절에서설명하고있는기본프로그램의전체소스코드는 Appendix B. Tibero 와 Tuxedo 연동예 제프로그램소스코드 를참고한다. 다음에제시된순서대로따르면 Tuxedo와 Tibero의연동하는것을확인할수있다. 운영체제나시스템환경에따라서예제파일을수정하여테스트해야한다. 1. 시스템환경변수설정 2. Tuxedo 기본환경설정 3. TMS 컴파일 4. 서버프로그램컴파일 5. 클라이언트프로그램컴파일 6. DB 테이블생성 7. 예제프로그램실행 제 4 장 XA 의사용 59
시스템환경변수설정 Tibero 와 Tuxedo 연동테스트를하기위해필요한시스템환경변수설정은아래와같다. Tibero 를위한기본환경변수설정 export TB_HOME=/path/to/tibero export TB_SID=tibero export PATH=$TB_HOME/bin:$TB_HOME/client/bin:$TB_HOME/scripts:$PATH export LD_LIBRARY_PATH=$TB_HOME/client/lib:$TB_HOME/lib:$LD_LIBRARY_PATH export LIBPATH=$TB_HOME/client/lib:$TB_HOME/lib:$LIBPATH Tuxedo 를위한기본환경변수설정 export TUXDIR=/path/to/tuxedo export JAVA_HOME=$TUXDIR/jre export JVMLIBS=$JAVA_HOME/lib/amd64/server:$JAVA_HOME/jre/bin export PATH=$TUXDIR/bin:$JAVA_HOME/bin:$PATH export COBCPY=:$TUXDIR/cobinclude; export COBCPY export COBOPT="-C ANS85 -C ALIGN=8 -C NOIBMCOMP -C TRUNC=ANSI -C OSEXT=cbl" export SHLIB_PATH=$TUXDIR/lib:$JVMLIBS:$SHLIB_PATH export LIBPATH=$TUXDIR/lib:$JVMLIBS:$LIBPATH export LD_LIBRARY_PATH=$TUXDIR/lib:$JVMLIBS:$LD_LIBRARY_PATH export WEBJAVADIR=$TUXDIR/udataobj/webgui/java Tuxedo 를위한추가환경변수설정 연동테스트를위해서추가설정해주어야할환경변수들로서상황에맞게설정해준다. export TUXCONFIG=/path/to/tuxedo/tuxconf export FLDTBLDIR32=/path/to/tuxedo export FIELDTBLS32=tmax32.fld export TLOGDEVICE=/path/to/tuxedo/TLOG export ULOGPFX=/path/to/tuxedo/ULOG Tuxedo 기본환경설정 Tuxedo 시스템환경파일설정 tb_tux.conf.m은 Tuxedo를기동시킬때필요한각종정보들이들어있는 Tuxedo 시스템환경파일이다. ASCII 파일형태로작성하며, tmloadcf 유틸리티로컴파일하여이진파일을생성한다. 생성된이진파일은 Tuxedo 기동및종료할때참조된다. Tibero 서버와연동하는서비스를활성화시키기위하여 tb_tux.conf.m 환경파일의 RESOURCES 절, MACHINES 절, GROUPS 절, SERVERS 절, SERVICES 절항목을아래와같이설정하였다. 60 Tibero RDBMS 애플리케이션개발자안내서
*RESOURCES IPCKEY 68300 DOMAINID tbrdomain MASTER tbrtest MAXACCESSERS 10 MAXSERVERS 5 MAXSERVICES 10 MODEL SHM LDBAL N *MACHINES DEFAULT: TUXDIR="path/to/tuxedo" APPDIR="path/to/example" TUXCONFIG="path/to/example/tuxconf" tux_machine LMID=tbrtest *GROUPS TBXA LMID=tbrtest GRPNO=1 TMSNAME=tms_tibero OPENINFO="TIBERO_XA:TIBERO_XA:user=sys,pwd=tibero,sestm=60,db=tibero" *SERVERS DEFAULT: CLOPT="-A -r" trans_fml32 SRVGRP=TBXA SRVID=1 *SERVICES SELECT_FML32 INSERT_FML32 ~ RESOURCES 절과 MACHINE 절은일반적인 Tuxedo 시스템환경파일설정처럼한다. MACHINE 절의 tux_machine은서버의호스트네임이므로테스트환경에따라다르게설정해주야한다. LMID 와 MASTER는임의로 tbrtest 라고정하였고, DOMAINID로임의로 tbrdomain 이라고정하였으로원하는대로설정해주면된다. GROUPS 절도일반적인 Tuxedo 시스템환경파일설정처럼한다. TMSNAME에는 Tibero 서버와 XA 통신을담당할모듈의이름을설정한다. OPENINFO는 XA 모드설정을위한 TIBERO_XA:TIBERO_XA: 를앞쪽에쓰고그뒤에 4.2.2. xa_open 함수의속성 이나열되어야한다. SERVERS 절에는예제서버프로그램인 trans_fml32가설정되어있다. SERVICE 절에는예제서버프로그램이제공하는서비스인 SELECT_FML32, INSERT_FML32가설정되어있다. 제 4 장 XA 의사용 61
참고 1. 현재 Tibero 에서는 xa_open 함수의속성중에 LogDir 속성을지원하지않고있다. 2. Tuxedo 시스템환경파일설정에대한자세한설명은 "Tuxedo Documentation" 를참조한다. Tuxedo 시스템환경파일컴파일파일을아래와같은명령으로컴파일한다. tmloadcf -y tb_tux.conf.m 필드테이블파일을헤더파일로변환한다. 서버나클라언트프로그램간에데이터를주고받을때공용자료구조체정의해서쓴다. 이번연동테스트에서는 FML(Field Manipulation Language) 을이용하여아래같은필드테이블파일 tmax32.fld 을새로정의해서쓴다. #name number type flag comment OUTPUT 302 string 0 - EMPNO 901 long 0 - ENAME 902 string 0 - JOB 903 string 0 - MGR 904 long 0 - SAL 905 float 0 - COMM 906 float 0 - DEPTNO 907 long 0 - 이필드테이블파일 tmax32.fld로부터헤더파일을생성하는방법은다음과같다. mkfldhdr32 tmax32.fld 이결과 tmax32.fld.h 이라는헤더파일이생성되며, 예제클라이언트프로그램과서버프로그램에서가 져다쓴다. 그밖의다른구조체를정의하여파일을만드는방법은 "Tuxedo Documentation" 을참조한 다. TMS 컴파일 다음아래와같은명령어를이용하여 Tibero 용 TMS 를컴파일한다. buildtms -o $TUXDIR/bin/tms_tibero -v -r TIBERO_XA 62 Tibero RDBMS 애플리케이션개발자안내서
서버프로그램컴파일 실제적으로서비스를제공하는서버프로그램을아래와같은빌드스크립트 builds.sh 를이용하여컴파일 한다. #### transaction server precompile #### PRECOMP=$TB_HOME/client/bin/tbpc PRECOMPFLAGS="UNSAFE_NULL=YES" LIB=$TB_HOME/client/lib INC=$TB_HOME/client/include CFLAGS="-ltbcli -ltbxa -lm -lrt -lpthread -ltbertl -g " CC=gcc rm -f trans_fml32.c $PRECOMP INCLUDE=$TUXDIR/include UNSAFE_NULL=YES INCLUDE=$INC $PRECOMPFLAGS ONAME=trans_fml32 #### transaction server build #### buildserver -o trans_fml32 -v -f trans_fml32.c -s INSERT_FML32,SELECT_FML32 -r TIBERO_XA 참고 프리컴파일옵션에대한자세한설명은 "Tibero RDBMS tbesql/c 안내서 " 를참조한다. 클라이언트프로그램컴파일 insert 와 select 서비스를요청하는클라이언트프로그램을아래와같은빌드스크립트 buildc.sh 를이용하 여컴파일한다. buildclient -o insert -v -f insert.c buildclient -o select -v -f select.c DB 테이블생성 Tibero 서버에 tibero/tmax 계정으로접속하여아래와같은 emp 테이블을생성한다. tbsql tibero/tmax drop table emp; CREATE TABLE emp ( empno ename job mgr hiredate sal NUMBER, VARCHAR2(10), VARCHAR2(9), NUMBER(4), DATE, NUMBER(7,2), 제 4 장 XA 의사용 63
); comm deptno NUMBER(7,2), NUMBER(2) 예제프로그램실행 Tuxedo 시스템기동 다음명령으로기동한다. tmboot -y 성공적으로기동되면다음과같은메시지가출력된다. Booting all admin and server processes in /path/to/example/tuxconf INFO: Oracle Tuxedo, Version 10.3.0.0, 64-bit, Patch Level (none) Booting admin processes... exec BBL -A : process id=3457104... Started. Booting server processes... exec tms_tibero -A : process id=4046910... Started. exec tms_tibero -A : process id=9265576... Started. exec tms_tibero -A : process id=1863802... Started. exec trans_fml32 -A -r : process id=3719284... Started. 5 processes started. 클라이언트프로그램실행 emp 테이블에 Empyee 정보를추가하고조회하는클라이언트프로그램은다음과같이실행시켜보자../insert ****************************************** Employee Number : 1 Employee Name : Kim Employee Job : Manager 64 Tibero RDBMS 애플리케이션개발자안내서
****************************************** insert 프로그램을실행시키고 Employee Number, Employ Name, Employ Job 를위와같이입력하면 Tuxedo 서버프로그램을통하여 Tibero 서버의 emp 테이블에레코드가추가된다../select ****************************************** Employee Number : 1 ****************************************** EMPNO: 1 ENAME: Kim JOB: Manager select 프로그램을실행시키고 Employee Number를위와같이입력하면 Tuxedo 서버프로그램을통하여 Tibero서버의 emp 테이블로부터해당레코드정보를가져와서출력한다. 제 4 장 XA 의사용 65
Appendix A. tbjdbc 예제프로그램소스코드 A.1. JdbcTest.class 다음은 tbjdbc 를이용하여 JdbcTest 클래스파일을작성한프로그램소스코드이다. import java.sql.callablestatement; import java.sql.connection; import java.sql.drivermanager; import java.sql.preparedstatement; import java.sql.resultset; import java.sql.sqlexception; import java.sql.statement; import java.sql.types; public class JdbcTest { Connection conn; public static void main(string[] args) throws Exception { JdbcTest test = new JdbcTest(); } test.connect(); test.executestatement(); test.executepreparedstatement(); test.executecallablestatement(); test.disconnect(); private void connect() throws SQLException, ClassNotFoundException { Class.forName("com.tmax.tibero.jdbc.TbDriver"); conn = DriverManager.getConnection( "jdbc:tibero:thin:@localhost:6666:tibero", "tibero", "tmax"); if (conn == null) { System.out.println("connection failure!"); System.exit(-1); Appendix A. tbjdbc 예제프로그램소스코드 67
} } System.out.println("Connection success!"); private void executestatement() throws SQLException { String droptable = "drop table emp"; String createtable = "create table emp (id number, "+ " name varchar(20), salary number)"; String InsertTable = "insert into emp values(1000, 'Park', 5000)"; Statement stmt = conn.createstatement(); try { stmt.executeupdate(droptable); } catch(sqlexception e) { // if there is not the table } stmt.executeupdate(createtable); stmt.executeupdate(inserttable); } stmt.close(); private void executepreparedstatement() throws SQLException { PreparedStatement pstmt = conn.preparestatement("select name from emp where id =?"); pstmt.setstring(1, "1000"); ResultSet rs = pstmt.executequery(); } while (rs.next()) { System.out.println(rs.getString(1)); } pstmt.close(); private void executecallablestatement() throws SQLException { String callsql = " CREATE PROCEDURE testproc "+ " (ID_VAL IN NUMBER, SAL_VAL IN OUT NUMBER) as " + " BEGIN" + " update emp" + " set salary = SAL_VAL" + 68 Tibero RDBMS 애플리케이션개발자안내서
" where id = ID_VAL;" + " select salary into SAL_VAL" + " from emp" + " where id = ID_VAl;" + " END;"; String dropproc = "DROP PROCEDURE testproc"; Statement stmt = conn.createstatement(); try { stmt.executeupdate(dropproc); } catch(sqlexception e) { // if there is not the procedure } stmt.executeupdate(callsql); CallableStatement cstmt = conn.preparecall("{call testproc(?,?)}"); cstmt.setint(1, 1000); cstmt.setint(2, 7000); cstmt.registeroutparameter(2, Types.INTEGER); cstmt.executeupdate(); int salary = cstmt.getint(2); System.out.println(salary); } stmt.close(); cstmt.close(); } private void disconnect() throws SQLException { if (conn!= null) conn.close(); } Appendix A. tbjdbc 예제프로그램소스코드 69