utf8mb4
照合では文字セットを使用するのが最適utf8mb4_unicode_ci
です。
文字セットはutf8
、可能な文字数の約6%の少量のUTF-8コードポイントのみをサポートしています。utf8
Basic Multilingual Plane(BMP)のみをサポートします。他に16機あります。各プレーンには65,536文字が含まれています。utf8mb4
17面すべてをサポートします。
MySQLは4バイトのUTF-8文字を切り捨て、データが破損します。
このutf8mb4
文字セットは2010-03-24のMySQL 5.5.3で導入されました。
新しい文字セットを使用するために必要な変更の一部は簡単ではありません。
- アプリケーションデータベースアダプタで変更を行う必要がある場合があります。
- 文字セット、照合順序の設定、innodb_file_formatのバラクーダへの切り替えなど、my.cnfに変更を加える必要があります。
- SQL CREATEステートメントには、以下を含める必要がある場合があります。
ROW_FORMAT=DYNAMIC
- VARCHAR(192)以上のインデックスにはDYNAMICが必要です。
注:Barracuda
からAntelope
に切り替えると、MySQLサービスを複数回再起動する必要がある場合があります。innodb_file_format_max
MySQLサービスが次のように再起動されるまで変更されませんinnodb_file_format = barracuda
。
MySQLは古いAntelope
InnoDBファイル形式を使用します。Barracuda
は動的行フォーマットをサポートします。これは、文字セットに切り替えた後にインデックスとキーを作成するためのSQLエラーにヒットしたくない場合に必要です。utf8mb4
- #1709-インデックス列のサイズが大きすぎます。列の最大サイズは767バイトです。
- #1071-指定されたキーが長すぎました。キーの最大長は767バイトです
次のシナリオはMySQL 5.6.17でテストされています。デフォルトでは、MySQLは次のように構成されています。
SHOW VARIABLES;
innodb_large_prefix = OFF
innodb_file_format = Antelope
MySQLサービスを停止し、既存のmy.cnfにオプションを追加します。
[client]
default-character-set= utf8mb4
[mysqld]
explicit_defaults_for_timestamp = true
innodb_large_prefix = true
innodb_file_format = barracuda
innodb_file_format_max = barracuda
innodb_file_per_table = true
# Character collation
character_set_server=utf8mb4
collation_server=utf8mb4_unicode_ci
SQL CREATEステートメントの例:
CREATE TABLE Contacts (
id INT AUTO_INCREMENT NOT NULL,
ownerId INT DEFAULT NULL,
created timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
modified timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
contact VARCHAR(640) NOT NULL,
prefix VARCHAR(128) NOT NULL,
first VARCHAR(128) NOT NULL,
middle VARCHAR(128) NOT NULL,
last VARCHAR(128) NOT NULL,
suffix VARCHAR(128) NOT NULL,
notes MEDIUMTEXT NOT NULL,
INDEX IDX_CA367725E05EFD25 (ownerId),
INDEX created (created),
INDEX modified_idx (modified),
INDEX contact_idx (contact),
PRIMARY KEY(id)
) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB ROW_FORMAT=DYNAMIC;
- がCREATEステートメントから削除された
INDEX contact_idx (contact)
場合に生成されたエラー#1709を確認できますROW_FORMAT=DYNAMIC
。
注:インデックスを変更して最初の128文字に制限すると、contact
BarracudaをROW_FORMAT=DYNAMIC
INDEX contact_idx (contact(128)),
また、フィールドのサイズがVARCHAR(128)
であると表示されている場合、128バイトではありません。128バイトの4バイト文字または128バイトの1バイト文字を使用できます。
このINSERT
ステートメントには、2行に4バイトの「poo」文字が含まれている必要があります。
INSERT INTO `Contacts` (`id`, `ownerId`, `created`, `modified`, `contact`, `prefix`, `first`, `middle`, `last`, `suffix`, `notes`) VALUES
(1, NULL, '0000-00-00 00:00:00', '2014-08-25 03:00:36', '1234567890', '12345678901234567890', '1234567890123456789012345678901234567890', '1234567890123456789012345678901234567890', '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678', '', ''),
(2, NULL, '0000-00-00 00:00:00', '2014-08-25 03:05:57', 'poo', '12345678901234567890', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '', ''),
(3, NULL, '0000-00-00 00:00:00', '2014-08-25 03:05:57', 'poo', '12345678901234567890', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '123💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩💩', '', '');
last
列で使用されているスペースの量を確認できます。
mysql> SELECT BIT_LENGTH(`last`), CHAR_LENGTH(`last`) FROM `Contacts`;
+--------------------+---------------------+
| BIT_LENGTH(`last`) | CHAR_LENGTH(`last`) |
+--------------------+---------------------+
| 1024 | 128 | -- All characters are ASCII
| 4096 | 128 | -- All characters are 4 bytes
| 4024 | 128 | -- 3 characters are ASCII, 125 are 4 bytes
+--------------------+---------------------+
データベースアダプタで、接続の文字セットと照合順序を設定することができます。
SET NAMES 'utf8mb4' COLLATE 'utf8mb4_unicode_ci'
PHPでは、これは次のように設定されます。 \PDO::MYSQL_ATTR_INIT_COMMAND
参照: