Reminiscence

 

multidump.zip

 

제목은 거창한데.. 내용은 별거 없네요.. ^^;

우리 회사에서 운영중인 특정 시스템의 경우 하나의 MySQL DB 서버에 약 2천여개의 DB를 가지고 있습니다.

뭐.. 용량은 서버마다 각각 다르지만, 대략 300GB ~ 500GB 사이를 왔다갔다 하는 서버죠

그런데 이 DB 엔진이 MyISAM으로 되어 있고, 이걸 InnoDB로 변경하면서 서버 교체까지 한번에 진행해야 하는 문제가 생깁니다.

이에 mysqldump로 힘들게 덤프 떠보니 속도가 너무 꽝이네요 .. -ㅠ - ;;

그래서 만들었습니다. 멀티쓰레드 덤프 ㅡ.,ㅡ;;

 

내용은 별거 없고 기본적인 흐름은 다음과 같습니다.

1. 현재 DB 서버 내 전체 데이터베이스 목록을 파일로 만든다.

2. 각 데이터베이스 이름마다 child process를 생성한다.

3. 각 child process에서 백업 작업이 끝나면, 목록에서 자신의 DB 명을 지우고 종료 한다.

 

간단한 스크립트라 공개하기에도 민망한데 필요하신 분들이 혹(?) 계실지도 모르니.. ^^;

 

###############

## multidump.sh  #

###############

## 4core MULTIDUMP SCRIPT

#!/bin/bash

 

remove_list() {

        sed -e "/^${DBNAME}$/d" $DB_LIST_FILE >> TMPFILE1;

        rm -f $DB_LIST_FILE;

        mv TMPFILE1 $DB_LIST_FILE;

echo "$DBNAME" >> RESTORE_LIST;

}

 

export c_black='\033[0m'

export c_boldblack='\033[1;0m'

export c_red='\033[31m'

export c_boldred='\033[1;31m'

export c_green='\033[32m'

export c_boldgreen='\033[1;32m'

export c_yellow='\033[33m'

export c_boldyellow='\033[1;33m'

export c_blue='\033[34m'

export c_boldblue='\033[1;34m'

export c_magenta='\033[35m'

export c_boldmagenta='\033[1;35m'

export c_cyan='\033[36m'

export c_boldcyan='\033[1;36m'

export c_white='\033[37m'

export c_boldwhite='\033[1;37m'

export c_colorend='\033[0m'

 

cecho ()

{

        local default_msg="No Message Passed."

 

        message=${1:-$default_msg}

        color=${2:-black}

 

        case $color in

                black)

                         printf "$c_black" ;;

                boldblack)

                         printf "$c_boldblack" ;;

                green)

                         printf "$c_green" ;;

                boldgreen)

                         printf "$c_boldgreen" ;;

                red)

                         printf "$c_red" ;;

                boldred)

                         printf "$c_boldred" ;;

                yellow)

                         printf "$c_yellow" ;;

                boldyellow)

                         printf "$c_boldyellow" ;;

                blue)

                         printf "$c_blue" ;;

                boldblue)

                         printf "$c_boldblue" ;;

                magenta)

                         printf "$c_magenta" ;;

                boldmagenta)

                         printf "$c_boldmagenta" ;;

                cyan)

                         printf "$c_cyan" ;;

                boldcyan)

                         printf "$c_boldcyan" ;;

                white)

                         printf "$c_white" ;;

                boldwhite)

                        printf "$c_boldwhite" ;;

        esac

        printf "%s$c_colorend\n" "$message"

}

 

dump_list(){

 

DISABLE_DB_LIST="information_schema mysql performance_schema sysbench test vsftp webmail webmail_admin wordlist";

 

mysql -h $DUMP_HOST -Ne "show databases" >> db_list;

for INF in $DISABLE_DB_LIST;do

        sed -e "/^${INF}$/d" db_list >> tmp_list

        rm -f db_list;

        mv tmp_list db_list;

done;

 

}

 

# 임시 파일 생성

cecho "==== Temporary file create ====" boldgreen

echo "1" >> PROC_TMP1;

echo "1" >> PROC_TMP2;

echo "1" >> PROC_TMP3;

echo "1" >> PROC_TMP4;

 

CNT="0"

DB_LIST_FILE="./db_list"

CHILD_BIN="./multidump_child.sh"

DUMP_HOST="192.168.1.15"

S_DATE=`date +"%Y-%m-%d %H:%M:%S"`

 

