56
MySQLの文字コード事情 MySQLの文字コード事情 2017版 2017版 MySQL Casual Vol.10 2017/02/01 とみたまさひろ

MySQLの文字コード事情 2017版

Embed Size (px)

Citation preview

Page 1: MySQLの文字コード事情 2017版

MySQLの文字コード事情MySQLの文字コード事情2017版2017版

MySQL Casual Vol.10

2017/02/01

とみたまさひろ

Page 2: MySQLの文字コード事情 2017版

MySQL Casual こわいMySQL Casual こわい

Page 3: MySQLの文字コード事情 2017版

自己紹介自己紹介とみた まさひろ

長野県北部在住プログラマー好きなプログラミング言語 RubyRuby/MySQLライブラリ

http://tmtms.hatenablog.comhttp://twitter.com/tmtmshttps://github.com/tmtm

Page 4: MySQLの文字コード事情 2017版

最近の活動最近の活動Software Design 2016年6月号

「MySQLでデータベースを作ってみよう!」Software Design 2016年9月号

「MySQL 4つのログの使いどころ」Software Design 2016年12月号

「Rubyと文字コード」「MySQLと文字コード」

mysql.gr.jp ドメイン料支払い

Page 5: MySQLの文字コード事情 2017版

MySQLに対する興味分野MySQLに対する興味分野プロトコルプロトコルX Protocol とか

文字コード文字コード

Page 6: MySQLの文字コード事情 2017版

今回は文字コード今回は文字コード

Page 7: MySQLの文字コード事情 2017版

MySQLで文字コードというMySQLで文字コードというと Character set(Charset)と Character set(Charset)

Page 8: MySQLの文字コード事情 2017版

Character set ?Character set ?

Page 9: MySQLの文字コード事情 2017版

語源的には文字集合語源的には文字集合

Page 10: MySQLの文字コード事情 2017版

文字集合文字集合US-ASCII

数字、英字、32個の記号JIS X 0201

US-ASCII(「\」→「¥」/「~」→「‾」)+カタカナ

JIS X 0208数字、ひらがな、カタカナ、漢字、ラテン文字、ギリシャ文字、記号等々

JIS X 0213JIS X 0208 + 第三水準/第四水準、ローマ数字、鼻濁音文字等々

Page 11: MySQLの文字コード事情 2017版

文字集合文字集合Windows-31J

JIS X 0201 + JIS X 0208 + NEC特殊文字 + IBM拡張文字(「⑧」「Ⅷ」「㈱」「髙」「﨑」「彅」等)

Unicode世界中の文字。絵文字(「�����������������」「�������������������」等)も含む。

Page 12: MySQLの文字コード事情 2017版

あれ?あれ?「CP932」とか「UTF-8」「CP932」とか「UTF-8」

は?は?

Page 13: MySQLの文字コード事情 2017版

エンコーディングエンコーディング文字符号化方式文字符号化方式

文字集合の文字をコンピュータで利用できるバイト列に変換する方式

Page 14: MySQLの文字コード事情 2017版

エンコーディングエンコーディング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 0208Windows-31JCP932

Windows-31J Windows

Page 15: MySQLの文字コード事情 2017版

エンコーディングエンコーディングEncoding 文字集合 1文字のサイズUTF-8 Unicode 1〜4バイトUTF-16 Unicode 2バイトUTF-32 Unicode 4バイト

Page 16: MySQLの文字コード事情 2017版

Charset ≒ エンコーディングCharset ≒ エンコーディング(MySQLに限らない)(MySQLに限らない)

Page 17: MySQLの文字コード事情 2017版

MySQLのCharsetMySQLのCharsetmysql> SHOW CHARACTER SET;+----------+---------------------------------+---------------------+---| Charset | Description | Default collation | Ma+----------+---------------------------------+---------------------+---| 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_ci | | latin2 | ISO 8859-2 Central European | latin2_general_ci | | swe7 | 7bit Swedish | swe7_swedish_ci | | ascii | US ASCII | ascii_general_ci |

Page 18: MySQLの文字コード事情 2017版

日本語が使えてASCII互換の日本語が使えてASCII互換のは ujis, sjis, eucjpms,は ujis, sjis, eucjpms,cp932, utf8, utf8mb4cp932, utf8, utf8mb4

Page 19: MySQLの文字コード事情 2017版

MySQL CharsetMySQL Charsetcharset 文字集合 エンコーディングujis JIS X 0201 + 0208 EUC-JPsjis JIS X 0201 + 0208 SHIFT_JISeucjpms Windows-31J EUC-JP風cp932 Windows-31J Windows-31Jutf8 Unicode UTF-8utf8mb4 Unicode UTF-8

Page 20: MySQLの文字コード事情 2017版

今なら普通はUnicode今なら普通はUnicode世界中のほぼすべての文字を扱える絵文字も使える世の中もう普通にユニコード文字コード変換とか考えなくていい文字化けしない

Page 21: MySQLの文字コード事情 2017版

utf8 ? utf8mb4 ?utf8 ? utf8mb4 ?

Page 22: MySQLの文字コード事情 2017版

utf8 と utf8mb4utf8 と utf8mb4utf8: 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バイト

Page 23: MySQLの文字コード事情 2017版

4バイトになる JIS X 02134バイトになる JIS X 0213の文字の文字

𠀋𡈽𡌛𡑮𡢽𠮟𡚴𡸴𣇄𣗄𣜿𣝣𣳾𤟱𥒎𥔎𥝱𥧄𥶡𦫿𦹀𧃴𧚄𨉷𨏍𪆐𠂉𠂢𠂤𠆢𠈓𠌫𠎁𠍱𠏹𠑊𠔉𠗖𠘨𠝏𠠇𠠺𠢹𠥼𠦝𠫓𠬝𠵅𠷡𠺕𠹭𠹤𠽟𡈁𡉕𡉻𡉴𡋤𡋗𡋽𡌶𡍄𡏄𡑭𡗗𦰩𡙇𡜆𡝂𡧃𡱖𡴭𡵅𡵸𡵢𡶡𡶜𡶒𡶷𡷠𡸳𡼞𡽶𡿺𢅻𢌞𢎭𢛳𢡛𢢫𢦏𢪸𢭏𢭐𢭆𢰝𢮦𢰤𢷡𣇃𣇵𣆶𣍲𣏓𣏒𣏐𣏤𣏕𣏚𣏟𣑊𣑑𣑋𣑥𣓤𣕚𣖔𣘹𣙇𣘸𣘺𣜜𣜌𣝤𣟿𣟧𣠤𣠽𣪘𣱿𣴀𣵀𣷺𣷹𣷓𣽾𤂖𤄃𤇆𤇾𤎼𤘩𤚥𤢖𤩍𤭖𤭯𤰖𤴔𤸎𤸷𤹪𤺋𥁊𥁕𥄢𥆩𥇥𥇍𥈞𥉌𥐮𥓙𥖧𥞩𥞴𥧔𥫤𥫣𥫱𥮲𥱋𥱤𥸮𥹖𥹥𥹢𥻘𥻂𥻨𥼣𥽜𥿠𥿔𦀌𥿻𦀗𦁠𦃭𦉰𦊆𦍌𣴎𦐂𦙾𦚰𦜝𦣝𦣪𦥑𦥯𦧝𦨞𦩘𦪌𦪷𦱳𦳝𦹥𦾔𦿸𦿶𦿷𧄍𧄹𧏛𧏚𧏾𧐐𧑉𧘕𧘔𧘱𧚓𧜎𧜣𧝒𧦅𧪄𧮳𧮾𧯇𧲸𧶠𧸐𧾷𨂊𨂻𨊂𨋳𨐌𨑕𨕫𨗈𨗉𨛗𨛺𨥉𨥆𨥫𨦇𨦈𨦺𨦻𨨞𨨩𨩱𨩃𨪙𨫍𨫤𨫝𨯁𨯯𨴐𨵱𨷻𨸟𨸶𨺉𨻫𨼲𨿸𩊠𩊱𩒐𩗏𩙿𩛰𩜙𩝐𩣆𩩲𩷛𩸽𩸕𩺊𩹉𩻄𩻩𩻛𩿎𪀯𪀚𪃹𪂂𢈘

𪎌𪐷𪗱𪘂𪘚𪚲

Page 24: MySQLの文字コード事情 2017版

4バイトになる絵文字(一部)4バイトになる絵文字(一部)�����������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

Page 25: MySQLの文字コード事情 2017版

MySQLのCharsetMySQLのCharsetサーバークライアントサーバー/クライアント間の接続データベース毎テーブル毎カラム毎

…を全部別々に設定できる(嫌な予感しかしない)

Page 26: MySQLの文字コード事情 2017版

ハマりたくなければ全部統一ハマりたくなければ全部統一

Page 27: MySQLの文字コード事情 2017版

サーバー Charsetサーバー Charset新規に作成するデータベースのCharsetのデフォルトこれさえ指定しておけばだいたいOKmysqld の起動オプション--character-set-server=utf8mb4my.cnf の [mysqld] セクションcharacter-set-server = utf8mb4サーバー変数 character_set_server

