DB를 사용하게되면, 한번씩 격는 한글깨짐 현상.. 지난 날.. 어떻게 하다보니 한글이 나오게 되었지만.. 기억이 나지 않네요. 그래도 이렇게 좋은 글들이 있어서 스크랩 해봅니다.
필자가 개발 프로젝트를 진행하던 몇 년 전만하더라도 PMO(Project Management Officer) 조직은 프로젝트에 참여하는 주요 회사들의 PM들로 구성됐다. 그러나 최근 기업들이 경영정보시스템(MIS: Management Information System)을 구축하면서 프로젝트의 규모가 커지고, 제안된 프로젝트 기간, 프로젝트 관리에 대한 전문성 요구 등으로 PMO 조직을 강화하는 추세로 변화하고 있다.
프로젝트 관리자는 오케스트라의 지휘자로 비유된다. 지휘자는 아주 상세한 내용까지는 모르더라도 각각의 악기가 어떤 화음을 내야 한다는 것을 악보를 통해 알 수 있다. 프로젝트 관리자들도 마찬가지이다.
프로젝트 관리자들은 개발 방법론 상의 태스크(Task : 해야 할 일)., 산출물, 방법론(Technique)을 자세하게 알 필요는 없다. 그러나 각각의 태스크가 무슨(what) 일을 왜(why) 해야 하는지에 대한 개념을 가지고 어떠한 방법(how)으로 산출물을 만들지에 대해 인식하고 있어야 한다. 그래야 최소의 인적자원과 시간을 할애해 프로젝트를 진행할 수 있다.
필자가 처음 MySQL을 겪으며 느꼈던 점은 ‘설정할 부문이 정말 많다’였다. 오라클처럼 설치 단계에서 variable을 몇 개 지정해 주면 알아서 잘 돌아가는 것이 아니라 MySQL은 프로젝트 특성에 맞게 variable들에 대해 최대한 설정을 맞춰줘야 최고의 성능을 낸다. 어쩌면 보편적으로 잘 돌아가는 오라클에 비해 성능이 잘 나오지 않는다고 생각할 수 있으나 프로젝트의 특성에 맞게 설정만 잘 해준다면 어떤 DBMS에도 뒤지지 않는 최고의 성능을 지닌 DBMS가 될 것이다. 이러한 여러 설정 가운데 이 글에서는 character set에 대한 설정을 다루도록 하겠다.
한글 데이터가 깨지는 것은 무심코 사용하는
console 설정 값 때문 먼저 MySQL에 접속해 character set의 설정을 확인해 보자. 아래의 접속은 GUI 툴을 이용하지 않고 MySQL에서 제공하는 유틸리티인 mysql을 통한 접속이다.
mysql> show variables like ‘character_set\_%’;
+--------------------------+--------+
| Variable_name | Value |
+--------------------------+--------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | utf8 |
| character_set_filesystem | utf8 |
| character_set_results | latin1 |
| character_set_server | utf8 |
| character_set_system | utf8 |
+--------------------------+--------+
7 rows in set (0.00 sec)
위의 명령어를 통해 보면 여러 가지 character set 관련 설정 값이 나타난다. 여기서 주의 깊게 봐야 하는 것이 바로 charac ter_set_client, character_set_connection, character_set_ results의 값이 latin1으로 되어 있다는 것이다. MySQL의 설정 파일인 my.cnf 파일에 default-character-set=utf8로 설정했음에도 불구하고 character set에 대한 설정 값이 latin1으로 나타나는 이유는 무엇일까? 그 이유는 다음과 같은 명령어를 통해 확인할 수 있다.
[mysql@newyark mysql]$ /db/mysql/bin/mysql --help | grep default-character-set
default-character-set latin1
우리가 아무런 옵션 없이 다음과 같이 접속하면,
[mysql@newyark mysql]$ /db/mysql/bin/mysql -uroot -p
mysql은 default 값을 적용해 다음의 명령어를 실행한 효과와 같다.[mysql@newyark mysql]$ /db/mysql/bin/mysql --default-character-set=latin1
오라클은 OS user의 shell 설정에 따라 접속 character set이 정해지지만 mysql은 default-character-set이 latin1으로 고정되어 있다. 이번에는 Query GUI 툴을 사용해 같은 쿼리를 실행해 보자. 필자는 개발자들이 가장 자주 사용하는 툴인 SQL yog를 통해 접속하고 처음과 같은 쿼리를 실행했다.
같은 서버에 접속해 동일한 쿼리를 실행했지만 모든 설정 값이 utf8로 나오는 것을 확인할 수 있다. 이처럼 다른 이유는 무엇일까? 최근에 개발자들이 즐겨 쓰는 GUI 툴의 에디터는 utf8을 쓰고 있다. 그 에디터에 맞춰 GUI 툴은 접속할 당시 암시적으로 set names ‘utf8’; 이라는 쿼리를 MySQL에 보내어 현재 utf8 에디터에서 작업했음을 알려준다. 그렇다면 set names라는 명령어는 무엇일까? set names라는 명령어는 character_ set_client, character_set_connection, character_set_results의 3개 변수에 대해 지정된 character set으로 설정하는 역할을 한다. 즉, 내가 보내는 문자열이 어떤 character set(charac ter_set_client)이고 어떤 character set으로 접속했으며(character_set_connection), 쿼리의 결과 값을 어떤 character set으로 받을지(character_set_results) 지정해 주는 명령어인 것이다. 하지만 자동적으로 set names를 실행해 주는 GUI 툴에 비해 웹 애플리케이션에서는 특별한 설정을 하지 않는다. 설정 대신 우리는 웹에서 한글 데이터가 깨져 보일 때 웹 애플리케이션에서 받아온 값을 getBytes()를 통해 바꾸거나 HTML에서 들어오는 형식을 바꾸기도 한다. 물론 이 방법이 틀린 것은 아니지만 설정만 잘 해준다면, 이러한 불필요한 오버헤드(overhead)를 줄일 수도 있다. 먼저 MySQL의 character set의 동작원리를 살펴보자. MySQL은 데이터를 받아들이면 들어온 데이터와 저장될 데이터베이스 내의 character set을 먼저 비교한다. 들어온 데이터의 character set 값은 character_set_client의 설정 값이며 데이터베이스의 character set은 table 생성시 지정됐던 character set이다. 만약 비교해서 같지 않으면, MySQL은 들어온 데이터를 저장될 데이터베이스 내의 character set으로 인코딩(encoding)해서 저장한다. 물론 내보낼 때도 저장된 character set과 character_set_results를 비교해 같지 않으면 character _set_results의 character set에 맞춰 다시 디코딩(decoding)해서 내보낸다. 다음과 같은 예제를 통해 한글 깨짐 현상을 확인해보자. 데이터는 utf8로 저장되어 있고, 우리는 MySQL 유틸리티?인한다.
Console setting : utf8
mysql> select * from profile limit 1 \G
*************************** 1. row ***************************
id: 13
user_id: newyark
daum_id: newyark
daum_name: ????
name: ?????
real_name: ?????
tags: @@_talknetizen_??-???_@@
우리가 한글 문제에서 자주 보는 ????의 문자들이 찍히는 것을 확인할 수 있다. 그 이유를 살펴보자. 처음에 설명했듯이 MySQL의 default-character-set은 latin1이므로 character _set_results의 설정 값은 latin1이 된다. 저장된 데이터는 utf8이지만 MySQL은 character_set_results에 맞춰 utf8을 latin1으로 변환하려고 노력한다. 물론 영어나 숫자는 상관없겠지만 한글은 latin1의 문자 table에 한글 utf8 코드는 맵핑되는 값이 존재하지 않기 때문에 알 수 없는 문자라는 ???? 라는 문자를 찍게 된다.
<그림 1> MySQL character set 동작원리
그렇다면 set names를 통해 결과 값에 대한 character set을 맞춰보자.
Console setting : utf8
mysql> set names utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from profile limit 1 \G
*************************** 1. row ***************************
id: 13
user_id: newyark
daum_id: newyark
daum_name: 하이서울
name: 조민
real_name: 조민
tags: @@_talknetizen_화이팅_@@
set names utf8;이라는 명령어를 통해 character_set_client, character_set_connection, character_set_results의 값을 utf8로 바꾸게 되면 MySQL은 결과 값으로 보내줘야 하는 character set과 저장된 데이터의 character set이 utf8로 같다고 판단하기 때문에 데이터를 아무런 변환 없이 출력하게 된다.
단 여기서 우리가 간과하지 말아야 부분이 있다. 그것이 바로 console setting이다. 간혹 모든 부문을 잘 맞추고도 한글 데이터가 깨져 나오는 경우가 있는데 그 이유는 console의 character setting이 맞지 않아서다. 작업하는 console에서 한글 데이터가 깨져 보일 때는 반드시 console 설정 값을 character_set _results의 값과 동일하게 맞춰야 한다. 프로젝트 시작 단계에서 프로젝트의 character set은 동일하지만, 개발 툴의 character set의 정의는 간과하는 것인 대부분이다. 자주 쓰이는 터미널 툴이나 GUI 툴은 버전에 따라 다른 character set을 default로 하기 때문에 많은 주의가 필요하다.
여기서 꼭 짚고 넘어가야 할 부분이 있는데, 그것은 테스트하는 에디터의 character 설정과 웹 애플리케이션 작성시 HTML header에 선언하는 contentType=“text/html; charset=utf8”이라는 부문이 같다는 것이다. 에디터에서 한글 데이터가 깨지지 않고 잘 나왔다면, 에디터에서 설정된 character 값을 HTML header에 똑같이 선언해 주어야 한다. 개발 시에 툴에서 보이는 한글 데이터가 깨졌다면, 웹에서도 물론 깨지게 된다. 그 깨진 한글을 웹 애플리케이션에서 가공해 바로잡는 것은 한글 데이터가 나올 때와 들어갈 때 인코딩과 디코딩을 추가로 해주는 오버헤드가 발생한다. MySQL은 결과 값을 utf8로 출력해 주지만, console이 해석을 euckr로 해석한다면 역시 한글 데이터가 깨지게 된다. 제대로 받은 utf8 값을 무심코 HTML header에 contentType=“text/html; charset= euckr”로 선언해 euckr로 보여주는 페이지에 대해 getBytes()를 통해 바꿔 보여주고 euckr로 들어온 데이터를 다시 utf8로 저장한다면, 이는 HTML header에 contentType=”text/html; charset=utf8”이라고 선언하고 애플리케이션에서 아무 작업을 하지 않는 것에 비해 분명 잘못된 방법일 것이다. 다음의 예제를 보자.
Console setting : euckr
mysql> set names utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from profile limit 1 \G
*************************** 1. row ***************************
id: 13
user_id: newyark
daum_id: newyark
daum_name: ???댁???
name: ???명?밸???
real_name: ???명?밸???
tags: @@_talknetizen_??遺?-吏???泥?@@
만약 console setting이 utf8이었다면, 한글 데이터가 정확히 보였을 것이다. 하지만 무심코 설정된 console의 setting 때문에 우리는 한글 깨짐 현상을 만나야 했다. set names를 통해 character set은 맞췄지만, 해석하는 console에서 utf8의 데이터를 ecukr로 해석하기 때문에 우리가 자주 볼 수 있는 또 하나의 한글 데이터 깨짐 문제가G src="/images/know/0407_05.jpg" width=277 height=103>
Console setting : euckr
mysql> set names euckr;
Query OK, 0 rows affected (0.00 sec)
mysql> select * from profile limit 1 \G
*************************** 1. row ***************************
id: 13
user_id: newyark
daum_id: newyark
daum_name: 하이서울
name: 조민
real_name: 조민
tags: @@_talknetizen_화이팅_@@
데이터는 utf8이지만 set names euckr을 통해 character_ set_results의 값을 console setting 값인 euckr로 바꿔 주었고 MySQL은 utf8로 된 결과를 euckr로 변형해 출력해 준다. 우리는 그 결과를 euckr console로 확인하게 되므로 한글 데이터가 깨지지 않고 정상적으로 보이게 되는 것이다.
그렇다면 접속 시에 MySQL과 애플리케이션이 session을 맺는 순간 모든 애플리케이션에서 set names 명령어를 실행시켜야 할까? 이는 참 고통스러울 것이다. 위와 같은 이유로 MySQL은 session이 맺어지는 순간, 서버의 character set을 가져와 character_set_client, character_set_connection, character_ set_results를 서버의 character set으로 맞춰 주는 옵션이 존재한다. 그 옵션이 잘 알려지지는 않았지만 바로 skip-character-set-client-handshake라는 옵션이다. 직역한다면, clinet의 character set 옵션에 대한 약속을 무시한다는 의미이다. 이 옵션을 my.cnf에 추가하고 재접속 후 가장 처음 실행했던 쿼리를 다시 실행해 보자.
mysql> show variables like ‘character_set\_%’;
+--------------------------+--------+
| Variable_name | Value |
+--------------------------+--------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | utf8 |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
+--------------------------+--------+
7 rows in set (0.00 sec)
set names 명령어를 실행하지 않았음에도 불구하고 모두 character set의 값들이 utf8로 설정된 것을 확인할 수 있다. 이를 통해 우리는 프로젝트 진행시 HTML에서 보여주는 엔코딩만 utf8로 맞춰주면 한글 데이터가 깨져 보이는 것을 막을 수 있다. 만약 euckr로 프로젝트를 진행한다면 my.cnf 파일의 설정을 다음과 같이 설정하고, 보여주는 HTML header에서 charset =euckr이라고 명시하면 웹 애플리케이션에서 한글 엔코딩에 대한 별다른 노력 없이 한글 문제를 해결할 수 있다.
my.cnf
[mysqld]
skip-character-set-client-handshake
default-character-set = euckr
위 두 줄은 character set에 있어 엄청난 의미를 가진다. character set에 대한 아무런 옵션 없이 데이터베이스를 생성하거나 table을 만들면 모두 euckr로 생성되고(default-character-set = euckr) WAS 혹은 client가 접속시 모든 문자열의 주고받음은 default-character-set인 euckr(skip-character-set-client-handshake)임을 MySQL에게 알려준다. 우리가 데이터를 euckr로만 전달한다면, 한글 깨짐 현상은 100% 해결할 수 있다. 다음은 프로젝트 시작시 character set을 utf8로 설정하는 하나의 예이다.
- HTML
contentType=“text/html; charset=utf8” (console setting과 같다.)
테스트할 툴의 editor setting = utf8
- 웹 애플리케이션
- MySQL
default-character-set = utf8
skip-character-set-client-handshake
그렇다면 MySQL의 character set은 왜 이렇게 복잡한 것일까? 그 이유는 데이터베이스의 최대 성능 향상에 있다. 거의 모든 성능 개선 관련 자료들을 확인해 보면, 가장 먼저 나오는 이야기가 ‘데이터량을 줄여라’이다. 데이터량을 줄이지 못하면 DBMS가 처리하는 단계 중 가장 많은 시간 지연을 초래하게 되는 하드디스크와 메모리간의 I/O가 많이 발생하게 된다. 또한 CPU 역시 필요치 않는 오버헤드를 발생시키게 된다. utf8에서 한글은 한 글자당 3바이트를 차지하게 되는데, euckr로 할 경우 한글자당 2바이트를 차지하게 된다. 이 때문에 MySQL의 성능을 최대로 고려한 프로젝트에서는 아직도 프로젝트 생성시 character 설정을 euckr로 많이 가져가고 있다. 그렇다면 이러한 프로젝트의 경우 euckr에서 받을 수 없는 문자인 다국어 등은 어떻게 대응해야 할까? 이와 같은 이유로 MySQL은 각 column마다 character set을 지정할 수 있고, 그 character set에 맞춰 적절하게 변환해 저장 가능하다.
예를 들어보자. 우리는 2개의 칼럼이 필요하다. 하나의 칼럼은 euckr로는 충분한 일반적인 한글과 영어, 숫자 데이터가 들어가고, 다른 칼럼에는 한글을 포함해 일본어, 중국어 데이터 등이 들어가야 한다.
mysql> create database cm charset euckr;
Query OK, 1 row affected (0.01 sec)
mysql> create table cm.tester(
-> col1 CHAR(1),
-> col2 CHAR(1) CHARSET utf8);
Query OK, 0 rows affected (0.01 sec)
mysql> show full columns from cm.tester;
+-------+---------+-----------------+
| Field | Type | Collation |
+-------+---------+-----------------+
| col1 | char(1) | euckr_korean_ci |
| col2 | char(1) | utf8_general_ci |
+-------+---------+-----------------+
2 rows in set (0.00 sec)
우? 저장해야 할 필요성이 있을 때, 그 칼럼 하나에 대해서만 utf8로 지정하면 된다. 그럼 col1과 col2에 대해 한글을 저장할 때 어떻게 해야 할까? 이를 위해 MySQL은 여러 character set에 대한 설정을 하고 있다. MySQL은 저장하는 시점에서 client의 character set을 확인하기 때문에 웹 애플리케이션에서 들어온 character set이 euckr이었다면 col1은 그대로 저장하고, col2에 대해서는 utf8로 인코딩해서 저장하게 된다. 밖으로 보낼 때도 같은 과정을 겪는다. 데이터베이스에 저장된 character set을 확인하고 character_set_results의 설정을 확인한다. col2의 경우 utf8로 저장된 것을 확인하고 character_set_results의 값인 euckr로 다시 디코딩해서 보내주게 된다. 이와 같은 이유로 MySQL은 character set을 세분화하고 웹 애플리케이션의 성능을 최대로 이끌 수 있는 세심한 배려를 했다. 이러한 세심한 배려 덕분에 우리는 혼란에 빠졌고 한글을 제대로 사용할 수 없었다.
한글을 확인할 수 있다면 character set에 대한
모든 Migration이 가능
요즘 다국어를 지원하거나 더 큰 프로젝트를 위한 데이터 마이그레이션(data migration) 혹은 좀 더 나은 성능을 위한 utf8에서 euckr로의 마이그레이션이 많이 진행된다. euckr로 된 데이터를 어떻게 utf8로 바꿀 수 있을까? 답은 의외로 간단하다. 내가 dump된 데이터를 열어봤을 때 한글을 확인할 수 있다면, character set에 대한 마이그레이션은 간단하게 진행될 수 있다. 그렇다면 어떻게 한글을 확인할 수 있는지 확인해 보자. 먼저 euckr로 된 데이터를 mysqldump 유틸리티를 이용해 받아보자. dump는 내가 한글을 확인할 수 있도록 default character set=utf8 옵션을 주고 utf8 console에서 확인한다. mysqldump는 default-character-set=utf8 옵션을 주게 되면 모든 euckr 데이터들을 utf8로 변환해 뽑아준다. 위의 데이터들을 utf8 console에서 확인하면, Insert into bbb values(‘1’,’이유씨케알’);과 같이 정상적인 한글을 확인할 수 있다.
이제 기존의 euckr로 지정된 데이터베이스와 table들을 utf8로 만드는 과정이 필요하다. 이 과정은 의외로 간단하다. sed 명령어를 통해 sed ‘s/CHARACTER SET euckr/CHARACTER SET utf8/g’ fulldump.sql | sed ‘s/CHARSET=euckr/CHARSET= utf8/g’| /db/mysql/bin/mysql -uroot -pxxx와 같이 실행해 주면 된다. DDL 문에 대한 character set을 변환해 실행하기 때문에 데이터베이스와 table을 만드는 과정에서 기존의 euckr로 되어 있던 데이터베이스와 table 생성구문이 utf8을 기본으로 하는 데이터베이스와 table로 만들어지게 된다. 또한 mysqldump 실행시 주었던 default-character-set=utf8의 옵션에 의해 dump 데이터의 header 부문에 /*!40101 SET NAMES utf8*/;라는 명령어가 들어가게 되는데, 이는 자신이 집어넣는 데이터는 utf8임을 명시하는 효과를 준다.
이 예제를 다음과 같이 정리할 수 있다.
1. Source 파일에서 다음과 같이 데이터를 export해 온다.
mysqldump -- default-character-set=utf8 --single-transaction --opt --allow-keywords -all-databases --add-drop-table -uroot --password=‘xxx’ > fulldump.sql 2. fulldump.sql 파일을 target 서버로 이동한다.
3. euckr로 되어 있었던 데이터베이스와 table 생성구문을 utf8로 바꾼다.
sed ‘s/CHARACTER SET euckr/CHARACTER SET utf8/g’ fulldump.sql | sed ‘s/CHARSET= euckr/CHARSET=utf8/g’| /db/mysql/ bin/mysql -uroot -pxxx;
utf8 console에서 한글을 확인할 수 있다면 MySQL도 /*!40101 SET NAMES utf8*/;를 통해 앞으로 들어오는 데이터가 한글임을 확인할 수 있도록 해준다. 여기서 “/*!40101 SET NAMES utf8*/;”의 의미가 MySQL에서 쓰이는 주석이 아님을 혼동하지 말아야 할 것이다. 그럼 필자가 MySQL character set에 관한 트러블 슈팅(trouble shoot ing) 중 어렵게 해결했었던 사례를 소개해 보고자 한다.
이 경우도 character set의 기본 원리를 이해하면 간단하지만 원리를 이해하지 못하고 접근한다면, 더욱 난항에 빠졌을 것이다. latin1 데이터베이스와 table에 euckr의 한글 데이터가 들어있는 경우를 생각해 보자. 어떻게 latin1에 euckr의 데이터가 들어갈 수 있었을까? 프로젝트 생성시 MySQL을 띄우는 과정에서 아무런 옵션 없이 default 값으로 띄우고 table 역시 아무런 옵션 없이 default 값으로 만들게 된다. 하지만 그 table은 default character set인 latin1으로 생성되고, 웹 애플리케이션에서도 역시 character set에 대한 아무런 옵션 없이 connection이 맺어졌기 때문에 MySQL은 character_ set_client, character_set_connection, character_set _results를 latin1으로 설정하게 된다. 물론 데이터는 euckr이지만, MySQL은 데이터베이스가 latin1이고 들어오는 데이터도 latin1이라고 가정하기 때문에 아무런 인코딩 없이 저장하게 된다. 즉 들어온 스트림 그대로를 저장하고 내보내는 것이다. 위의 상황에서 보여주는 HTML 쪽 설정을 charset=euckr로 한다면, 웹에서 들어왔던 그대로의 데이터를 보여주고 한글 깨짐 없이 잘 보이게 된다. 이것이 우리가 자주 하는 실수인데 사용할 때는 문제가 없지만, 이 데이터를 필요에 의해 분석하거나 마이그레이션할 시에는 어려운 문제에 봉착하게 된다. 이러한 경우 어떻게 마이그레이션을 할 수 있는지 알아보자. 앞의 내용을 이해했다면, 해결책을 찾을 수 있다. 이해하지 못했다면 다음의 예제를 통해 정확히 이해해 보자. 먼저 dump data를 저장했던 stream 그대로 가져오기 위해 dump시 default-character-set= latin1 옵션을 준다. 그 이유는 latin1에는 다른 한글 character set으로 가기 위한 맵핑 코드가 없기 때문에 euckr이나 utf8로 변형시 잘못된 글자로 해석해 버린다. 웹에서 보냈던 그대로를 받아내기 위해 default-character-set= latin1의 설정이 꼭 필요하다. 옵션을 통해 dump를 받은 후 확인해보자. Utf8 console에서는 Insert into bbb values(‘1’,‘’)에서와 같이 깨지는 것을 확인할 수 있다. 데이터는 stream 그대로 euckr 코드이나 해석을 utf8로 했기 때문이다. 그럼 console을 euckr로 맞추고 다시 확같이 한글 데이터가 제대로 나오고 있는 것을 확인할 수 있다. euckr 데이터를 euckr console에서 확인했기 때문이다. 이렇게 한글을 확인할 수 있었다면, 추가로 해줘야 하는 작업이 있다. 우리가 처음 default-character-set=latin1이라는 옵션을 주었기 때문에 dump된 파일의 header에는 /*!40101 SET NAMES latin1*/;라고 쓰여 있는 것을 확인할 수 있다. 하지만 우리는 euckr의 console에서 한글을 확인할 수 있었기 때문에, MySQL에게도 위의 데이터가 euckr임을 알 수 있도록 /*!40101 SET NAMES latin1*/;을 /*!40101 SET NAMES euckr*/;로 바꿔준다. 이렇게 바꿔준 후 sed ‘s/”CHARACTER SET latin1”/”CHARACTER SET utf8”/g’ | sed ‘s/”CHARSET=latin1”/”CHARSET=utf8”/g’ | /db/mysql/bin/mysql -uroot -pxxx라는 명령어를 실행해 주면 table 생성시 MySQL은 latin1으로 만들었던 table을 utf8로 만들게 되고 앞으로 들어올 데이터가 euckr이라는 것을 인지하게 된다. 위와 같이 데이터를 집어넣을 시 데이터가 들어가야 할 공간은
utf8이고 들어오는 데이터가 euckr이므로 MySQL은 euckr 데이터를 다시 utf8로 변환해 저장하게 된다. 이로써 latin1의 데이터베이스에 들어 있는 euckr 데이터를 utf8 데이터베이스의 utf8 데이터로 마이그레이션이 무사히 끝나게 된다.
위의 예제를 다음과 같이 정리할 수 있다.
1. Source 파일에서 다음과 같이 데이터를 export해 온다.
mysqldump -- default-character-set=latin1 --single-transaction --opt --allow-keywords -all-databases --add-drop-table -uroot --password=’xxx’ > fulldump.sql
2. fulldump.sql 파일을 target 서버로 이동한다.
3. Fulldump.sql 파일을 열어 /*!40101 SET NAMES latin1*/;라고 쓰인 부문을 /*!40101 SET NAMES utf8*/;로 바꾼다.
4. euckr로 되어 있었던 데이터베이스와 table 생성구문을 utf8로 바꾼다.
sed ‘s/CHARACTER SET euckr/CHARACTER SET utf8/g’ fulldump.sql | sed ‘s/CHARSET=euckr/CHARSET=utf8/g’| /db/mysql/bin/mysql -uroot -pxxx;
물론 euckr로 마이그레이션하고 싶다면, sed ‘s/”CHARACTER SET latin1”/”CHARACTER SET utf8”/g’ | sed ‘s/”CHARSET=latin1”/”CHARSET=utf8”/g’ | /db/mysql/bin/mysql -uroot -pxxx 부분에서 utf8을 euckr로 바꿔주기만 하면 된다. 그렇게 되면 MySQL은 데이터베이스가 euckr이므로 들어오는 데이터에 대해 아무런 변환 없이 저장하게 되고 euckr로의 마이그레이션은 성공하게 된다.
마치면서
일반적으로 MySQL을 많이 접하지 못한 개발자들로부터 다음과 같은 요청을 많이 받는다. “MySQL은 느려서 못 쓰겠어요. 다른 데이터베이스로 바꿔주세요.” 이러한 이야기를 듣고 그 서버에 접속해 서버를 살펴보면 엔진을 InnoDB만 사용하면서 메모리의 반을 MyISAM에 설정해 두거나, query cache가 꼭 필요한 상황에도 값을 제대로 설정하지 못해 오히려 더 느려지는 경우를 많이 본다. 물론 설정 값의 의미를 하나하나 알 수 없어서 MySQL에서 제공하는 default 설정 파일을 많이 사용하게 되어 발생한 현상들임을 알고 있다. 그러나 MySQL에 조금만 흥미를 가지고 주의를 기울인다면, 여느 DBMS보다 더 빠른 성능으로 사용할 수도 있다. 심지어 MySQL은 character set에 관해 아주 작은 성능 차이일지라도 그 성능을 위해 설치할 때 꼭 필요한 character set만을 인스톨할 수 있도록 옵션을 제시해 주기도 한다.
필자소개
조민 jo.min@hanmail.net병역특례로 3년간 자바 개발을 하고 다음커뮤니케이션에 입사 후 DBA로서 MySQL과 오라클, 프로젝트에 대한 개발 지원을 수행했다. 이후 MySQL의 매력에 빠져 MySQL CELL에서 최적 성능 발휘를 위한 연구를 진행 중이다. 얼굴은 개성이 아주 뚜렷함.
'프로그래밍 > SQL' 카테고리의 다른 글
SQLite 속도 비교 (PostgreSQL, MySQL, SQLite, SQLite<nosync>) (0) | 2011.11.10 |
---|---|
데이터베이스 명명법 (0) | 2011.10.31 |
trigger를 이용해 sqlite에서 foreign key를 사용하자! (1) | 2011.08.16 |
[SQL] 제약조건, Constraint(NOT NULL, UNIQUE, PRIMARY KEY(기본키), FOREIGN KEY(외래키)) (0) | 2011.08.16 |
SQL 언어의 종류 (0) | 2011.08.15 |