# DB LIST OUTPUT

cecho "==== START TIME : ${S_DATE} ====" boldgreen

cecho "==== Backup target listing ====" boldgreen

dump_list;

TOTAL_RUN=`cat $DB_LIST_FILE | wc -l`

sleep 1;

 

 

while (( `cat $DB_LIST_FILE | wc -l` ))

do

        sleep 1;

 

        DBNAME=`tail -n 1 $DB_LIST_FILE`;

 

        if [ -s PROC_TMP1 ]

        then

                cat /dev/null > PROC_TMP1;

                CNT=`expr $CNT + 1`

                cecho "  * ($CNT/$TOTAL_RUN) : $DBNAME DUMP 실행 " boldblue

                $CHILD_BIN $DBNAME PROC_TMP1 $DUMP_HOST &

                remove_list

        elif [ -s PROC_TMP2 ]

        then

                cat /dev/null > PROC_TMP2;

                CNT=`expr $CNT + 1`

                cecho "  * ($CNT/$TOTAL_RUN) : $DBNAME DUMP 실행 " boldblue

                $CHILD_BIN $DBNAME PROC_TMP2 $DUMP_HOST &

                remove_list

        elif [ -s PROC_TMP3 ]

        then

                cat /dev/null > PROC_TMP3;

                CNT=`expr $CNT + 1`

                cecho "  * ($CNT/$TOTAL_RUN) : $DBNAME DUMP 실행 " boldblue

                $CHILD_BIN $DBNAME PROC_TMP3 $DUMP_HOST &

                remove_list

        elif [ -s PROC_TMP4 ]

        then

                cat /dev/null > PROC_TMP4;

                CNT=`expr $CNT + 1`

                cecho "  * ($CNT/$TOTAL_RUN) : $DBNAME DUMP 실행 " boldblue

                $CHILD_BIN $DBNAME PROC_TMP4 $DUMP_HOST &

                remove_list

        else

                cecho "==== 현재 모든 프로세스가 처리 중입니다. ====" boldwhite

        fi

done

 

rm -f PROC_TMP*;

 

cecho "==== START TIME : ${S_DATE} ====" boldgreen

S_DATE=`date +"%Y-%m-%d %H:%M:%S"`

cecho "==== END TIME : ${S_DATE} ====" boldgreen

 

여기까지가 메인 스크립트이구요.. 아래는 multidump_child.sh 스크립트 입니다.

####################

## multidump_child.sh ##

####################

## MULTIDUMP CHILD SCRIPT

## Dump 하면서 sed를 이용해 백업되는 데이터의 Engine Type을 InnoDB로 변경한다.

 

#!/bin/bash

/usr/local/mysql/bin/mysqldump -h $3 --force -c $1 | sed "s/ENGINE=MyISAM/ENGINE=InnoDB/g" >> /backup/MULTI_DUMP/${1}_dump.sql

echo "$1" >> $2;

 

지금도 가끔 쓰는 스크립트지만, 그때 그때 수정해서 필요한 부분에 맞게 맞춰서 쓰고 있구요..

그냥 mysqldump로 뜨는것보단 한 2배에서 2.5배 정도 빠르네요..

Sed로 치환처리 안하면 좀 더 빠릅니다. ;;

 

위에는 4개 스레드를 기본으로 한건데 8개로 하면 쪼~~~~끔 더 빨라지니.. 필요에 따라.. =_=;;;

저작자 표시
신고

댓글 0개가 달렸습니다.

회사에서 운영중인 서버중 MySQL을 사용하는 DB 서버만 대략 100여대 가량이다 보니(다 제각각이에요 ㅠ_ㅠ) 가끔씩 오류로 인해 서버가 다운되거나 MySQL 데몬이 죽었을때 테이블이 깨지는 경우가 발생 하곤 합니다. ㅠ _ㅠ

하나하나 찾아서 Repair 하기도 어렵기도 하고 귀찮기도 하고.. 그냥 간단하게 스크립트로 Check 해서 결과를 리턴하는 형식의 스크립트를 짰는데..

결과를 보는게 조금 엉성 하네요.. =ㅠ = ;; 꾸미는데에는 재주가 없어서;; ㅎㅎ

필요하신 분들은 가져가셔서 사용하시고.. 퍼가실때에는 출처만 밝혀주세요 +_+ ㅎㅎ

더보기