Page 28: MySQLの文字コード事情 2017版

データベース Charsetデータベース Charset配下に作成するテーブルのCharsetのデフォルト値

サーバーCharsetと同じであれば指定しなくてもいい

作成: CREATE DATABASE db CHARSET utf8mb4;

確認: SHOW CREATE DATABASE db;

変更: ALTER DATABASE db CHARSET utf8mb4;

変更しても既存のテーブルCharsetは変更されない

Page 29: MySQLの文字コード事情 2017版

テーブル Charsetテーブル Charsetテーブル内カラムのCharsetのデフォルト値

データベースCharsetと同じであれば指定する必要はない

作成: CREATE TABLE tbl (...) CHARSET utf8mb4;

確認: SHOW CREATE TABLE tbl;

Page 30: MySQLの文字コード事情 2017版

テーブル Charsetテーブル Charsetテーブル属性だけ変更:ALTER TABLE tbl CHARSET utf8mb4;

既存のカラムのcharsetは変更されない

全カラムとデータの変換:ALTER TABLE tbl CONVERT TO CHARSET utf8mb4;

utf8 で作ってしまったテーブルを utf8mb4 に変換とか

Page 31: MySQLの文字コード事情 2017版

カラム Charsetカラム CharsetテーブルCharsetと同じであれば指定する必要はない

作成: CREATE TABLE tbl (col VARCHAR(10) CHARSETutf8mb4, ...);

確認: SHOW CREATE TABLE tbl;

変更: ALTER TABLE tbl MODIFY col VARCHAR(10)CHARSET utf8mb4;

変更するとカラム内のデータも変換される

Page 32: MySQLの文字コード事情 2017版

クライアント Charsetクライアント Charsetクライアント内での文字列処理とサーバーとの接続Charsetに使用される

指定方法はプログラム/言語に依存

mysql --default-character-set=utf8mb4

プログラムによっては my.cnf の [client] セクションが有効

「loose-」をつけておくとそのパラメータを知らないプログラムは無視してくれる

[client]loose-default-character-set = utf8mb4

Page 33: MySQLの文字コード事情 2017版

クライアント Charsetクライアント Charsetmysqld との接続毎に異なる

mysql コマンドでOKでも他のアプリからはNGかもしれない

何も指定しなければ latin1

Page 34: MySQLの文字コード事情 2017版

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/ |+--------------------------+----------------------------+

Page 35: MySQLの文字コード事情 2017版

mysql コマンドmysql コマンドmysql コマンドのデフォルトCharsetは auto

システムロケール(LC_ALL, LC_CTYPE, LANG 環境変数等)により値が決定

LANG=ja_JP.UTF-8 の場合は utf8 になるutf8mb4 ではない

LANG=C の場合は latin1 になる

Page 36: MySQLの文字コード事情 2017版

utf8 と utf8mb4 の混在でutf8 と utf8mb4 の混在で起きること起きること

Page 37: MySQLの文字コード事情 2017版

utf8接続から4バイト文字をutf8接続から4バイト文字を参照参照

クライアントが扱えない文字は「?」になるmysql> SELECT str FROM tbl;+-------+| str |+-------+| ?と? | ← '�������������������と�����������������'| ?と? | ← '?と?'+-------+

Page 38: MySQLの文字コード事情 2017版

バイト列を見れば違いがわかバイト列を見れば違いがわかるる

mysql> SELECT HEX(str) FROM tbl;+------------------------+| HEX(str) |+------------------------+| F09F8DA3E381A8F09F8DBA | ← '�������������������と�����������������'| 3FE381A83F | ← '?と?'+------------------------+

Page 39: MySQLの文字コード事情 2017版

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 |+-------------+------------------------+

Page 40: MySQLの文字コード事情 2017版

sql_modesql_modeMySQLはおかしなことしてもあまりエラーにならない(余計なお世話)

sql_mode でちゃんとエラーにしてくれる

mysql> SET sql_mode='STRICT_ALL_TABLES';

mysql> INSERT INTO tbl (str) VALUES ('�������������������と�����������������');ERROR 1366 (HY000): Incorrect string value: '\xF0\x9F\x8D\xA3\xE3\x81...' for column 'str' at row 1

Page 41: MySQLの文字コード事情 2017版

sql_modesql_modeMySQL 5.7 からはデフォルト

mysql> SELECT @@sql_modeONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATENO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USERNO_ENGINE_SUBSTITUTION

Page 42: MySQLの文字コード事情 2017版

�������������������=����������������� 問題

Page 43: MySQLの文字コード事情 2017版

