MySQL から取得した文字が化けるのは DBD::MySQL のせいだった

MySQL を使った Web システムの移行作業をした。

何年か前に作成したもので、DB とのやり取りをする部分は Perl による CGI 形式になっている。
枯れた技術最高!(笑)
あ、今回は Perl ではなく MySQL の話ね(^^;

移行先にも MySQL は入っていたので、早速、移行元で、

# mysqldump -u root -p --default-character-set=binary hoge_db > hoge_db.sql

と、バイナリデータとしてバックアップ。
このデータを移行先サーバに持ち込み、

# mysql -u root --default-character-set=binary hoge_db < hoge_db.sql

と、DB にリストアした。(もちろん、予め空の DB を作っておく)

早速 mysql コマンドで SELECT をしてみると、文字化け~。表示できなかった文字が ? に置換されとる。

DB を確認すると、

mysql> show variables like '%char%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | latin1                     |
| character_set_connection | latin1                     |
| character_set_database   | latin1                     |
| character_set_filesystem | binary                     |
| character_set_results    | latin1                     |
| character_set_server     | latin1                     |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

なんか、文字コードが「ラテン語」になっとるやないか。

/etc/my.cnf の mysqld、client セクションに、それぞれ、

[mysqld]
character-set-server = utf8

[client]
default-character-set = utf8

を追加し、DB 確認。

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                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

お~。この時点で、mysql コマンド上での文字化けはなくなった。

しかし、CGI からのアクセスでは相変わらず文字が化ける。
こういう場合は、だいたい DBI/DBD モジュールの問題だ。

案の定、このサーバ上で make された DBD::MySQL は mysql_enable_utf8 を設定されていないようで、そのため「DBに格納されている通常の utf8 文字列は、エンコード失敗の ? に置換されDBから取り出される。」ようだ。

その証拠に、mysql_enable_utf8 を設定した場合と同じ効果のある「SET NAMES utf8」という SQL 文を、本来の SQL 文を処理する前に DB に送るようにしたら文字化けは解消した。(db_tool::directExec というのは当社独自の DB アクセス関係の関数)

# 先に SET NAMES utf8 を発行
my $set_sql =<<EOS;
SET NAMES utf8
EOS

@db = &db_tool::directExec($Conn, $set_sql);

# 次に SELECT を実行
$sql  =<<EOS;
SELECT
COUNT(id) AS count
FROM
hoge_data_list
WHERE
ID = $USER_ID
EOS

@db = &db_tools::directExec($Conn, $sql);

<以下略>

こんな感じで。

これで CGI でも文字化けは解消された。

ちなみに、db_tools::directExec 関数の中で「SET NAMES utf8」を発行するようにすれば、CGI 側で修正する必要はなくなるんだけど、この関数、他の人も使ってるからなあ・・・あんまり触りたくない。

トラックバック(0)

このブログ記事を参照しているブログ一覧: MySQL から取得した文字が化けるのは DBD::MySQL のせいだった

このブログ記事に対するトラックバックURL: https://blog.netandfield.com/mt/mt-tb.cgi/4891

コメントする

このブログ記事について

このページは、shinodaが2018年6月 6日 02:28に書いたブログ記事です。

ひとつ前のブログ記事は「「ちょるる」カレー。ただし食レポなし」です。

次のブログ記事は「居酒屋「新谷」にてカープの試合の中止を待つ」です。

最近のコンテンツはインデックスページで見られます。過去に書かれたものはアーカイブのページで見られます。


月別 アーカイブ

電気ウナギ的○○ mobile ver.

携帯版「電気ウナギ的○○」はこちら