mysqlダンプ→インポート→文字化け→くそおおおおおおお! ~ ブチ切れエンジニアのボヤキ
はじめに
オッス!オラ、エンジニア!!
今回はmysqlのデータベースをダンプとインポートで移してみっぞ!!
これはオラが実際にハマった経験を面白おかしくその原因と対策を書いたものだ。
これがみんなの役に立ったらならオラすんげぇ嬉しいぞ!!
ちなみにOSはWindowsだからよろしくな!
powershellのバージョンは5.1だ!
自分のバージョンが気になる奴は$PSVersionTableってやると調べられるぞ!
始めっぞ!!!
まず、データベースを用意したぞ!
CREATE database dragonball;
CREATE TABLE chara (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL,
`Quote` varchar(255) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
INSERT INTO chara (name, Quote) VALUES
("悟空", "クリリンのことかーーーーーっ!!!!!"),
("ウーロン", "ギャルのパンティーおくれーーーっ!!!!!"),
("フリーザ", "わたしの戦闘力は530000です。"),
("ベジータ", "へっ! きたねえ花火だ"),
("少年悟空", "それ食えんのか?"),
("フリーザ", "初めてですよ・・・ここまで私をコケにしたおバカさん達は・・・"),
("野沢雅子", "うっせぇ!ぶっ殺すぞぉ!"),
("アイデンティティ", "口悪ぃなおい!"),
("パラガス", "パッパ、パラガス♪"),
("ブロリー", "親父ぃ・・・"),
("パラガス", "ゑゑゑゑゑゑゑ!?"),
("シュワルツネグァア", "I'll be back");

データベースをダンプすっぞ!!
このコマンドってやつやればダンプ出来るらしいぞ!!
mysqldump --default-character-set=utf8mb4 -u root -B dragonball > dragonball.dmp
オラもう訳わかんねぇぞ!
自慢じゃねえが、オラ面倒くせえ事が大嫌いなもんだからよぉ
ローカルホストだしrootだしパスワードは勿論いらねぇっていう環境だ!
オラと同じような人はさっきのコマンドでOKだ!
だけど、違う人は色々オプションが必要だからそこはググってなんとかしてけれよ!!
じゃあ、このコマンドどうやって実行するかなんだけどよ。
Windowsでは次の2つでできるらしいぞ!
- cmd(コマンドプロンプト)
- powershell
オラ、強え奴見るとワクワクすっからよぉ!
powershellでやってみっぞ!
PS C:\Users\gokuu> mysqldump --default-character-set=utf8mb4 -u root dragonball > dragonball.dmp
mysqldump : 用語 'mysqldump' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラムの名前として認識
されません。名前が正しく記述されていることを確認し、パスが含まれている場合はそのパスが正しいことを確認してから、再試行
してください。
発生場所 行:1 文字:1
+ mysqldump --default-character-set=utf8mb4 -u root dragonball > dragon ...
+ ~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (mysqldump:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
うおおおおおおおお!!!!
はぁはぁ・・・手強え奴だったが、何とか倒したぞ!
これでオラもダンプってやつが出来たぞ!
ダンプをインポートすっぞ!!
よっしゃ、やっぞ!!
さっきやったダンプファイルをインポートすればいいらしいぞ!
さっきはパスで手こずったから今回はダンプファイルをインポートする所に置いておくぞ!!
ちなみにオラはC:\xampp_8_2_12\mysql\binここにあるデータベースにインポートしていくぞ!
インポートするときはこのコマンドをやればいいらしいぞ!
# オラ、パスとかよくわかんねぇから先に移動すっぞ!
cd "C:\xampp_8_2_12\mysql\bin"
# インポートすっぞ!
.\mysql --default-character-set=utf8mb4 -P 3307 -u root < dragonball.dmp
よっしゃ、早速やっぞ!!
PS C:\Users\gokuu> cd "C:\xampp_8_2_12\mysql\bin"
PS C:\xampp_8_2_12\mysql\bin> .\mysql --default-character-set=utf8mb4 -P 3307 -u root < dragonball.dmp
発生場所 行:1 文字:15
+ .\mysql --default-character-set=utf8mb4 -P 3307 -u root < dragonball.dmp
+ ~
演算子 '<' は、今後の使用のために予約されています。
+ CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : RedirectionNotSupported
あああああああああああ!!!
オラ、すっげぇイライラしてきたぞ!!!
Powershellって全然パワーねぇじゃねえか!!
仕方ねぇからここは cmd(コマンドプロンプト) でもう一回やっぞ!!
注)powershellそのものは cmd(コマンドプロンプト)より遥かにパワフル ですが複雑多岐な要件を実装しているためかこのような問題が度々起こり得ます。
C:\Users\gokuu>cd "C:\xampp_8_2_12\mysql\bin"
C:\xampp_8_2_12\mysql\bin>mysql --default-character-set=utf8mb4 -P 3307 -u root < dragonball.dmp
ERROR: ASCII '\0' appeared in the statement, but this is not allowed unless option --binary-mode is enabled and mysql is run in non-interactive mode. Set --binary-mode to 1 if ASCII '\0' is expected. Query: '-'.
コマンドプロンプトでも、できねぇじゃねぇかよ!!!!!
くそおおおおおおお!
できねぇぞ!!?(原因考察)
できねぇぞ!!?
どうしてだよおおおおおおお!!!
なぜこのような事が起こったのか
まずダンプはpowershellで以下のコマンドを行いました。
# 実行可能なパスに移動してからやったよ!
mysqldump --default-character-set=utf8mb4 -u root dragonball > dragonball.dmp
次に、powershellでは出来なかったのでコマンドプロンプトで以下のコマンドを行いました。
mysql --default-character-set=utf8mb4 -P 3307 -u root < dragonball.dmp
原因はエンコーディング(文字コード)と>(リダイレクト)の挙動の差にある!
エンコーディング(文字コード)
有名なものでは以下のものがあります。
- ASCII
- SHIFT-JIS
- UTF-8
- EUC-JP
これは人間が理解できるあいうえおという文字列をPCが理解できる227 129 130 227 129 132 227 129 134 227 129 136 227 129 138と言ったバイト数値に相互変換します。(UTF-8の場合)
ちなみにSHIFT-JISの場合は130 160 130 162 130 164 130 166 130 168 です。
全然違いますね・・・。
そしてファイルはPCが理解できるバイト数値で文字列を保持しています。
つまりUTF-8であいうえおと書いて保存したファイルは内部的に227 129 130 227 129 132 227 129 134 227 129 136 227 129 138と言った数値で保存されています。
なので・・・227 129 130 227 129 132 227 129 134 227 129 136 227 129 138と保存されたファイルをSHIFT-JISで開くと縺ゅ>縺�縺医♀と表示されます。
これが文字化けという現象です。
>(リダイレクト)の差
さて、文字化けの仕組みは分かりました。
ということはエンコーディング(文字コード)を合わせれば文字化けしないということでもあります。
だけれども、今回は文字化けしています。
次に、>(リダイレクト)の差に着目してみましょう。
リダイレクトとは出力の向き先を変更するための機能です。
powershellとコマンドプロンプトの挙動を見比べてみましょう。
mysqldump --default-character-set=utf8mb4 -u root -B dragonball > dragonball.dmp
今回はこのコマンドをpowershellでやってみました。
ではコマンドプロンプトでやってみるとどうでしょうか?
rem ダンプすっぞ!!
mysqldump --default-character-set=utf8mb4 -u root -B dragonball > dragonball.dmp
rem インポートすっぞ!!
mysql --default-character-set=utf8mb4 -P 3307 -u root < dragonball.dmp
実行結果

不思議ですね・・・、コマンドプロンプトでやった場合は上手くいきました。
なぜ同じコマンドを実行したのに結果に差が出たのでしょうか?
ここを少し深掘りしていってみましょう。
色々調べてみた
-
powershell
> について

バイナリファイルのリダイレクトについて

-
cmd(コマンドプロンプト)
コマンドプロンプトの入出力ストリームのリダイレクトについて

リダイレクトという概念について

バイトストリームという概念について

考察及び調査の結果概要
-
powershell
>は一般的なリダイレクト演算子よりもOut-Fileというコマンドレットに近い挙動をしており、バイトではなく文字列のストリームにより処理されOut-Fileの規定エンコーディングでUTF16LEに変換されたため文字化けを起こした。 -
コマンドプロンプト
調査と挙動からの推測だが、コマンドプロンプトの>は一般的なリダイレクト演算子でありバイトストリームにより処理されるため文字化けが発生しなかった。
対策
cmd(コマンドプロンプト)でやりましょう。
結局のところこれが一番簡単だと思います。
rem ダンプすっぞ!!
mysqldump --default-character-set=utf8mb4 -u root -B dragonball > dragonball.dmp
rem インポートすっぞ!!
mysql --default-character-set=utf8mb4 -P 3307 -u root < dragonball.dmp
powershellをアップデートしよう!
2024年現在はバージョン7だそうです。
以下の手順を参考にアップデートするもの良さそうです。
さいごに
今回は淡々と手順説明しがちな技術記事に面白さを加えてみる試みで書いてみました。
できねぇぞ!!?(原因考察)までは、スラスラ執筆できましたが、原因考察編になるととても今回のテーマは奥がとても深いのと信頼できる情報源が中々見つからずに4日程かかりました。
こんな調子で書きたい記事はまだあるので心が折れてなければ再チャレンジしようと思います。
Discussion