database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
PostgreSQL
Firebird
ㆍOracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
Oracle Q&A 23983 게시물 읽기
No. 23983
Character set, DB link 어떤 문제인지?
작성자
핸시기(hainsigi)
작성일
2005-09-07 11:03
조회수
14,542

현재 바보서버와 온달서버 두개가 있습니다. winnt 4.0에 oracle 7.3 버전이 설치 되어 있구요.

환경은 거의 같은데 단지... Character set이 틀립니다. 바보서버는 US7ASCII 온달서버는 KO16KSC5601!!!

바보서버에서 온달서버로 DB link를 만들어 단지 select만 합니다.

select * from tb_name@BABO_DBLK;를 하면

xxx xxxxx ??? xxxxxxxxxxxx

xxx xxxxx ??2 xxxxxxxxxxxx

xxx xxxxx (?)?? xxxxxxxxxxxx => 한글부분은 전부 ? 당근 Character set이 틀려서겠죠?

하지만 이렇게 15행까지 조회가 되고 Error가 나타납니다.

ERROR:
ORA-24365: error in character conversion
ORA-02063: preceding line from BABO_DBLK => 이 2개 에러가 왜 발생하는지?

다른 table를 select 하면 아무 문제가 없는데 유독 이 table만 에러가 발생하네요.

더 이상한건 select count(*) from tb_name@BABO_DBLK; 하면 count 갯수가 29600건 바로 나타납니다. 왜? count()를 돌리면 갯수를 가져오고 *로 하면 중간에 Error가 나타나는지 모르겠습니다.

이 글에 대한 댓글이 총 8건 있습니다.

오라클에서는 클라이언트에 NLS_LANG 환경변수에 설정된 문자세트와 DB에 설정된 문자세트가 다를 경우 두 문자 사이에 conversion이 발생합니다. 이때 클라이언트 문자 세트가 서버의 문자세트보다  super set일 경우만 정확한 conversion이 발생하고, 나머지는 conversion이 실패할 수 밖에 없습니다.

이때 두 문자 세트 사이에 불일치가 일어나면 ?로 변환이 됩니다.

 

그러나 예를 들어서 KO16KSC5601 문자 세트에 아예 없는 문자가 이미 DB 내에 존재하고 있다면 아예 변환 자체를 할 수 없는 경우가 생깁니다. 즉 윈도우98부터인가 윈도우 계열에서는 KSC5601 이 아니라 확장완성형(CP 949)이 사용되므로 KSC5601 에는 없는 문자가 있습니다.

예를 대표적으로 썊 같은 문자입니다. 이런 문자가 있을 경우에는 이런 현상이 발생할 수 있습니다.

 

  ORA-24365: error in character conversion
      Cause: This usually occurs during conversion of

              a multibyte character data when the

              source data is abnormally terminated in

              the middle of a multibyte character.
     Action: Make sure that all multibyte character

             data is properly terminated.

사실 이 경우에 영어만 사용하면 모르겠지만 한글이 사용되고 있다면, 근본적인 방법은 문자세트를 일치시켜주는 방법 외에는 다른 방법이 없습니다. ( dblink를 사용할 경우 multibyte character를 사용한다면 반드시 문자세트를 일치시키는 것이 좋습니다. 다만 영어, 한글만 있다면 UTF8 <-> KO16MSWIN949 는 아직까지 문제를 발견하지 못했는데(앞으로도 반드시 그럴것이다라고는 못하겠고?) 일어나 중국어가 있을 경우 여지없이 동일한 문자가 발생하더군요. )

 

다만 한글이 깨어지게 두고 에러만 안나게 하려면 문자세트를 KO16MSWIN949로 변경하면 되지만 이것도 7 버전에서는 불가능할 것입니다. 아마도 8.x 버전 이상으로 upgrade를 해야만 가능할 것입니다.  또 다른 길은 이렇게 깨어진 문자를 찾아내어서 KSC5601 에 맞게 고쳐주면 됩니다.

아마도(amado)님이 2005-09-07 11:26에 작성한 댓글입니다.

질문 하나 더 입니다.

이전에 온달서버의 Character set을 US7ASCII에서 KO16KSC560로 바꾼적이 있다고 하네요. 그럼 tb_name table안에 Character set을 US7ASCII일때는 US7ASCII data가 KO16KSC560일때는 KO16KSC560 data가 공존하나요?

그래서 이런 Error가 발생하는지...

핸시기(hainsigi)님이 2005-09-07 12:12에 작성한 댓글입니다.

오라클에서 US7ASCII  는 모든 character set의 subset 입니다.

온달서버의 character set을 변경했다고 해서 발생하는 문제는 아닙니다.

 