이게.. VI에서 탭으로 구분해 놓은걸 그대로 가져왔더니 이렇게 올라가네요;; =ㅠ=;;
저작자 표시 비영리
신고

댓글 0개가 달렸습니다.

잘 동작하던 메일 스팸서버의 DB가 갑자기 데이터가 쌓이지 않기 시작 했다..
원인은 알 수 없었고.. 이리 저리 뒤져보았더니 MySQL의 경우 Linux 시스템에 따라 MyISAM 엔진이 저장할 수 있는 최대 데테이블 데이터 사이즈가 지정되어 있다고 한다.

Operating System File-size Limit
Win32 w/ FAT/FAT32 2GB/4GB
Win32 w/ NTFS 2TB (possibly larger)
Linux 2.2-Intel 32-bit 2GB (LFS: 4GB)
Linux 2.4+ (using ext3 file system) 4TB
Solaris 9/10 16TB
MacOS X w/ HFS+ 2TB
NetWare w/NSS file system 8TB

- 관련 문서 : http://dev.mysql.com/doc/refman/5.0/en/full-table.html

우선 서버에서 해당 테이블의 상태를 확인하기 위해 아래와 같이 명령어를 실행..
mysql> show table status like 'mail_content' \G
*************************** 1. row ***************************
           Name: mail_content
         Engine: MyISAM
        Version: 9
     Row_format: Dynamic
           Rows: 548249
 Avg_row_length: 7833
    Data_length: 4294967280
Max_data_length: 4294967295
   Index_length: 40935424
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2008-04-24 11:31:01
    Update_time: 2010-07-27 11:53:13
     Check_time: 2010-05-12 09:50:03
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.00 sec)

상태를 보니 이미 MAX_data_Length값인 4G까지 모두 사용중이네요..
20G 까지 테이블 사이즈를 늘리기 위해 다음 명령어를 실행...하였습니다.

 alter table mail_content MAX_ROWS=1000000 AVG_ROW_LENGTH=21474;

위의 내용을 보면 최대 행(Row)는 1,000,000개 까지 저장 가능하도록 하였고, 각 행의 평균 길이는 21474 Byte로 지정 하였습니다.
이 명령어는 다음 내용을 참조하여 생성 하였습니다.

MySQL의 MyISAM 스토리지 엔진의 데이터 테이블의 전체 크기는 [SHOW variables]명령을 통해 확인 할 수 있는 myisam_data_pointer_size 라는 값에 의하여 결정 된다고 합니다.

이 myisam_data_pointer_size는 최소 2부터 최대 7까지 값을 가지고 있으며, 이 값을 참조하여 다음 공식에 의해 테이블 사이즈의 최대 크기를 지정 할 수 있습니다.

[ 2 ^ ( myisam_data_pointer_size * 8 ) - 1 byte ]

위의 공식을 따라 기본값인 4를 대입하면 4Gbyte까지 생성 할 수 있음을 알 수 있습니다.
문제는 이 값을 임의로 수정하는 것이 아닌 Alter Table 또는 Create Table 명령을 사용할 때 MAX_ROWS 와 AVG_ROW_LENGTH 값을 변경 하면 myisam_data_pointer_size 값이 자동으로 변경 된다는 것 입니다.

그럼 제가 원하는 20G 사이즈의 테이블을 생성하기 위해서는 어떻게 해야 할까요?
다음의 3가지 방식의 명령 모두 20G 사이즈의 테이블로 수정하는 명령입니다.

명령 1 : ALTER TABLE mail_content MAX_ROWS=1 AVG_ROW_LENGTH=21474836480
명령 2 : ALTER TABLE mail_content MAX_ROWS=20971520 AVG_ROW_LENGTH=1024
명령 3 : ALTER TABLE mail_content MAX_ROWS=1000000 AVG_ROW_LENGTH=21474

위의 3가지 방식의 명령 모두 20G 사이즈의 테이블을 생성하는 명령어 입니다.
자신이 원하는 방식을 이용하면 되겠지만, 테이블의 내용에 따라서 이 명령어를 다르게 적용하여 주는 것이 더 좋습니다.

예를 들어 테이블의 데이터 타입이 BLOB 또는 TEXT 일 경우에는 MAX_ROWS를 일정 수치이하로 줄이고 AVG_ROW_LENGTH 값을 늘려주는 것이 좋습니다.
다른 예로 테이블의 데이터 타입이 Integer 또는 Boolean과 같은 데이터 사이즈가 작은 경우라면 MAX_ROWS값을 늘리고 AVG_ROW_LENGTH값을 줄이는 것이 더 효과적입니다.


