MySQLとPHPで文字化けが発生する。MySQL5.5+PHPからのDB更新時に文字化けが発生する。

MySQLとPHPで文字化けが発生した。 MySQL4.x で動作していたPHPアプリケーション一式をMySQL5.5の環境に移設したところ、 DB更新時に文字化けが発生する。ログを取ってみたところ、次の状況。 環境

PHP 5.3.6(php-mysql.i386 5.3.6-4)
  • FormからPHPに渡されるパラメータをダンプ →文字化けしていない。

  • SQL文 →文字化けしていない。

  • DB中のデータ →文字化けしている。日本語部分が?になっている。phpMyAdmin等で見ても同じ。

また、同じサーバーで動作させているほぼ同じような構成のPHPアプリケーションでは文字化けが発生しない。

このあたりを手掛かりに調べてみると次の事が分かった。
該当DBの変数を比較してみると、character_set_databaseに差異がある。
どうやら、my.cnfにcharacter-set-serverの設定をする前にDBを作成したのが原因の模様。

show variables like 'character%';
Variable_name 正常動作するDBの値 文字化けするDB
character_set_client utf8 utf8
character_set_connection utf8 utf8
character_set_database utf8 latin1
character_set_filesystem binary binary
character_set_results utf8 utf8
character_set_server latin1 latin1
character_set_system utf8 utf8
character_sets_dir /usr/share/mysql/charsets/ /usr/share/mysql/charsets/

解決方法

(1) /etc/my.cnf を編集

[mysqld]
character-set-server=utf8 ← 追加
・
・
・

datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
・
・
・

※ mysql5.5からcharacter-set-serverと記述するらしい。 default-character-setと記述するとMySQLが起動しない模様。

(2) DBを再生成
これで文字化けすることなくDBに値が格納された。 ・ ・ ・ とこのままでは不完全だった。。

文字化けその2と解決方法

この問題の他にも「~」が「?」に化けてしまう現象に遭遇。
どうやら、MySQL4.x→MySQL5.xにデータを移設した際に、照合順が ujis_japanese_ci となってしまったことが原因の模様。 utf8_general_ci とした方が良い。

今回は生成したTABLEを破棄してTABLEを再生成することが可能だったため、最小限の対応で済ませるため、 ダンプされたsqlファイルを直接変更して再度MySQLに投入した。
変更点は次の通り。

  • Table生成部分の変更
DROP TABLE IF EXISTS `testtbl`;
CREATE TABLE `testtbl` (
  `id` varchar(2) NOT NULL default '',
   
   
   
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=ujis; ←これを消す。
  
) ;

-SQLファイル中の 「?」 FULLWIDTH TILDEを「~」に置換 あとは編集後のSQLをDBにインポートする。

# mysql -u USERNAME -p DBNAME1  < dump.sql

※DB上のTableがいったん消えるので、十分気を付ける&バックアップを事前に取ること。

参考情報その1

古めのこのPHPアプリケーションは mb_internal_encoding=eucJP-win で動作し、 このあたりに原因がありそうな雰囲気と調べていたら次の情報も見つかった。。 このPHPアプリはDB接続時に

mysql_query("SET CHARACTER SET eucjpms");

を発行しているが、これはあまりよくないらしい。 5.2.3以降のみのようだが、次の関数を利用した方が望ましい模様。

mysql_set_charset("eucjpms");

関連記事