728x90

안녕하세요. DBeaver와 같은 JDBC 연결 프로그램에서 인포믹스의 한글 데이터가 깨져보이는 경우가 있습니다.

이런 현상을 해결하기 위한 방법을 정리해보려고 합니다.

 

우선 대부분의 경우는 인포믹스 데이터베이스 로케일이 영문일 가능성이 높습니다.

아래와 같이 데이터베이스의 로케일을 확인하실 수 있습니다. 영문 로케일은 일반적으로 en_US.819 로 표시됩니다.

데이터베이스에 한글 데이터 INSERT 문장을 실행하면 오류메시지(Code-set conversion function failed due to an illegal sequence or invalid value.)가 발생합니다.

이번에는 터미널에서 한글 데이터를 입력해놓고 조회를 해봅니다. 조회는 오류가 발생하지 않지만 아래처럼 알아볼 수 없는 깨진 글자가 나옵니다.

근본적인 해결방법은 데이터베이스 생성시 한글 코드를 지원하는 데이터베이스에 마이그레이션 하는 것이 좋지만, 실제 사용중인 데이터베이스를 변경하기는 어려우므로, JDBC Driver에서 지원되는 기능을 사용하여 이 현상을 우회할 수 있습니다.

 

DBeaver Connection 설정에서 JDBC Driver 사용자 속성 NEWCODESET을 추가합니다.

해당 속성을 추가해서 JDK 로케일(ksc5601)과 인포믹스 JDBC 드라이버의 내부 테이블(8859-1,819)과 매핑시킬 수 있습니다.

속성을 추가한 후 새로 데이터베이스에 연결하면 한글 데이터 입력과 조회 모두 잘 실행됩니다.

 

NEWCODESET 속성은 인포믹스 서버 10버전 부터 소개되고 있는데, 이에 대응하는 JDBC Driver는 3버전 이상입니다.

DBeaver에서 JDBC Driver 3.00.JC1 버전으로 연결 테스트를 해보니 오류가 나네요. 최소 3.5버전 이상으로 테스트 해보시길 바랍니다.

728x90
728x90

1. 클라이언트 NLS_LANG

   많은 오라클 엔지니어들이 아직도 이경우 제대로 정리되지 않은 부분입니다.

   결론부터 말하면 DB의 CHAR SET이  UTF8이라고 하더라도

   클라이언트 LOCALE은 KSC5601 혹은 WIN949이어야 합니다.

   문서도 있는데 링크는 기억나지 않고^^;

   UTF8이 서버 로케일일 경우이건 뭐건, 클라이언트 로케일은 해당 국가 로케일이 되어야 합니다.

   간략한 테스트는

   LENGTHB와 CONVERT 함수를 이용해서 테스트를 해보면 됩니다.

   DB가 UTF8일 경우

   클라이언트 LOCALE이 UTF8로 올릴 경우 한글이 2바이트로 됩니다.

   CONVERT로 바꿀 때 SOURCE를 KOC5601로 처리해야 됩니다. (하지만 DUMP를 떠보면 다르게 나옵니다)

   DB가 UTF8이라고 클라이언트 로케일을 UTF8로 바꿀 경우 치러야 할 대가가 만만치 않습니다.

   특히 EXPORT,IMPORT할 때 NLS_LANG을 잘못한 경우...--;

 

2. CHAR TYPE 문제

   하나의 칼럼이 CHAR TYPE인데 이를 UTF8로 바꾼다면?

   해당 데이터가 오로지 영숫자만 있다면 상관없겠으나

   한글도 들어간 칼럼이라면?

   DATA TYPE 변경 없이 일괄적으로 칼럼의 LENGTH를 늘리면

   스페이스가 들어가는 경우가 발생합니다.

   즉, CONVERSION이 잘못된 경우이죠.

   이때는 먼저 SOURCE에서 CHAR -> VARCHAR2로 변경한 뒤에 작업하셔야 합니다.

   일반적으로 특수한 경우(좀있다 얘기하겠습니다)를 제외하고 이렇게 변경한 뒤에

   어플리케이션 영향도는 없다고 보셔도 됩니다.

   그리고 변경하는데 생기는 부하는 거의 없습니다. 단, 피크시간대는 절대 피하셔야죠

   LIBRARY CACHE 쪽에서 해당 테이블을 참조하는 오브젝트가 모두 재컴파일 됩니다.

 

3. VARCHAR2(4000)칼럼의 문제

   LOB나 LONG을 사용하지 않고 VARCHAR2로 칼럼을 정의하고 게시판 본문이나

   각종 텍스트를 처리하는 테이블이 있습니다.

   이 경우 UTF8로 넘어갈 때 BYTE가 늘어나 해당 레코드를 처리할 때 에러가 납니다.

   EXP를 사용할 경우 그냥 에러로그에 남으니까 그나마 낳습니다.

   DB LINK로 땡길 경우 전체 트랜잭션이 에러나면 많이 힘들게 되죠.

   그리고 실질적으로 VARCHAR2(4000)을 넘기 때문에 데이터가 잘리는 문제가 생깁니다.

   이를 해결하려면 LOB로 바꿔야 하는데 이경우 어플리케이션 테스트를 제대로 못하면 문제가 커집니다.

   JAVA같은 경우 TYPE문제가 걸리죠

   이경우 최선의 방법은 없습니다.

   저같은 경우 어플리케이션 담당자를 설득해서 해당 칼럼 데이터의 나머지를 버렸습니다.

   물론 당근으로는... LOB로 바꿀 경우 어플리케이션을 바꿔야 한다는 것. 하지만 일부 데이터의 OVER LENGTH부분을

   버리면 아무것도 손댈 필요가 없다는 것...

   아무튼, 이부분은 DBA가 단독으로 결정하면 안됩니다.

 