결론을 내리자면, 테이블의 사이즈를 변경하는 것은 ALTER TABLE 또는 CREATE TABLE 명령을 이용하여 MAX_ROWS값과 AVG_ROW_LENGTH값을 주게되면 myisam_data_pointer_size 값이 변경되면서 자연적으로 적용되게 됩니다.

만약 ALTER TABLE을 사용하는 경우라면 테이블 사이즈에 따라 또는 테이블 내 행의 개수에 따라 작업 시간을 조율 하시기 바랍니다.

저같은 경우 4G의 데이터 파일을 ALTER TABLE로 수정하는데 약 12분 가량 소요되었고, 그 시간동안에는 해당 테이블에 Lock이 걸리게 되므로, 약간의 장애 유사한 현상이 발생했었습니다. ^^*

참고 하세요~ =ㅁ=

신고

댓글 0개가 달렸습니다.

서버 관리를 해주다보면.. 참 어처구니 없는 일들이 많이 일어난다.

오늘의 문제는 다음과 같은 에러가 뜨는것.....

/usr/bin/perl: relocation error: /usr/lib/perl5/vendor_perl/5.8.8/i386-linux-thread-multi/auto/DBD/mysql/mysql.so: symbol mysql_init, version libmysqlclient_15 not defined in file libmysqlclient.so.15 with link time reference

구글을 찾아보고 이것 저것 해봤는데..
고객 서버의 구성이 참 독특하기도 하고, 서비스가 죽으면 안된다는 이야기...
원인은 perl에서 MySQL커넥션을 위한 라이브러리를 찾을때 MySQL의 라이브러리를 찾지 못한다는 이야기 인데..

머 에러야 그렇다고 치자..

원인을 찾아 /usr/lib/mysql을 찾았는데..
엥?? 폴더가 없다.. -_-;;;;;;

어쩌라는거지;;;

ldd /usr/bin/mysqlbinlog를 해보니 libmysqlclient.so.15의 경로가 들어가 있어야 할 자리에.. 아무런 내용이 없다.

쩝.. 그냥 mysql을 재설치 하면 간단하게 해결이 되겠지만..
고객은 MySQL서버가 단 1초라도 죽으면 안된단다 ..

그래서 내린 특단의 야매 조치..

동일한 OS를 Virtual Box를 이용해 설치 한 뒤 동일한 버전의 MySQL을 설치.
그리고 /usr/lib에 있는 mysql 폴더를 통째로 압축.
문제의 서버로 압축파일 전송 후 압축 해제.

perl 에러가 발생한 파일을 다시 확인해 보니 정상 동작.

후...... /usr/lib/mysql을 왜 지웠을까.. '_' ?
신고

댓글 0개가 달렸습니다.

얼마전 회사 DB서버의 Replication이 깨지는 바람에 복구하게 됐다.

실제 운영중인 서버를 다운 시키고 백업 받을수는 없었기 때문에 최단시간동안 Write Lock을 걸고 백업을 받은 후 Write Lock을 해제하고 리플리케이션을 설정하는것이 관건 이었다.

그래서 다음과 같은 작업을 진행..

/usr/local/mysql/bin/mysqladmin -uroot -p flush-logs
/usr/local/mysql/bin/mysqladmin -uroot -p -C "flush tables with read lock"
/usr/local/mysql/bin/mysqldump --single-transaction --all-databases --extended-insert=FALSE -c -uroot -p -R > all-databases.sql


또는

/usr/local/mysql/bin/mysqladmin -uroot -p flush-logs
/usr/local/mysql/bin/mysql -u root -p -h localhost
Passwd :
MySQL > flush tables with read lock;
MySQL > show master status\G
+------------------+----------+--------------+------------------+
| File                     | Position   | Binlog_Do_DB | Binlog_Ignore_DB |
+------------------+----------+--------------+------------------+
| mysql-bin.000011  |   1024026  |                      |                          |
+------------------+----------+--------------+------------------+
1 row in set (0.00 sec)
# 위의 MASTER STATUS 정보는 별도로 저장해 두자.

/usr/local/mysql/bin/mysqldump --single-transaction --all-databases --extended-insert=FALSE -c -uroot -p -R > all-databases.sql

