MySQLのエラー『エラー1118: Row Size Too Large』の解決方法

MySQLのエラー『エラー1118: Row Size Too Large』の解決方法

MySQLで「エラー1118: Row size too large(行サイズが大きすぎます)」が発生するのは、1つの行のサイズがMySQLの制限を超えてしまった場合。この制限は特にInnoDBストレージエンジンで影響が出やすく、大量のカラムやTEXT/VARCHAR型を多用するテーブル設計時に遭遇しやすい。

1. エラーメッセージの例

ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB may help.

このメッセージは、1行あたりのバッファページサイズ(通常16KB)の上限を超えたときに表示される。

2. 発生条件と背景

InnoDBでは1ページ16KBの制限があり、1レコードで使えるデータサイズは最大で約8126バイト(行オーバーヘッド含む)に制限されている。多くのVARCHARカラムや長いデータ型があるとこの制限を超えてしまう。

3. TEXT型やBLOB型を使うとどうなるか

VARCHARやCHAR型は固定長・可変長でもページ内に格納されるのに対し、TEXTやBLOB型はオフページ(別領域)に格納され、ページサイズにカウントされにくくなる。

例:

CREATE TABLE example (
  col1 VARCHAR(1000),
  col2 VARCHAR(1000),
  ...
  col30 VARCHAR(1000) -- 多すぎてエラーになる
);

上記のような場合、colXをTEXT型にすることで回避可能。

4. 解決策1: カラムをTEXTまたはBLOBに変更

ALTER TABLE example MODIFY col5 TEXT;

これにより、そのカラムのデータはオフページに格納され、行サイズ制限の対象外になる。

5. 解決策2: innodb_strict_modeを無効にする(非推奨)

SET GLOBAL innodb_strict_mode = 0;

この方法は強制的にINSERTを許容するが、データが正しく格納されない可能性があり推奨されない。

6. 解決策3: DYNAMICまたはCOMPRESSEDフォーマットを使用する

InnoDBでは、テーブルフォーマットを「DYNAMIC」または「COMPRESSED」に設定することで、大きなVARCHARもオフページに追い出される。

CREATE TABLE example (
  col1 VARCHAR(1000),
  ...
) ROW_FORMAT=DYNAMIC;

既存テーブルに対しては:

ALTER TABLE example ROW_FORMAT=DYNAMIC;

7. 解決策4: 不要なカラムを削除・分割

1テーブルに大量の列を持たせるのではなく、正規化してサブテーブルに分けることで行サイズを減らせる。

8. 解決策5: VARCHARのサイズを見直す

必要以上に大きなVARCHARを指定していないか見直す。たとえばVARCHAR(10000)などは実際の使用量に比べて過大な場合が多い。

9. 解決策6: utf8mb4ではなくutf8を使う

utf8mb4は1文字4バイト、utf8は最大3バイト。もし絵文字などが不要ならutf8で十分な場合もある。

CREATE TABLE example (
  name VARCHAR(200) CHARACTER SET utf8
);

文字セットを変更することで、1列あたりのバイト数を削減可能。

10. 解決策7: テーブルの再構築と確認

テーブルを再作成したりOPTIMIZE TABLEを実行して、InnoDBの行フォーマットを見直す。

OPTIMIZE TABLE example;

11. 使用中のROW_FORMATを確認する方法

SELECT TABLE_NAME, ROW_FORMAT
FROM information_schema.tables
WHERE table_name = 'example';

現在のROW_FORMATがCOMPACTになっていればDYNAMICに変更を検討できる。

12. テーブルサイズとカラム長のバランスを意識する

大きなカラムが大量に存在する場合、ページサイズの制限に抵触しやすくなる。全体設計でサイズの上限を意識した設計が必要。