4. UTL_FILE을 이용한 FILE CONTROL 문제

   이건 상당히 골치 아픈 문제입니다.

   대상 DB와 어플리케이션이 UTL_FILE을 사용해서 데이터를 읽거나 쓰지 않는다면  여러분은 일단 복받으신 겁니다.

   일반적으로 소켓으로 주고받는 데이터(뭐 금융권 전문이나 애니링크같은)는 구분자가 아니라 자리수로 구분합니다.

   FILE에서는 한글2바이트,영문1바이트이기 때문에 그걸로 미리 자리수가 정해져 있죠.

   이를 UTL_FILE이나 LOADER로 올려서 SUBSTRB로 잘라서 쓰는 경우가 있습니다.

   그런데 디비에서 처리하면 한글3바이트,영문1바이트입니다. 즉, 정해진 자리수로 자를 수 없습니다.

   당연히 배치에서 데이터가 잘못 처리됩니다.

   이럴 때 첫번째로 생각하는 방법은 CONVERT로 KSC5601로 바꿔서 기존 데이터 처리 방식으로 처리하면 됩니다.

   하지만 이런 경우에도 글자는 깨집니다. 왜냐하면 SUBSTRB(SUBSTR 포함)는 해당 로케일을 따라가기 때문에

   CONVERT로 바꾼다고 해도 보장을 못합니다.

   이를 해결할려면 UTL_RAW 팩키지를 사용해야 합니다.

   특히, 잘라서 올리는 것만이 아니라 자리수에 맞춰서 UTL_FILE로 WRITE 할 경우 CONVERT를 제대로 안하면

   전문처리 등에서 대형사고를 일으킵니다.

 

5. PARTIAL MULTI BYTE 에러

   이는 KSC5601 -> UTF8로 DB LINK로 처리할 때 많이 생깁니다.

   원인은 KSC5601 자체 있습니다.

   UTF 코드는 자신이 파싱 못하는 문자는 받아들이지 않으나 KSC5601은 다 받아들입니다.

   즉, 파싱되지 않는 쓰레기 데이터도 해당 칼럼에 들어갑니다.(예를 들어 ¿ 같은 문자)

   그나마 눈에 보이는 문자면 다행이죠... 아예 조회시 누락되는 바이트도 있습니다.

   물론 TO_SINGLE_BYTE FUNCTION으로 대부분 해결됩니다. 그래서 가능한 이방식을 먼저 적용합니다.

   하지만 그렇게 되지 않는 경우도 발생합니다.

   이런 경우는 일일이 찾아서 해당 데이터를 고쳐야 합니다.

   제일 편한 방법은 EXPORT/IMPORT로 넣어서 ERROR LOG를 보면 됩니다.

   그런데 해당 사이트에 여러개의 DB가 있고 해당 데이터가 원천데이터가 아닌 경우는 끝까지 추적해서 그걸 잡아내지 않으면

   마이그레이션 이후에도 계속 에러납니다.

   예를 들어 UTF로 바꾼 DB는 정보계이고 계정계는 아직 KSC5601이라면 마감배치 돌릴 때마다 에러나겠죠?

 

6. COLUMN LENGTH의 문제

   한글은 2->3바이트, 영숫자는 1->1 바이트이므로 계산상 해당 칼럼을 1.5배로 늘려주면 아무 이상이 없어야 하는데요...

   안타깝게도 안그렇습니다. 위의 PARTITAL MULTI BYTE에러와 연관되는 문제인데... 1바이트로 처리되어야하는 문자가

   3바이트로 처리되는 경우가 발생합니다. 이것을 피하고 싶으면  TO_SINGLE_BYTE로 처리해야 합니다.

   그러나... 이경우 문제가 있습니다. 일단 처리시간이 오래걸립니다.(마이그레이션은 제한된 시간에 해야 합니다)

   그렇다고 기존 SOURCE를 전부 UPDATE처리하자니 뒷감당이 안됩니다.( 문제가 발생하는 레코드의 칼럼만

    변경하면 됩니다만 이것을 추적해서 찾을 시간이 없습니다. 물론 시간이 있다면 하시는게 베스트죠. 그러나 그럴 시간을

    확보할 수 있을까요?)

    결국 나중에는 2배로 늘리고, 다시 2.5~3배로 늘렸습니다. 시간이 부족하기 때문에 벌어진 일이죠.

    이렇게 해도 큰 문제가 없는 이유는 대부분 이런 문제를 일으키는 데이터는 조회조건에 걸리는 칼럼이 아니라

    조회결과로 걸리는 칼럼이기 때문입니다.(비즈니스 어플리케이션을 이해하신다면 수긍하실겁니다)

    이것은 편법입니다. 원칙적으로는 이런 데이터 클린징작업을 먼저 수행해야 합니다.

728x90

+ Recent posts