MySQL 9 min read

MySQLのTEXT型の最大文字数 ― 65,535バイトと日本語・絵文字で入る文字数

MySQL の TEXT 型に入る量は、文字数ではなくバイト数で決まっています。TEXT は 65,535 バイトなので、何文字入るかは文字コードと文字の種類で変わります。この記事の出力は MySQL 8.4.6(文字コード utf8mb4)で採りました。

まず見る(結論)

型 上限(バイト) 英数字 日本語(3バイト) 絵文字(4バイト)
TINYTEXT 255 255 85 63
TEXT 65,535 65,535 21,845 16,383
MEDIUMTEXT 16,777,215 約1,677万 約559万 約419万
LONGTEXT 4,294,967,295 約42.9億 約14.3億 約10.7億

上限のバイト数は公式マニュアルの値です。TINYTEXT の英数字と TEXT の3列は実機で確かめ、それ以外は計算で出しました。日本語の多い本文を入れる列で 21,845 文字では足りないなら、MEDIUMTEXT にします。

TEXT に入る文字数を確かめる

表 t_text(tt TINYTEXT, t TEXT, mt MEDIUMTEXT, v VARCHAR(10)) を文字コード utf8mb4 で作って試しました。

mysql> INSERT INTO t_text(t) VALUES (REPEAT('a', 65535));   -- 通る
mysql> INSERT INTO t_text(t) VALUES (REPEAT('a', 65536));
ERROR 1406 (22001): Data too long for column 't' at row 1

mysql> INSERT INTO t_text(t) VALUES (REPEAT('あ', 21845));  -- 通る
mysql> INSERT INTO t_text(t) VALUES (REPEAT('あ', 21846));
ERROR 1406 (22001): Data too long for column 't' at row 1

「あ」は UTF-8 で3バイトなので、21,845 文字でちょうど 65,535 バイトです。LENGTH(バイト数)と CHAR_LENGTH(文字数)で見ると分かります。

mysql> SELECT LENGTH(t), CHAR_LENGTH(t) FROM t_text WHERE CHAR_LENGTH(t) = 21845;
+-----------+----------------+
| LENGTH(t) | CHAR_LENGTH(t) |
+-----------+----------------+
|     65535 |          21845 |
+-----------+----------------+

絵文字(😀、4バイト)は 16,383 個(65,532 バイト)まで入り、16,384 個で ERROR 1406 になりました。

エラーにならず切り捨てられる場合

上のエラーが出るのは strict モードのときです。8.4 の既定の sql_mode には STRICT_TRANS_TABLES が入っています。

mysql> SELECT @@sql_mode;
ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION

sql_mode を空にすると、はみ出した分は切り捨てられて INSERT は成功し、警告だけが残ります。

mysql> SET SESSION sql_mode = '';
mysql> INSERT INTO t_text(t) VALUES (REPEAT('a', 65536));
mysql> SHOW WARNINGS;
+---------+------+----------------------------------------+
| Level   | Code | Message                                |
+---------+------+----------------------------------------+
| Warning | 1265 | Data truncated for column 't' at row 1 |
+---------+------+----------------------------------------+

入った値の長さは 65,535 でした。アプリケーションの接続で sql_mode を変えていると、長い文章の末尾がエラーにならずに欠けます。古いシステムから移したデータベースでは、SELECT @@GLOBAL.sql_mode; とアプリケーションの接続設定を確かめます。

VARCHAR は文字数で数える

TEXT と違い、VARCHAR(n) の n は文字数です。VARCHAR(10) に日本語10文字(30バイト)は入り、11文字では ERROR 1406 になりました。

ただし VARCHAR にも上限があります。utf8mb4 では1文字を最大4バイトとして計算するので、1列は 16,383 文字までです。

mysql> CREATE TABLE t_vc(v VARCHAR(20000)) DEFAULT CHARSET=utf8mb4;
ERROR 1074 (42000): Column length too big for column 'v' (max = 16383); use BLOB or TEXT instead

さらに、1行の VARCHAR などの列の合計にも 65,535 バイトの上限があります。VARCHAR(16383) の列1つなら作れましたが、VARCHAR(10000) を2つ並べると作れませんでした。

mysql> CREATE TABLE t_vc3(a VARCHAR(10000), b VARCHAR(10000)) DEFAULT CHARSET=utf8mb4;
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

TEXT や BLOB の本体はこの合計に含まれません(行の中にはポインターだけが残ります)。長い文字列の列が複数あるなら TEXT にします。

LONGTEXT でも1回に送れる量には上限がある

LONGTEXT の列には 4GB まで入りますが、1回の SQL でサーバーに送れる大きさは max_allowed_packet で決まります。

mysql> SELECT @@max_allowed_packet;
+----------------------+
| @@max_allowed_packet |
+----------------------+
|             67108864 |
+----------------------+

既定は 64MB です。これより大きい値を1回の INSERT で入れるなら、サーバーとクライアントの両方でこの値を上げます。