SlideShare a Scribd company logo
MySQLの文字コード事情MySQLの文字コード事情
2017版2017版
MySQL Casual Vol.10
2017/02/01
とみたまさひろ
MySQL Casual こわいMySQL Casual こわい
自己紹介自己紹介
とみた まさひろ
長野県北部在住プログラマー
好きなプログラミング言語 Ruby
Ruby/MySQLライブラリ
http://tmtms.hatenablog.com
http://twitter.com/tmtms
https://github.com/tmtm
最近の活動最近の活動
Software Design 2016年6月号
「MySQLでデータベースを作ってみよう!」
Software Design 2016年9月号
「MySQL 4つのログの使いどころ」
Software Design 2016年12月号
「Rubyと文字コード」
「MySQLと文字コード」
mysql.gr.jp ドメイン料支払い
MySQLに対する興味分野MySQLに対する興味分野
プロトコルプロトコル
X Protocol とか
文字コード文字コード
今回は文字コード今回は文字コード
MySQLで文字コードというMySQLで文字コードという
と Character set(Charset)と Character set(Charset)
Character set ?Character set ?
語源的には文字集合語源的には文字集合
文字集合文字集合
US-ASCII
数字、英字、32個の記号
JIS X 0201
US-ASCII(「」→「¥」/「~」→「‾」)+カタカ
ナ
JIS X 0208
数字、ひらがな、カタカナ、漢字、ラテン文字、
ギリシャ文字、記号等々
JIS X 0213
JIS X 0208 + 第三水準/第四水準、ローマ数字、
鼻濁音文字等々
文字集合文字集合
Windows-31J
JIS X 0201 + JIS X 0208 + NEC特殊文字 + IBM
拡張文字(「⑧」「Ⅷ」「㈱」「髙」「﨑」「彅」
等)
Unicode
世界中の文字。絵文字(「�����������������」「�������������������」等)も含む。
あれ?あれ?
「CP932」とか「UTF-8」「CP932」とか「UTF-8」
は?は?
エンコーディングエンコーディング
文字符号化方式文字符号化方式
文字集合の文字をコンピュータで利用できるバイト列
に変換する方式
エンコーディングエンコーディング
Encoding 文字集合 用途
ISO-2022-JP US-ASCII, JIS X 0201(ラテン文
字), JIS X 0208
メール
EUC-JP US-ASCII, JIS X 0201(カナ文字),
JIS X 0208, JIS X 0212
昔の
UNIX
SHIFT_JIS JIS X 0201, JIS X 0208
Windows-31J
CP932
Windows-31J Windows
エンコーディングエンコーディング
Encoding 文字集合 1文字のサイズ
UTF-8 Unicode 1〜4バイト
UTF-16 Unicode 2バイト
UTF-32 Unicode 4バイト
Charset ≒ エンコーディングCharset ≒ エンコーディング
(MySQLに限らない)(MySQLに限らない)
MySQLのCharsetMySQLのCharset
mysql> SHOW CHARACTER SET;
+----------+---------------------------------+-----------------
| Charset | Description | Default collatio
+----------+---------------------------------+-----------------
| big5 | Big5 Traditional Chinese | big5_chinese_ci
| dec8 | DEC West European | dec8_swedish_ci
| cp850 | DOS West European | cp850_general_ci
| hp8 | HP West European | hp8_english_ci
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci
| latin1 | cp1252 West European | latin1_swedish_c
| latin2 | ISO 8859-2 Central European | latin2_general_c
| swe7 | 7bit Swedish | swe7_swedish_ci
| ascii | US ASCII | ascii_general_ci
日本語が使えてASCII互換の日本語が使えてASCII互換の
は ujis, sjis, eucjpms,は ujis, sjis, eucjpms,
cp932, utf8, utf8mb4cp932, utf8, utf8mb4
MySQL CharsetMySQL Charset
charset 文字集合 エンコーディング
ujis JIS X 0201 + 0208 EUC-JP
sjis JIS X 0201 + 0208 SHIFT_JIS
eucjpms Windows-31J EUC-JP風
cp932 Windows-31J Windows-31J
utf8 Unicode UTF-8
utf8mb4 Unicode UTF-8
今なら普通はUnicode今なら普通はUnicode
世界中のほぼすべての文字を扱える
絵文字も使える
世の中もう普通にユニコード
文字コード変換とか考えなくていい
文字化けしない
utf8 ? utf8mb4 ?utf8 ? utf8mb4 ?
utf8 と utf8mb4utf8 と utf8mb4
utf8: 1文字 1〜3バイト (U+0000〜U+FFFF)
utf8mb3 という別名あり
utf8mb4: 1文字 1〜4バイト(U+0000〜U+1FFFFF)
UTF-8 は普通1〜4バイト
utf8 / utf8mb4 の違いは MySQL のみ
ほとんどの日本語文字は3バイト
一部の漢字と絵文字等が4バイト
4バイトになる JIS X 02134バイトになる JIS X 0213
の文字の文字
𠀋𡈽𡌛𡑮𡢽𠮟𡚴𡸴𣇄𣗄𣜿𣝣𣳾𤟱𥒎𥔎𥝱𥧄𥶡𦫿𦹀𧃴𧚄𨉷𨏍𪆐𠂉
𠂢𠂤𠆢𠈓𠌫𠎁𠍱𠏹𠑊𠔉𠗖𠘨𠝏𠠇𠠺𠢹𠥼𠦝𠫓𠬝𠵅𠷡𠺕𠹭𠹤𠽟𡈁
𡉕𡉻𡉴𡋤𡋗𡋽𡌶𡍄𡏄𡑭𡗗𦰩𡙇𡜆𡝂𡧃𡱖𡴭𡵅𡵸𡵢𡶡𡶜𡶒𡶷𡷠𡸳
𡼞𡽶𡿺𢅻𢌞𢎭𢛳𢡛𢢫𢦏𢪸𢭏𢭐𢭆𢰝𢮦𢰤𢷡𣇃𣇵𣆶𣍲𣏓𣏒𣏐𣏤𣏕
𣏚𣏟𣑊𣑑𣑋𣑥𣓤𣕚𣖔𣘹𣙇𣘸𣘺𣜜𣜌𣝤𣟿𣟧𣠤𣠽𣪘𣱿𣴀𣵀𣷺𣷹𣷓
𣽾𤂖𤄃𤇆𤇾𤎼𤘩𤚥𤢖𤩍𤭖𤭯𤰖𤴔𤸎𤸷𤹪𤺋𥁊𥁕𥄢𥆩𥇥𥇍𥈞𥉌𥐮
𥓙𥖧𥞩𥞴𥧔𥫤𥫣𥫱𥮲𥱋𥱤𥸮𥹖𥹥𥹢𥻘𥻂𥻨𥼣𥽜𥿠𥿔𦀌𥿻𦀗𦁠𦃭
𦉰𦊆𦍌𣴎𦐂𦙾𦚰𦜝𦣝𦣪𦥑𦥯𦧝𦨞𦩘𦪌𦪷𦱳𦳝𦹥𦾔𦿸𦿶𦿷𧄍𧄹𧏛
𧏚𧏾𧐐𧑉𧘕𧘔𧘱𧚓𧜎𧜣𧝒𧦅𧪄𧮳𧮾𧯇𧲸𧶠𧸐𧾷𨂊𨂻𨊂𨋳𨐌𨑕𨕫
𨗈𨗉𨛗𨛺𨥉𨥆𨥫𨦇𨦈𨦺𨦻𨨞𨨩𨩱𨩃𨪙𨫍𨫤𨫝𨯁𨯯𨴐𨵱𨷻𨸟𨸶𨺉
𨻫𨼲𨿸𩊠𩊱𩒐𩗏𩙿𩛰𩜙𩝐𩣆𩩲𩷛𩸽𩸕𩺊𩹉𩻄𩻩𩻛𩿎𪀯𪀚𪃹𪂂𢈘
𪎌𪐷𪗱𪘂𪘚𪚲
4バイトになる絵文字(一部)4バイトになる絵文字(一部)
�����������������������������������������������������������������������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������
���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
������������������������������������������������������������������������������������������������������������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
�����������������������������������������������������������������������������������������������������������������������������������������������������������������
�������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������
MySQLのCharsetMySQLのCharset
サーバー
クライアント
サーバー/クライアント間の接続
データベース毎
テーブル毎
カラム毎
…を全部別々に設定できる(嫌な予感しかしない)
ハマりたくなければ全部統一ハマりたくなければ全部統一
サーバー Charsetサーバー Charset
新規に作成するデータベースのCharsetのデフォルト
これさえ指定しておけばだいたいOK
mysqld の起動オプション
--character-set-server=utf8mb4
my.cnf の [mysqld] セクション
character-set-server = utf8mb4
サーバー変数 character_set_server
データベース Charsetデータベース Charset
配下に作成するテーブルのCharsetのデフォルト値
サーバーCharsetと同じであれば指定しなくてもいい
作成: CREATE DATABASE db CHARSET utf8mb4;
確認: SHOW CREATE DATABASE db;
変更: ALTER DATABASE db CHARSET utf8mb4;
変更しても既存のテーブルCharsetは変更されない
テーブル Charsetテーブル Charset
テーブル内カラムのCharsetのデフォルト値
データベースCharsetと同じであれば指定する必要は
ない
作成: CREATE TABLE tbl (...) CHARSET utf8mb4;
確認: SHOW CREATE TABLE tbl;
テーブル Charsetテーブル Charset
テーブル属性だけ変更:
ALTER TABLE tbl CHARSET utf8mb4;
既存のカラムのcharsetは変更されない
全カラムとデータの変換:
ALTER TABLE tbl CONVERT TO CHARSET utf8mb4;
utf8 で作ってしまったテーブルを utf8mb4 に変
換とか
カラム Charsetカラム Charset
テーブルCharsetと同じであれば指定する必要はない
作成: CREATE TABLE tbl (col VARCHAR(10) CHARSET
utf8mb4, ...);
確認: SHOW CREATE TABLE tbl;
変更: ALTER TABLE tbl MODIFY col VARCHAR(10)
CHARSET utf8mb4;
変更するとカラム内のデータも変換される
クライアント Charsetクライアント Charset
クライアント内での文字列処理と
サーバーとの接続Charsetに使用される
指定方法はプログラム/言語に依存
mysql --default-character-set=utf8mb4
プログラムによっては my.cnf の [client] セクショ
ンが有効
「loose-」をつけておくとそのパラメータを知らないプログラムは
無視してくれる
[client]
loose-default-character-set = utf8mb4
クライアント Charsetクライアント Charset
mysqld との接続毎に異なる
mysql コマンドでOKでも他のアプリからはNGかも
しれない
何も指定しなければ latin1
Charset の確認Charset の確認
mysql> SHOW VARIABLES LIKE '%char%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
mysql コマンドmysql コマンド
mysql コマンドのデフォルトCharsetは auto
システムロケール(LC_ALL, LC_CTYPE, LANG 環境
変数等)により値が決定
LANG=ja_JP.UTF-8 の場合は utf8 になる
utf8mb4 ではない
LANG=C の場合は latin1 になる
utf8 と utf8mb4 の混在でutf8 と utf8mb4 の混在で
起きること起きること
utf8接続から4バイト文字をutf8接続から4バイト文字を
参照参照
クライアントが扱えない文字は「?」になる
mysql> SELECT str FROM tbl;
+-------+
| str |
+-------+
| ?と? | ← '�������������������と�����������������'
| ?と? | ← '?と?'
+-------+
バイト列を見れば違いがわかバイト列を見れば違いがわか
るる
mysql> SELECT HEX(str) FROM tbl;
+------------------------+
| HEX(str) |
+------------------------+
| F09F8DA3E381A8F09F8DBA | ← '�������������������と�����������������'
| 3FE381A83F | ← '?と?'
+------------------------+
utf8接続から4バイト文字をutf8接続から4バイト文字を
登録登録
文字化けして登録されちゃう
mysql> INSERT INTO tbl (str) VALUES ('�������������������と�����������������');
Query OK, 1 row affected, 2 warnings (0.05 sec)
mysql> SELECT str,HEX(str) FROM tbl;
+-------------+------------------------+
| str | HEX(str) |
+-------------+------------------------+
| ????と???? | 3F3F3F3FE381A83F3F3F3F |
+-------------+------------------------+
sql_modesql_mode
MySQLはおかしなことしてもあまりエラーにならな
い(余計なお世話)
sql_mode でちゃんとエラーにしてくれる
mysql> SET sql_mode='STRICT_ALL_TABLES';
mysql> INSERT INTO tbl (str) VALUES ('�������������������と�����������������');
ERROR 1366 (HY000): Incorrect string value:
'xF0x9Fx8DxA3xE3x81...' for column 'str' at row 1
sql_modesql_mode
MySQL 5.7 からはデフォルト
mysql> SELECT @@sql_mode
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE
NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER
NO_ENGINE_SUBSTITUTION
�������������������=����������������� 問題
�������������������と�����������������以外でも
mysql> SELECT '����������'='�������������';
+---------+
| '?'='?' |
+---------+
| 1 |
+---------+
mysql> SELECT '����������'='�����';
+---------+
| '?'='?' |
+---------+
| 1 |
+---------+
実は未知の文字�扱い実は未知の文字�扱い
‘�������������������’=’�����������������’=’�’
CollationCollation
CollationCollation
文字の照合規則・照合順序
Charset 毎に Collation がある
Charset の指定は Charset のデフォルトの
Collation を指定するのと同じ
Collation 一覧Collation 一覧
mysql> SHOW COLLATION LIKE 'utf8mb4%';
+------------------------+---------+-----+---------+----------+
| Collation | Charset | Id | Default | Compiled |
+------------------------+---------+-----+---------+----------+
| utf8mb4_general_ci | utf8mb4 | 45 | Yes | Yes |
| utf8mb4_bin | utf8mb4 | 46 | | Yes |
| utf8mb4_unicode_ci | utf8mb4 | 224 | | Yes |
| utf8mb4_icelandic_ci | utf8mb4 | 225 | | Yes |
| utf8mb4_latvian_ci | utf8mb4 | 226 | | Yes |
| utf8mb4_romanian_ci | utf8mb4 | 227 | | Yes |
| utf8mb4_slovenian_ci | utf8mb4 | 228 | | Yes |
| utf8mb4_polish_ci | utf8mb4 | 229 | | Yes |
| utf8mb4_estonian_ci | utf8mb4 | 230 | | Yes |
utf8mb4 の Collationutf8mb4 の Collation
utf8mb4_general_ci
utf8mb4_bin
utf8mb4_unicode_ci
utf8mb4_unicode_520_ci
utf8mb4_言語_ci
utf8mb4_japanese_ci は無い
「ci」は Case Insensitive(大文字小文字を区別しない)
の意味らしい
utf8mb4_general_ciutf8mb4_general_ci
utf8mb4 Charset のデフォルト Collation
大文字小文字を区別しない(A=a, A=a)
全角半角は区別する(A≠A)
絵文字を区別しない(�������������������=�����������������)
utf8mb4_binutf8mb4_bin
varchar(n) binary
全文字を区別する(A≠a, �������������������≠�����������������)
utf8mb4_unicode_ciutf8mb4_unicode_ci
Unicode Collation Algorithm 4.0.0
大文字小文字を区別しない(A=a, A=a)
全角半角も区別しない(A=A)
絵文字を区別しない(�������������������=�����������������)
ひらがな、カタカナ、濁点有無、全角、半角を区別
しない(は=ば=ぱ=ハ=バ=パ=ハ)
「ハハ=パパ=ババ問題」
http://www.unicode.org/reports/tr10/tr10-11.html
http://dev.mysql.com/doc/refman/5.6/ja/charset-unicode-sets.html
utf8mb4_unicode_520_ciutf8mb4_unicode_520_ci
Unicode Collation Algorithm 5.2.0
大文字小文字を区別しない(A=a, A=a)
全角半角も区別しない(A=A)
絵文字を区別する(�������������������≠�����������������)
ひらがな、カタカナ、濁点有無、全角、半角を区別
しない(は=ば=ぱ=ハ=バ=パ=ハ)
http://www.unicode.org/reports/tr10/tr10-20.html
utf8mb4_*utf8mb4_*
Collation A : a ������������������� : ����������������� は : ば
ぱ : ハ
general_ci = = ≠
bin ≠ ≠ ≠
unicode_ci = = =
unicode_520_ci = ≠ =
utf8mb4_*utf8mb4_*
Collation A : a ������������������� : ����������������� は : ば
ぱ : ハ
general_ci = = ≠
bin ≠ ≠ ≠
unicode_ci = = =
unicode_520_ci = ≠ =
ぼくたちが欲しかった
japanese_ci
= ≠ ≠
寿司=ビール問題 : MySQL 8.0でのUTF8寿司=ビール問題 : MySQL 8.0でのUTF8
サポート入門(MySQL Server Blogより)サポート入門(MySQL Server Blogより)
https://yakst.com/ja/posts/4405
私たちは日本語の照合順序の追加も計
画中です。日本語は興味深い言語であ
り、私たちの照合順序のエキスパート
であるXing ZhangとBernt Marius
Johnsenが、今後のブログ記事でもっ
と詳しく説明するはずです。
まとめまとめ
ふつうは utf8mb4
サーバーとクライアントの両方で Charset を指定
sql_mode をちゃんと設定
Collation は適切に
MySQL 8 で unicode_japanese_ci ができるかも!?