다만 KO16KSC5601 로 설정된 데이타베이스 ( 온달서버)에 KSC5601 문자세트에 포함되지 않은 문자가 들어있어서 발생하는 문제입니다. 아까 제가 예를 든 샾 같은 문자는 MSWIN949 로 인하여 현재 잘 사용하고 있지만 KSC5601 에는 없는 문자입니다. 그래서 샾을 오라클은 2 byte 로 이해를 합니다. 이때 뒤쪽에 있는 1바이트와 다음 바이트가 하나의 한글 문자로 인식되는 경우가 발생할 때 SQL 문장 자체가 깨어지는 현상이 발생할 수 있고 이 경우 같은 문제가 발생할 수도 있습니다.

 

1. dblink 사용시는 반드시 문자세트가 일치하는 database에서만 사용해야 합니다. 이 경우 정확한 DB 정보를 알면 바보서버를 KO16KSC5601로 바꾸는 것도 한 방법입니다. (이때 영어,한글만 있을 경우만 가능하고, 이 데이타베이스 일어나 중국어 같은 다른 문자 세트가 들어 있는 경우 불가능합니다. 그럴 경우는 영어,한글이외에는 모두 깨어져 보일것입니다.) 물론 이 경우 이 DB에 접속하는 클라이언트의 NLS_LANG 도 모두 바꾸어 주어야 합니다.

 

2. 온달서버에 존재하는 데이타 중에서 KO16KSC5601 아닌 문자는 모두 변경합니다. 그럼 한글의 경우는 ? 로 변환되어서 인식하지는 못하겠지만 에러는 발생하지 않겠지요. US7ASCII  는 KO16KSC5601의 subset 이므로 영어는 잘 보이겠구요.

select rowid, * from tb_name@BABO_DBLK where rowid > 'xxxx' and rownum < 10 ; 이런 씩으로 에러난 근처에서 찾으면 해당 row를 찾을 수 있습니다. 그때 한글이 들어간 칼럼을 주의해서 보시면 잘못된 문자를 찾을 수 있을 것입니다.

제가 지금 오라클에 접속할 수 있는 환경이 없어서 테스트 결과는 못 알려드리지만, 예전에 where han_column != trim(han_column) 이렇게 한글이 들어간 칼럼에 함수를 적용한 후에 비교를 해서 틀린 경우를 추출하니 대부분 나왔던 기억이 있습니다만, 함수 이름이 헷갈리네요. trim 이었는지 다른 것이었는지...

아마도(amado)님이 2005-09-07 13:05에 작성한 댓글입니다.
이 댓글은 2005-09-08 02:08에 마지막으로 수정되었습니다.

먼저 답변 정말 감사드립니다.

 

어느 문자가 잘못되었는지 확인하는데... 15번행까지 나왔던 다음 16번행에는 다음과 같이 한글이 포함되어 있었습니다.

"(주)세우산업", "최홍규외", "건설", "토공외", "부산시동구초량동"

KSC5601에 포함되지 않는 문자가 있나요?

핸시기(hainsigi)님이 2005-09-07 15:05에 작성한 댓글입니다.

윗분 말씀대로 Charset을 바꿔주는게 좋을 듯 합니다.

 

US7ASCII 는 2-byte를 위한 캐릭터셋이 아니기 때문에 지속적으로 문제를 일으킬 수 있습니다.

 

오라클에 캐릭터셋 변환시 얼마나 깨지는지 사전 체크가 가능한 툴이 존재합니다. 일단 그걸로 돌려보시면 정확히 예상이 가능합니다. 그리고 나서 변환을 하시는게 좋을 듯 합니다.

 

KO16MSWIN949 확장완성코드는 KO16KSC5601 완성형을 포함하므로  이의 사용을 권고 드립니다.

앞으로 KO16KSC5601 는 잊으시고 KO16MSWIN949 를 사용하시기 바랍니다.

 7.3같은 낡은 버전의 경우 KO16MSWIN949 같은 최신 캐릭터셋을 이해하지 못해서 에러가 발생하는 경우도 본 것 같네요. 체크 바랍니다.
김주현님이 2005-09-07 19:40에 작성한 댓글입니다.
이 댓글은 2005-09-07 19:42에 마지막으로 수정되었습니다. Edit

테스트를 sqlplus 에서 하셨다면, sqlplus 는 default 로 15개씩 array fetch를 합니다. 따라서 sqlplus 에서 15번째 이후에 에러가 발생했다면 에러가 난 row는 16~30 번째 레코트 내에 존재할 것입니다.

반드시 16번째라고 장담할 수 없지요.

정확하게 찾으려면 sqlplus 의 arraysize 를 1로 변경하시기 바랍니다.

 

일단 보여주신 16번째 레코드는 KSC5601에 포함되는 것 같습니다.

아마도(amado)님이 2005-09-07 23:33에 작성한 댓글입니다.
이 댓글은 2005-09-08 02:20에 마지막으로 수정되었습니다.

제가 이 사이트에서 본 건데요..

어느분이 서로 다른 문자셑 설정된 서버간의 db_link시에 ...

이진 전송을 사용한 일종의 꽁수에 가까운(그러나 상당히 의미있는) 방법으로 해결하신 것을 올려놓으신 것을 본적이 있습니다.

검색창에 "캐릭터셋이 다른 DB간의 DB링크"라고 치면 나옵니다.

 

그리 권장할 만한 방법인가!

다른 대안은 없는가!

음.... 솔찍히 대답이 망설여지지만...

정 방법이 없다면 사용해볼만 한 방법이라 생각합니다.

 

그 아이디어는 이런 겁니다.

 

1. 먼저 오라클은 서버와 클라이언트의 문자셑이 일치하면 문자셑 변환을 시도 하지 않고 문자열의 이진 이미지 그대로를 저장합니다.

이 말이 무엇이냐면 예를 들어 US7ASCII로 설정된 서버와 클라이언트가 있는데... 이때 '썊' 같은 지원되지 않는 문자를 입력해도 ... 잘 입력되고 조회된다는 말입니다.단 위의 님들 말처럼 서버 내부에서는 저 놈을 문자로 안 봅니다.length('썊') 하면 2가 나옵니다.

즉 서버와 클라이언트가 동일한 문자셑을 가지면 그때 입력한 자료는 그놈이 US7ASCII의 문자셑일 때 입력한 자료나 KO16KSC5601 일 때 입력한 자료나 KO16MSWIN949 일 때 입력한 자료나 다 동일한 저장 이미지를 갖는다는 것입니다.생각해 보십시오. 단지 sys.props$의 값만 바꾼다고 문자셑이 바뀌는 이유도 다 이때문이죠.

2. 두대의 서버가 있고 각각의 서버에 접근하는 클라이언트는 각각 서버의 문자셑을 따른다고 가정하면 문제는 서버간의 문자 전송 역시 문자셑변환을 일으키지 않도록 하면 되지 않는가!라는 아이디어 이지요..

방법이 있죠 utl_raw.cast_to_raw를 써서 이진 포맷으로 속이는 겁니다. 마찬가지로 받는 쪽에서는 utl_raw.cast_to_varchar2로 살리구요..

 

이렇게 해서 서로 다른 문자셑의 db간의 링크를 문제 없이 하는 방법을 올려놓았더군요...

 

참 대단한 아이디어다 생각했습니다...

게다가 질문 올리신 분이 스스로 찾아서 올려 놓으셨더라구요...

그래서 그분께 감사의 말씀을 전했습니다.

 

정도는 아닐지 모르나 분명 참고할 가치가 있는 글이었습니다.

그래서 여기서 이렇게 소개 드립니다.

 

김흥수(protokhs)님이 2005-09-08 00:12에 작성한 댓글입니다.
이 댓글은 2005-09-08 00:13에 마지막으로 수정되었습니다.

소스 DB에서 utl_raw.cast_to_raw를 사용하고 받는 DB에서는 utl_raw.cast_to_varchar2 를 사용하여 해당 테이블들에 대해서 view를 만들면 select 시에는 해결되겠군요.

 

만약 응용프로그램의 수가 적다면 변경부분도 적을 것이고...

 

7.3 버전에도 utl_raw 패키지가 존재하나요? 정말 궁금해서... ^^;

 

만약 존재하지 않는다면, 결국 가장 좋은 방법은 두 DB에 영어,한글만 있다면, 문자세트를 KO16MSWIN949 로 둘다 변경하는 것이 가장 좋을듯합니다. (이 경우 조심해야 할 점은 이 DB에 접근하는 모든 클라이언트들은 NLS_LANG을 없애거나 KO16MSWIN949 바꾸어 주어야 한다는 점입니다. 물론 변경 직전에 DB 백업을 받아두구요.)

아마도(amado)님이 2005-09-08 02:19에 작성한 댓글입니다.
[Top]
No.
제목
작성자
작성일
조회
23986벤치마크 [4]
ohyouknow
2005-09-07
1458
23985트리거 질문 있어요. [1]
오라초보
2005-09-07
2027
23984쿼리좀 알려주세요.. [1]
궁금이
2005-09-07
1272
23983Character set, DB link 어떤 문제인지? [8]
핸시기
2005-09-07
14542
23982dblink 질문 [2]
이인호
2005-09-07
2982
23981정렬을 위해 힌트를 사용하는 게 괜찮은가요? [1]
음..
2005-09-07
2293
23980힌트 질문입니다. [3]
...
2005-09-07
1724
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.018초, 이곳 서비스는
	PostgreSQL v16.4로 자료를 관리합니다