이제 백업된 파일이 생성이 되었다.
그렇다면, 슬레이브 서버에 접속하여 백업된 파일을 업로드 하고 Slave 셋팅 설정을 확인한다.


server-id = 2

master-host = 마스터서버IP

master-user = <계정>

master-password = <비밀번호>

셋팅값에 이상이 없으면 백업한 파일을 Restore 한다.

/etc/init.d/mysql restart
/usr/local/mysql/bin/mysql -u root -p
/usr/local/mysql/bin/mysql -u root -p < all-databases.sql

복구 작업이 모두 완료 되면 다음 명령어를 통해 recplication을 실행한다.

mysql> stop slave;
mysql> reset slave;
mysql> CHANGE MASTER TO MASTER_LOG_FILE="mysql-bin.000011", MASTER_POS='1024026';
mysql> start slave;
mysql> show slave status\G
            Slave_IO_State: Waiting for master to send event
               Master_Host: 마스터서버IP
               Master_User: repl
               Master_Port: 3306
             Connect_Retry: 60
           Master_Log_File: mysql-bin.000011
       Read_Master_Log_Pos: 1024026
            Relay_Log_File: mysqld-relay-bin.000002
             Relay_Log_Pos: 402402
     Relay_Master_Log_File: mysql-bin.000011
          Slave_IO_Running: Yes
         Slave_SQL_Running: Yes
           Replicate_Do_DB:
       Replicate_Ignore_DB:
        Replicate_Do_Table:
    Replicate_Ignore_Table:
  Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
                Last_Errno: 0
                Last_Error:
              Skip_Counter: 0
       Exec_Master_Log_Pos: 1024026
           Relay_Log_Space: 402402
           Until_Condition: None
            Until_Log_File:
             Until_Log_Pos: 0
        Master_SSL_Allowed: No
        Master_SSL_CA_File:
        Master_SSL_CA_Path:
           Master_SSL_Cert:
         Master_SSL_Cipher:
            Master_SSL_Key:
     Seconds_Behind_Master: 0
1 row in set (0.00 sec)


출력된 데이터 중 Slave_IO_State가 Waiting for master to send event와 같으면 정상적인 리플리케이션이 동작하는 것이다.

만약 DB데이터의 양이 너무 많아 mysqldump로 백업 및 복구에 시간이 많이 소요된다면, MySQL의 MASTER/SLAVE 서버간의 버전이 동일하다는 가정하에, DB_DATA폴더를 통째로 압축하여 전송한뒤 압축 해제를 통해 복사하는것도 좋은 방법일 수 있다.


신고

댓글 0개가 달렸습니다.

가끔씩 고객들이 load data infile할때 권한이 없다는 문의를 해온다.
작년에 이와 같은 문제로 해결해 준적이 있었는데 올해들어 이것저것 하다보니 까먹어 버렸었다;; 그러다 오랜만에 찾아보니 아래와 같이 나와있네.. ㅋ

1) load data infile '파일명' into table 테이블명
2) load data local infile '파일명' into table 테이블명


두 문장의 차이는 불러오려는 파일이 MySQL 서버에 있느냐? 아니면 원격에서 접속해서 처리하느냐이다.

local 명령어를 추가해서 사용할 경우에는 서버와 클라이언트 모두 local-infile옵션이 on으로 되어 있어야만 사용가능 하며 그에 따른 확인은 아래와 같이 할 수 있다.

mysql> show variables like 'local%';
위와 같은 명령어를 내렸을때 local-infileOn 으로 되어 있으면 사용이 가능한거다.

클라이언트에서 연결할때 사용하는 명령어는 아래와 같다.
$> mysql -u 아이디 -p -h 서버명 DB명 --local-infile=1

신고

댓글 0개가 달렸습니다.

Client does not support authentication protocol requested by server와 같은 메세지를 내뿜으며 MySQL서버에 접속되지 않는 경우. 아래와 같이 해보세요~

MySQL 4.1 이상 버전에서는 비밀번호를 해쉬알고리즘을 기반으로한 인증 프로토콜을 사용합니다.
그리고 해당 기능이 하위버전의 Client와 호환이 되지 않기에 서버를 4.1이상으로 업그레이드를 한 후에 아래와 같은 에러메세지를 접하게 될수 있습니다.

shell> mysql
Client does not support authentication protocol requested
by server; consider upgrading MySQL client

위의 문제점을 해결하기 위해서는

