DBMS 1
DA, SQL, DB보안 등 실무자를 위한 위한 DB기술 바이블!
TIBERO to MS-SQL DBLink 작업 전, Java로 된 단위프로그램을 이용하여 Java Gateway가 설치된 서버에서 MS-SQL서버에 정상적으로 접속 되는지 테스트를 진행한다. 접속 테스트 프로그램은 tbnet_alias.tbr에 설정한 GW_TX_MODE property에 설정할 값에 따라 선택한다. 테스트가 잘 되지 않을 경우 MS-SQL 설치 머신의 방화벽 및 TCP/IP 인터페이스 활성화 여부 등 외적인 환경에 문제가 없는지 확인하도록 한다. Java를 통해 MS-SQL서버에 접속 되지 않는다면 Java Gateway도 사용할 수 없다. MS-SQL 서버 접속 테스트 성공 시 MS-SQL DBLink 설정 작업을 진행한다 부록 4.1 GW_TX_MODE = LOCAL일 경우 Java로 된 단위프로그램으로 Java Gateway가 설치된 서버에서 MS-SQL서버에 정상적으로 접속 되는지 테스트를 진행한다. [파일명: defaultStmt.java] Java로 된 단위프로그램(2 Phase Commit)으로 Java Gateway가 설치된 서버에서 MS-SQL서 버에 정상적으로 접속 되는지 테스트를 진행한다. XA 테스트를 위해서는 우선 MS-SQL서버 의 DTC(분산 트랜잭션)서비스가 가능한지 확인해야 하며, 설정방법은 다음과 같다. [MSSQL서버의 DTC(분산 트랜잭션)서비스 설정방법] MSSQL 서버 접속테스트를 위해 단위프로그램(XA)은 다음과 같다. [파일명: testXA.java] 장애유형1. GW_TX_MODE = LOCAL 설정 후, 접속테스트프로그램 실행 시 [에러현상] 장애유형2. GW_TX_MODE = GLOBAL 설정 후, 접속테스트프로그램 실행 시 [에러현상] 1) DBLink 생성구문 2) DBLink 사용방법 Tibero to MS-SQL의 DBLink 쿼리 수행 시 함수에 관한 제약사항부록
부록 (Java gateway 사용 전 MS-SQL 서버접속테스트)
부록 4.2 GW_TX_MODE = GLOBAL일 경우
부록 4.3 TroubleshootingGW_TX_MODE=LOCAL일 경우
(소스 내 접속 URL 및 select 할 schema(uid, pwd)변경 후 실행할 것)
import java.util.*;
import java.sql.*;
import com.microsoft.sqlserver.jdbc.*;public class defaultStmt
{
Connection tb_conn = null;
private final String testquery = "select c1 from t1";
PreparedStatement pstmt = null;
String url="jdbc:sqlserver://192.168.14.239:1433;databasename=tmax";
String uid="test";
String pwd="tmax123";
ResultSet rset = null;public defaultStmt() {
init();
}
public void init() {
try {
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
}
catch(Exception e) { e.printStackTrace(); }
execCall();
}
public void execCall() {
try {tb_conn = DriverManager.getConnection(url, uid, pwd);
pstmt = tb_conn.prepareStatement(testquery);
rset = pstmt.executeQuery();
while(rset.next()){
System.out.println( rset.getInt(1) );
}
pstmt.close();
tb_conn.close();
}catch(Exception e) { e.printStackTrace();
}finally{ try { pstmt.close(); tb_conn.close(); } catch(Exception ex)
{ ex.printStackTrace(); } }
}public static void main(String[] args) {
new defaultStmt();
}
}
GW_TX_MODE=GLOBAL일 경우
1. sqljdbc_xa.dll 파일을 SQL Server의 Binn 디렉토리에 복사
(해당파일은 Microsoft SQL Server 2005 JDBC Driver 1.2의 sqljdbc_1.2\kor\xa에 플랫폼별
로 있음)2. 첨부한 (xa_install.sql)을 DB 에 관리자 계정으로 로그인 후 실행.
(설치여부 확인 sp_help xp_sqljdbc_xa_init )3. XA Transaction을 사용하기 위한 권한 부여.
ex)
use master
go
exec sp_grantdbaccess 'tibero','tmax'
go
exec sp_addrolemember [SqlJDBCXAUser], 'tibero'
go4. DTC Service 가능토록 설정(XA Transaction을 지원할 수 있도록 설정)
- 제어판-관리도구-구성요소서비스-컴퓨터-내컴퓨터(속성: 오른쪽마우스 클릭)
- MSDTC TAB에서 '보안구성' XA 트랜잭션 사용을 체크 후 MSDTC 및 MSSQL 재구동
import java.net.Inet4Address;
import java.sql.*;
import java.util.Random;
import javax.transaction.xa.*;
import javax.sql.*;
import com.microsoft.sqlserver.jdbc.*;public class testXA {public static void main(String[] args) throws Exception {
// Create a variable for the connection string.
String url="jdbc:sqlserver://192.168.14.239:1433;databasename=tmax";
String uid="test";
String pwd="tmax123";try {
// Establish the connection.
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection con = DriverManager.getConnection(url, uid, pwd);// Create a test table.
Statement stmt = con.createStatement();
try {stmt.executeUpdate("DROP TABLE t1"); }catch (Exception e) {}
stmt.executeUpdate("CREATE TABLE t1 (c1 int)");
stmt.close();
con.close();// Create the XA data source and XA ready connection.
SQLServerXADataSource ds = new SQLServerXADataSource();
ds.setUser("hslim");
ds.setPassword("tmax123");
ds.setServerName("192.168.14.239");
ds.setPortNumber(1433);
ds.setDatabaseName("tmax");
XAConnection xaCon = ds.getXAConnection();
con = xaCon.getConnection();// Get a unique Xid object for testing.
XAResource xaRes = null;
Xid xid = null;
xid = XidImpl.getUniqueXid(1);// Get the XAResource object and set the timeout value.
xaRes = xaCon.getXAResource();
xaRes.setTransactionTimeout(0);// Perform the XA transaction.
System.out.println("Write -> xid = " + xid.toString());
xaRes.start(xid,XAResource.TMNOFLAGS);
PreparedStatement pstmt =con.prepareStatement("INSERT INTO t1 (c1) VALUES ()");
pstmt.setInt(1,1);
pstmt.executeUpdate();// Commit the transaction.
xaRes.end(xid,XAResource.TMSUCCESS);
xaRes.commit(xid,true);// Cleanup.
pstmt.close();
con.close();
xaCon.close();// Open a new connection and read back the record to verify that it worked.
con = DriverManager.getConnection(url, uid, pwd);
ResultSet rs = con.createStatement().executeQuery("SELECT * FROM t1");
rs.next();
System.out.println("Read -> 1 rows = " + rs.getInt(1));
rs.close();
con.close();
}// Handle any errors that may have occurred.
catch (Exception e) {
e.printStackTrace();
}
}
}
class XidImpl implements Xid {public int formatId;
public byte[] gtrid;
public byte[] bqual;
public byte[] getGlobalTransactionId() {return gtrid;}
public byte[] getBranchQualifier() {return bqual;}
public int getFormatId() {return formatId;}XidImpl(int formatId, byte[] gtrid, byte[] bqual) {
this.formatId = formatId;
this.gtrid = gtrid;
this.bqual = bqual;
}
public String toString() {
int hexVal;
StringBuffer sb = new StringBuffer(512);
sb.append("formatId=" + formatId);
sb.append(" gtrid(" + gtrid.length + ")={0x");
for (int i=0; i<gtrid.length; i++) {
hexVal = gtrid[i]&0xFF;
if ( hexVal < 0x10 )
sb.append("0" + Integer.toHexString(gtrid[i]&0xFF));
else
sb.append(Integer.toHexString(gtrid[i]&0xFF));}
sb.append("} bqual(" + bqual.length + ")={0x");
for (int i=0; i<bqual.length; i++) {
hexVal = bqual[i]&0xFF;
if ( hexVal < 0x10 )
sb.append("0" + Integer.toHexString(bqual[i]&0xFF));
else
sb.append(Integer.toHexString(bqual[i]&0xFF));
}
sb.append("}");
return sb.toString();
}// Returns a globally unique transaction id.
static byte [] localIP = null;
static int txnUniqueID = 0;
static Xid getUniqueXid(int tid) {Random rnd = new Random(System.currentTimeMillis());
txnUniqueID++;
int txnUID = txnUniqueID;
int tidID = tid;
int randID = rnd.nextInt();
byte[] gtrid = new byte[64];
byte[] bqual = new byte[64];
if ( null == localIP) {
try {
localIP = Inet4Address.getLocalHost().getAddress();
}
catch ( Exception ex ) {
localIP = new byte[] { 0x01,0x02,0x03,0x04 };
}
}
System.arraycopy(localIP,0,gtrid,0,4);
System.arraycopy(localIP,0,bqual,0,4);// Bytes 4 -> 7 - unique transaction id.
// Bytes 8 ->11 - thread id.
// Bytes 12->15 - random number generated by using seed from current time in
milliseconds.
for (int i=0; i<=3; i++) {
gtrid[i+4] = (byte)(txnUID%0x100);
bqual[i+4] = (byte)(txnUID%0x100);
txnUID >>= 8;
gtrid[i+8] = (byte)(tidID%0x100);
bqual[i+8] = (byte)(tidID%0x100);
tidID >>= 8;
gtrid[i+12] = (byte)(randID%0x100);
bqual[i+12] = (byte)(randID%0x100);
randID >>= 8;
}
return new XidImpl(0x1234, gtrid, bqual);
}
}
Troubleshooting
com.microsoft.sqlserver.jdbc.SQLServerException: 호스트 에 대한 TCP/IP 연결에 실패했습니다.
java.net.ConnectException: Connection refused
at com.microsoft.sqlserver.jdbc.SQLServerException.makeFromDriverError(Unknown Source)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connectHelper(Unknown Source)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.loginWithoutFailover(Unknown Source)
at com.microsoft.sqlserver.jdbc.SQLServerConnection.connect(Unknown Source)
at com.microsoft.sqlserver.jdbc.SQLServerDriver.connect(Unknown Source)
at java.sql.DriverManager.getConnection(DriverManager.java:512)
at java.sql.DriverManager.getConnection(DriverManager.java:171)
at defaultStmt.execCall(defaultStmt.java:37)
at defaultStmt.init(defaultStmt.java:30)
at defaultStmt.(defaultStmt.java:22)
at defaultStmt.main(defaultStmt.java:52)
java.lang.NullPointerException
at defaultStmt.execCall(defaultStmt.java:48)
at defaultStmt.init(defaultStmt.java:30)
at defaultStmt.(defaultStmt.java:22)
Write -> xid = formatId=4660
gtrid(64)={0x7f00000101000000010000000d5390f1000000000000000000000000
0000000000000000000
00000000000000000000000000000000000000000000000000000}
bqual(64)={0x7f00000101000000010000000d5390f1000000000000000000000000
0000000000000000000
00000000000000000000000000000000000000000000000000000}
javax.transaction.xa.XAException: java.sql.SQLException: XA 컨트롤 연결
을 만들지 못했습니다.
오류: xp_sqljdbc_xa_init failure, status:0 msg:***
SQLJDBC_XA DTC_ERROR Context: xa_init, state=1, StatusCode:0
(0x00000000) ***.
at com.microsoft.sqlserver.jdbc
2) MSSQL서버의 DTC(분산 트랜잭션)서비스 비활성화
2) DTC서비스 활성화 방법은 본 문서 12pate 참조하여 세팅 할 것. 참고: http://msdn.microsoft.com/ko-kr/library/ms378931(SQL.90).aspx (로컬, 분산 트랜잭션의 이해)별첨 1
CREATE DATABASE LINK 링크명
CONNECT TO 유저명 ID IDENTIFIED BY '패스워드' USING 'tns_alias명';
SELECT * FROM 테이블명@링크명;
INSERT INTO 테이블명@링크명 VALUES (col1, col2);
DELETE FROM 테이블명@링크명;
UPDATE 테이블명@링크명 SET col1=1;**PROCEDURE, TRIGGER안에서도 DBLink 사용가능.
별첨 2
함수명
사용가능여부
비 고
ABS
○
ACOS
○
ADD_MONTH
○
ASCII
○
ASIN
○
ATAN
○
ATAN2
○
CEIL
○
CHR
○
COALESCE
○
CONCAT
○
COS
○
COSH
X
decode
○
EXP
○
FLOOR
○
INSTR
△
인자 4개는 사용할 수 없음
character type only, 동일한 언어, 인코딩
LN
○
LOG
○
LOWER
○
LPAD
△
인자 2개만 가능
LTRIM
△
인자 1개만 가능
MOD
○
MONTHS_BETWEEN
○
NULLIF
○
NVL
○
NVL2
○
POWER
SELECT
REPLACE
○
ROUND(NUMBER)
○
RPAD
△
인자 2개만 가능
RPAD
SELECT
데이터 조회
RTRIM
△
인자 1개만 가능
SIGN
SELECT
○
SIN
SELECT
○
SINH
SELECT
X
SQRT
SELECT
○
SUBSTR
SELECT
○
TANH
SELECT
X
TO_CHAR(DATETIME)
△
인자 1개 버전만 가능
TO_CHAR(NUMBER)
△
인자 1개 버전만 가능
TO_DATE
△
인자 1개 버전만 가능
TO_NUMBER
△
인자 1개 버전만 가능
TRANSLATE
X
TRIM
△
인자 1개만 가능
TRUNC(NUMBER)
○
UPPER
△
동일한 언어, 인코딩일 경우 가능
AVG
○
COUNT
SELECT
○
MAX
SELECT
○
MIN
SELECT
○
STDDEV
SELECT
○
STDDEV_POP
SELECT
○
STDDEV_SAMP
SELECT
○
SUM
SELECT
○
VAR_POP
SELECT
○
VAR_SAMP
SELECT
○
VARIANCE
SELECT
○