More Related Content

PDF
20191115-PGconf.Japan
PDF
Swagger ではない OpenAPI Specification 3.0 による API サーバー開発
PDF
gRPC入門
PDF
分散トレーシング技術について(Open tracingやjaeger)
PDF
SQL大量発行処理をいかにして高速化するか
PDF
新入社員のための大規模ゲーム開発入門 サーバサイド編
PDF
インフラエンジニアの綺麗で優しい手順書の書き方
PPTX
Redisの特徴と活用方法について
20191115-PGconf.Japan
Swagger ではない OpenAPI Specification 3.0 による API サーバー開発
gRPC入門
分散トレーシング技術について(Open tracingやjaeger)
SQL大量発行処理をいかにして高速化するか
新入社員のための大規模ゲーム開発入門 サーバサイド編
インフラエンジニアの綺麗で優しい手順書の書き方
Redisの特徴と活用方法について

What's hot (20)

PPTX
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
PPTX
初心者向けMongoDBのキホン!
PDF
ドメイン駆動設計に15年取り組んでわかったこと
PDF
目grep入門 +解説
PDF
実運用して分かったRabbit MQの良いところ・気をつけること #jjug
PDF
ソーシャルゲームのためのデータベース設計
PDF
コンテナ未経験新人が学ぶコンテナ技術入門
PDF
わかる!metadata.managedFields / Kubernetes Meetup Tokyo 48
PDF
Springを何となく使ってる人が抑えるべきポイント
PDF
C# における Redis 徹底活用
PDF
ホットペッパービューティーにおけるモバイルアプリ向けAPIのBFF/Backend分割
PDF
MHA for MySQLとDeNAのオープンソースの話
PDF
MagicOnion入門
PPTX
kubernetes初心者がKnative Lambda Runtime触ってみた(Kubernetes Novice Tokyo #13 発表資料)
PPTX
GraphQLのsubscriptionで出来ること
PDF
VirtualBox と Rocky Linux 8 で始める Pacemaker ~ VirtualBox でも STONITH 機能が試せる! Vi...
PPTX
10分でわかるOpenAPI V3
PDF
できる!並列・並行プログラミング
PDF
MySQL 8.0で憶えておいてほしいこと
PDF
Twitterのsnowflakeについて
PostgreSQLクエリ実行の基礎知識 ~Explainを読み解こう~
初心者向けMongoDBのキホン!
ドメイン駆動設計に15年取り組んでわかったこと
目grep入門 +解説
実運用して分かったRabbit MQの良いところ・気をつけること #jjug
ソーシャルゲームのためのデータベース設計
コンテナ未経験新人が学ぶコンテナ技術入門
わかる!metadata.managedFields / Kubernetes Meetup Tokyo 48
Springを何となく使ってる人が抑えるべきポイント
C# における Redis 徹底活用
ホットペッパービューティーにおけるモバイルアプリ向けAPIのBFF/Backend分割
MHA for MySQLとDeNAのオープンソースの話
MagicOnion入門
kubernetes初心者がKnative Lambda Runtime触ってみた(Kubernetes Novice Tokyo #13 発表資料)
GraphQLのsubscriptionで出来ること
VirtualBox と Rocky Linux 8 で始める Pacemaker ~ VirtualBox でも STONITH 機能が試せる! Vi...
10分でわかるOpenAPI V3
できる!並列・並行プログラミング
MySQL 8.0で憶えておいてほしいこと
Twitterのsnowflakeについて
Ad

More from Masahiro Tomita (20)

PDF
お前の罪を数えろ
PDF
Ruby 2.5
PDF
本当はこわいMySQLプロトコル
PDF
ネットワークこわい
PDF
MySQLの文字コード事情 2017春版
PDF
PDF
MySQLの文字コード事情
PDF
進捗と品質
PDF
MySQLを拡張する
PDF
「理論から学ぶデータベース実践入門」読書会スペシャル
PDF
MyNAができるまで
PDF
文字化け
PDF
PDF
メールの暗号化
PDF
文字化け
PDF
進捗と品質
PDF
アジャイルジャパン長野サテライト
PDF
🍣=🍺
PDF
本当はこわいエンコーディングの話
お前の罪を数えろ
Ruby 2.5
本当はこわいMySQLプロトコル
ネットワークこわい
MySQLの文字コード事情 2017春版
MySQLの文字コード事情
進捗と品質
MySQLを拡張する
「理論から学ぶデータベース実践入門」読書会スペシャル
MyNAができるまで
文字化け
メールの暗号化
文字化け
進捗と品質
アジャイルジャパン長野サテライト
🍣=🍺
本当はこわいエンコーディングの話
Ad

MySQLの文字コード事情 2017版