Hatena::Diary

たこはちの「へのかっぱ」日記 このページをアンテナに追加 RSSフィード

2010年11月10日(水)

MySQLのデータをWindowsからLinuxへ移行する手順

Windowsで作成したMySQLスキーマとデータをごっそりLinuxへ移すことにしたのだが、例によって文字コードなどの問題があり、素直には行かなかった。メモとして残しておこう。mysqldumpを用いてWindowsMySQLで作成したデータベースバックアップし、それをLinuxMySQLmysqlを使ってリストアする手順なのだが、2点ほど注意が必要だった。

それぞれのMySQLは以下のような構成になっている。create database test; とするとtestというdatabaseが作成される。DBの実体はLinux側では/var/lib/mysql/testとなる。同じ構成でWindowsMySQLにもtestというdatabaseがあるとする。

Windows側
 +-- C:/Program Files/MySQL/MySQL Server 5.x/
 |   +-- my.ini
 |   +-- bin
 |       +-- mysql
 |       +-- mysqldump
 +-- C:/ProgramData/MySQL/MySQL Server 5.x/data/
     +-- mysql
     +-- test          # このdatabaseをmysqldumpして

■Linux側
 +-- /etc/
 |   +-- my.cnf
 +-- /var/lib/mysql/
 |   +-- mysql
 |   +-- test          # ここにrestoreしてみる
 +-- /usr/bin/
     +-- mysql
     +-- mysqldump

問題1: テーブル名が小文字になってしまう。

WindowsMySQLではテーブル名に大文字/小文字の区別がないが、LinuxMySQLでは区別されており、しかもWindows大文字で定義したテーブル名はmysqldumpを経由してLinux側にリストアするとテーブル名が小文字になってしまう。このままでは大文字でテーブル名を指定しているSQLが実行時にエラーになる。Linux側のmy.cnfにlower_case_table_names=1を指定しておけばいいことが分かった。この変数デフォルトUnixでは0、Windowsでは1、MacOSでは2になっているらしい。1を設定すると、テーブル名に大文字/小文字の区別がなくなり、内部的にはすべて小文字で表現されることになる。ちなみにカラム名WindowsでもLinuxでも大文字/小文字の区別はされない。

[mysqld]
lower_case_table_names=1

問題2: 文字コードWindowsではSJISにしているがLinuxではUTF8にしたい。

Linux側ではSJISは扱いにくい。Windows側でUTF8にしておけばよかったのかもしれないが、既にSJISで作成してしまっている。どうするか。mysqldumpでダンプする際にUTF8への変換を指定できるようだ。あるいはリストア時にUTF8に変換して登録できるようだ。

Windows側のtestデータベース文字コードは以下のようにSJISになっている。

# mysql -uroot -p test
mysql> show variables like 'char%';
 +--------------------------+-------------+
 | Variable_name            | Value       |
 +--------------------------+-------------+
 | character_set_client     | sjis        |
 | character_set_connection | sjis        |
 | character_set_database   | sjis        |
 | character_set_filesystem | binary      |
 | character_set_results    | sjis        |
 | character_set_server     | sjis        |
 | character_set_system     | utf8        |
 +----------------------------------------+

Linux側のmy.cnfには以下の感じでしつこくUTF8を明示しておいた。省略してもデフォルトがUTF8になるようだ。

[mysqld]
lower_case_table_names=1
default-character-set=utf8
[mysql]
default-character-set=utf8
[client]
default-character-set=utf8
[mysql.server]
default-character-set=utf8
[mysqldump]
default-character-set=utf8

これによってLinux側のtestデータベース文字コードが以下のようにUTF8になっていることを確認しておく。testデータベースが既存でUTF8でないなら一旦drop databaseして、my.cnfを変更した後に改めてcreate databaseすればいい。

# mysql -uroot -p
mysql> create database test;
mysql> use test;
mysql> show variables like 'char%';
 +--------------------------+-------------+
 | Variable_name            | Value       |
 +--------------------------+-------------+
 | character_set_client     | utf8        |
 | character_set_connection | utf8        |
 | character_set_database   | utf8        |
 | character_set_filesystem | binary      |
 | character_set_results    | utf8        |
 | character_set_server     | utf8        |
 | character_set_system     | utf8        |
 +----------------------------------------+

上記の条件の下でmysqldumpを行ってみる。ポイントは引数--default-character-set=utf8を指定してやればいい。これを省略するとSJISになる。

# mysqldump -uroot -p --default-character-set=utf8 test > dump-test.bak

Windows側で作成したdump-test.bakをLinux側に渡し、mysqlリストアする。testというdatabaseは事前に作成しておく必要があるが、各テーブルは作成しておく必要はない。テーブルがなければcreate tableを行ってからinsertしてくれるようだ。

# nkf -g dump-test.bak 
UTF-8 (CR)
# mysql -uroot -p test < dump-test.bak
# mysql -uroot -p test
mysql> show tables;
mysql> select * from test.xxx;

Windows側で作成したdump-test.bakがUTF-8で作成されていることをnkfで確認し、mysqlで登録されたテーブルとデータが文字化けもなく参照できることが確認できた。

[2010/12/04 追記]

Linux環境でMySQLを定期的にバックアップするようにしたので追記しておく。ネット情報を参考に以下のようなシェルmysql-backup.shを作成して、cronに登録した。一応うまく動作しているようなのでメモしておく。2週間分が保存されるようになっている。

#!/bin/sh
day=14
dst=/var/lib/mysql/backup-test
bak=test.bak
d1=`date +%Y%m%d`
d2=`date "-d${day} days ago" +%Y%m%d`
new=test-${d1}.tar.gz
old=test-${d2}.tar.gz

cd ${dst}
/usr/bin/mysqldump -uroot -pxxx test > ${bak}
tar zcvf ${new} ${bak} > /dev/null 2>&1
if [ $? != 0 -o ! -e ${new} ]; then
echo backup failed ${new}
exit 1
fi
if [ -e ${old} ]; then
rm -f ${old}
fi

echo ----------- ${dst}
ls   ${dst}

シェルに実行権を与えて、cronに毎朝4:00にバックアップされるように登録しておく。

# vi mysql-backup.sh
# chmod 777 mysql-backup.sh
# ./mysql-backup.sh
# echo "0 4 * * * root mysql-backup.sh" > /etc/cron.d/mysql-backup

[2010/12/07 追記]

tarコマンドの引数の順序を間違えてましたので、修正しておきました。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/tacohachi/20101110/p1