�������������������と�����������������以外でもmysql> SELECT '����������'='�������������';+---------+| '?'='?' |+---------+| 1 |+---------+mysql> SELECT '����������'='�����';+---------+| '?'='?' |+---------+| 1 |+---------+

Page 44: MySQLの文字コード事情 2017版

実は未知の文字�扱い実は未知の文字�扱い‘�������������������’=’�����������������’=’�’

Page 45: MySQLの文字コード事情 2017版

CollationCollation

Page 46: MySQLの文字コード事情 2017版

CollationCollation文字の照合規則・照合順序Charset 毎に Collation があるCharset の指定は Charset のデフォルトのCollation を指定するのと同じ

Page 47: MySQLの文字コード事情 2017版

Collation 一覧Collation 一覧mysql> SHOW COLLATION LIKE 'utf8mb4%';+------------------------+---------+-----+---------+----------+--------| Collation | Charset | Id | Default | Compiled | Sortlen+------------------------+---------+-----+---------+----------+--------| utf8mb4_general_ci | utf8mb4 | 45 | Yes | Yes | 1| utf8mb4_bin | utf8mb4 | 46 | | Yes | 1| utf8mb4_unicode_ci | utf8mb4 | 224 | | Yes | 8| utf8mb4_icelandic_ci | utf8mb4 | 225 | | Yes | 8| utf8mb4_latvian_ci | utf8mb4 | 226 | | Yes | 8| utf8mb4_romanian_ci | utf8mb4 | 227 | | Yes | 8| utf8mb4_slovenian_ci | utf8mb4 | 228 | | Yes | 8| utf8mb4_polish_ci | utf8mb4 | 229 | | Yes | 8| utf8mb4_estonian_ci | utf8mb4 | 230 | | Yes | 8

Page 48: MySQLの文字コード事情 2017版

utf8mb4 の Collationutf8mb4 の Collationutf8mb4_general_ciutf8mb4_binutf8mb4_unicode_ciutf8mb4_unicode_520_ciutf8mb4_言語_ciutf8mb4_ japanese_ci は無い

「ci」は Case Insensitive(大文字小文字を区別しない)の意味らしい

Page 49: MySQLの文字コード事情 2017版

utf8mb4_general_ciutf8mb4_general_ciutf8mb4 Charset のデフォルト Collation大文字小文字を区別しない(A=a, A=a)全角半角は区別する(A≠A)絵文字を区別しない(�������������������=�����������������)

Page 50: MySQLの文字コード事情 2017版

utf8mb4_binutf8mb4_binvarchar(n) binary全文字を区別する(A≠a, �������������������≠�����������������)

Page 51: MySQLの文字コード事情 2017版

utf8mb4_unicode_ciutf8mb4_unicode_ciUnicode 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

Page 52: MySQLの文字コード事情 2017版

utf8mb4_unicode_520_ciutf8mb4_unicode_520_ciUnicode Collation Algorithm 5.2.0

大文字小文字を区別しない(A=a, A=a)全角半角も区別しない(A=A)絵文字を区別する(�������������������≠�����������������)ひらがな、カタカナ、濁点有無、全角、半角を区別しない(は=ば=ぱ=ハ=バ=パ=ハ)

http://www.unicode.org/reports/tr10/tr10-20.html

Page 53: MySQLの文字コード事情 2017版

utf8mb4_*utf8mb4_*Collation A : a ������������������� : ����������������� は : ば

ぱ : ハgeneral_ci = = ≠bin ≠ ≠ ≠unicode_ci = = =unicode_520_ci = ≠ =

Page 54: MySQLの文字コード事情 2017版

utf8mb4_*utf8mb4_*Collation A : a ������������������� : ����������������� は : ば

ぱ : ハgeneral_ci = = ≠bin ≠ ≠ ≠unicode_ci = = =unicode_520_ci = ≠ =ぼくたちが欲しかったjapanese_ci

= ≠ ≠

Page 55: MySQLの文字コード事情 2017版

寿司=ビール問題 : MySQL 8.0でのUTF8寿司=ビール問題 : MySQL 8.0でのUTF8サポート入門(MySQL Server Blogより)サポート入門(MySQL Server Blogより)

https://yakst.com/ja/posts/4405

私たちは日本語の照合順序の追加も計画中です。日本語は興味深い言語であり、私たちの照合順序のエキスパート

であるXing ZhangとBernt MariusJohnsenが、今後のブログ記事でもっ

と詳しく説明するはずです。

Page 56: MySQLの文字コード事情 2017版

まとめまとめふつうは utf8mb4サーバーとクライアントの両方で Charset を指定sql_mode をちゃんと設定Collation は適切にMySQL 8 で unicode_ japanese_ci ができるかも!?