1. 모든 Client 프로그램을 4.1이상으로 업그레이드한다.
2. 사용하려는 계정을 4.1 이전 Client 프로그램과 통신이 가능한 이전 비밀번호 체계로 변경한다.

mysql> SET PASSWORD FOR
-> 'some_user'@'some_host' = OLD_PASSWORD('newpwd');

Alternatively, use UPDATE and FLUSH PRIVILEGES:

mysql> UPDATE mysql.user SET Password = OLD_PASSWORD('newpwd')
-> WHERE Host = 'some_host' AND User = 'some_user';
mysql> FLUSH PRIVILEGES;

3. --old-passwords 옵션으로 서버를 이전비밀번호 체계로 실행한다.

4.1 이후 비밀번호를 사용하는 계정을 모두 변경처리 한다.

SELECT Host, User, Password FROM mysql.user
-> WHERE LENGTH(Password) > 16;
신고

댓글 0개가 달렸습니다.

한글로된 MySQL 5.0 레퍼런스 메뉴얼이 있는 사이트 입니다.

모르는 사항이나 영문판으로 궁금한 사항이 있을때 참조하면 이해가 빠를꺼 같군요.

http://www.mysqlkorea.co.kr/develop/sub_01.html


MySQL Cert 관련 Dump 있으시거나, 관련 문서가 있으신 분은 제공 부탁드립니다.
신고

댓글 0개가 달렸습니다.

MySQL_reference_manual-4.1-en.pdf

MySQL 4.1 Reference Manual

신고

댓글 0개가 달렸습니다.

기존 MySQL 환경에서는 Database측 CHARSET 이 latin1 이나 euckr을 많이사용했을 겁니다.

Legacy DB쪽은 아무 생각없이 CREATE DATABASE ... ; 해버렸었던 경우가
많아서 latin1 으로 되어 있는 database가 저또한 엄청나게 많았습니다.

그런데, 이럴 경우 utf8을 제대로 쓸 수 없다거나, command line utility에서
꼭 문제가 발생하여서 utf8로 전환을 시도했습니다.

문제는 latin1 db에 client 는 utf8을 사용하고 있던 경우,
db에는 utf8로 들어가나, 정상적인 utf8이 아님으로써,
mysql 이나 query browser등에서 쿼리를 할 수 없었습니다.

한번은 잘못해서 database하나를 몽땅 못쓰게 만들어 버린 적도 있었죠.

이곳 게시판을 잘 읽어 본 결과 아래와 같이 하여 성공적으로 conversion을 하였습니다.

**. 준비물
vim 혹은 editplus 등 utf-8을 지원하거나, 변환가능한 editor
test한 MySQL 버젼 아무거나(기존), MySQL 4.1.12 , 5.0.16 (utf-8사용할 것)

A. DB는 latin1으로 만들어져 있고, client는 utf8을 사용하였던 경우

(1). 가장 먼저 mysql로 접속 한 후 use {database}, show variables like 'c%'; 로 확인을 합니다.
아마도 대부분 Database와 character_set_connection 이 latin1으로 되어 있을 겁니다.

(2). 기존 DB를 Dump받습니다.
mysqldump -u{username} -p{password} {dbname} --default-character-set latin1 > {dump}.sql
이때 Dump 받는 SQL은 database의 chracter set이 아니라, client가 실제로 사용한
character set. 즉 이경우에는 utf8로 저장되어 있게 됩니다.

(3). {dump}.sql 을 편집합니다.

3-1. SET NAMES latin1; 으로 되어 있는 놈을 SET NAMES utf8; 로 변경합니다.

3-2. CREATE DATABASE ..... DEFAULT CHARSET=latin1; 으로 되어 있는 놈을
CREATE DATABASE ..... DEFAULT CHARSET=utf8; 로 변경합니다.
vim 사용자라면, command line에서 1,$s/CHARSET=latin1/CHARSET=utf8/g 하면 바꿀 수 있습니다.
이렇게 하므로써, 다시 생성될 TABLE의 CHARSET도 utf8로 맞출 수 있게 됩니다.

(4). MySQL로 로그인 하여 새로 부어줄 DATABASE를 생성합니다.
CREATE DATABASE {utf8-dbname} DEFAULT CHARACTER SET utf8;

(5). dump 한 data를 부어넣습니다.
mysql -u{username} -p{password} {utf8-dbname} < {dump}.sql

B. DB는 latin1으로 만들어져 있고, client는 euckr을 사용하였던 경우
제로보드가 대표적인데, 다음과 같이 합니다.

(1). 가장 먼저 mysql로 접속 한 후 use {database}, show variables like 'c%'; 로 확인을 합니다.
아마도 대부분 Database와 character_set_connection 이 latin1으로되어 있을 겁니다.

(2). 기존 DB를 Dump받습니다.
mysqldump -u{username} -p{password} {dbname} --default-character-set latin1 > {dump}.sql
이때 Dump 받는 SQL은 database의 chracter set이 아니라, client가 실제로 사용한
character set. 즉 이경우에는 euckr로 저장되어 있게 됩니다.

(3). {dump}.sql 을 편집합니다.

3-1. SET NAMES latin1; 으로 되어 있는 놈을 SET NAMES euckr; 로 변경합니다.

3-2. CREATE DATABASE ..... DEFAULT CHARSET=latin1; 으로 되어 있는 놈을
CREATE DATABASE ..... DEFAULT CHARSET=utf8; 로 변경합니다.

vim 사용자라면, command line에서 1,$s/CHARSET=latin1/CHARSET=utf8/g
하면 바꿀 수 있습니다.
이렇게 하므로써, 다시 생성될 TABLE의 CHARSET도 utf8로 맞출 수 있게 됩니다.

(4). MySQL로 로그인 하여 새로 부어줄 DATABASE를 생성합니다.
CREATE DATABASE {utf8-dbname} DEFAULT CHARACTER SET utf8;

(5). dump 한 data를 부어넣습니다.
mysql -u{username} -p{password} {utf8-dbname} < {dump}.sql

C. 모두 끝난 다음에 절차...
이 게시판에 많이 나와 있는 방법대로 했습니다. 더 좋은방법도 있을 겁니다.
/{mysqld-my.cnf path}/my.cnf

[client]
default-character-set=utf8

[mysqld]
init_connect=SET collation_connection=utf8_general_ci
init_connect=SET NAMES utf8
default-character-set=utf8
character-set-server=utf8
collation-server=utf8_general_ci

로 바꾸어 줍니다.
/{init script path}/{init script} restart
아마 리눅스 사용자면 /etc/init.d/mysqld restart 일 것이고,
저처럼 NetBSD 사용자이면 /etc/rc.d/mysql restart 일겁니다.

D. client application의 접속단 변경...
Legacy 프로그램때문에 문제가 되는 게 많은데,
제로 보드의 경우 다음과 같이 바꾸어 줍니다.

{Zeroboard installed path}/lib.php 를 열고,
function dbconn() 을 찾습니다.
@mysql_select_db($f[4], $connect) or Error("DB Select 에러가 발생했습니다","");
이라고 되어 있는 부분 (즉, return $connect; 문 바로 앞)에다가 다음과 같이 넣습니다.
@mysql_query("set names euckr;",$connect);

모두 해피하게 사용하실 수 있을 겁니다.

가장 중요한 것은 show variables like 'c%' ; 해서
character_set_client 와 character_set_connection 과 character_set_database의
속성을 잘 파악하여야 한다는 것입니다.

아무쪼록 소중한 DATA 깨먹는 일 없도록 하시기 바라면서 이만 줄이겠습니다.

저의 시행착오가 다른 분들에게 조금이나마 도움이 되길 바랍니다.

이 문서는 여러분 모두의 경험을 바탕으로 정리한 것이기 때문에
써보시고 유익하시다면 많은 분들이 도움을 얻을 수 있게 해주세요.


출처 : datbase.sarang.net
작성자 : 박인서(bubux)
작성일 : 2006-01-11 20:15:40
Title : Utf8 환경으로 자료 conversion 성공기
Sub Title : MySQL환경을 UTF-8로 전환하기

제 개인 적으로 테스트 한 결과 위와 같은 방법으로 하는 것도 좋습니다. 다만 데이터를 Dump할때는 해당 Client와 DB의 Character-set에 주의해야 합니다.

저희 DB를 할때는 Characterset을 따로 지정하지 않고 덤프 뜬후 Vi를 통해 Characterset을 UTF-8로 변경하고 그 데이터를 그대로 DB에 넣은 후 제로보드 소스(lib.php)에서 수정하여 표기 하였습니다.

뭐... Iconv를 이용해서 컨버팅 하는 방법도 테스트를 해봐야 겠지만 급한 경우 이렇게 처리 하는것도 하나의 방법이겠네요 ^^
신고

댓글 0개가 달렸습니다.