MySQL 5.7から8.0へのアップグレード時にバックアップのインポートが失敗する問題、「行長さが大きすぎる」エラーについて解説します。
問題の再現
以下のようなテーブルを作成し、データをインポートしようとしたときのエラーです。
DROP TABLE IF EXISTS user_profile;
CREATE TABLE user_profile (
id INT NOT NULL AUTO_INCREMENT,
user_name VARCHAR(255),
pass_word VARCHAR(255),
full_name VARCHAR(255),
address VARCHAR(255),
mobile VARCHAR(255),
phone VARCHAR(255),
email_addr VARCHAR(255),
gender CHAR(1),
type_user CHAR(1),
descr TEXT,
temp_pass VARCHAR(255),
created_at DATETIME,
creator VARCHAR(255),
expire_date DATETIME,
pass_expire DATETIME,
login_stat CHAR(1),
first_login DATETIME,
last_login DATETIME DEFAULT NULL COMMENT '最終ログイン時間',
block_flag CHAR(1),
block_reason VARCHAR(1000),
last_pass_change DATETIME,
status CHAR(1),
home_page VARCHAR(255),
theme VARCHAR(255),
id_number VARCHAR(255),
dept VARCHAR(100),
admin_flag CHAR(1),
area_code VARCHAR(50),
PRIMARY KEY (id)
) ROW_FORMAT=DYNAMIC;
エラーメッセージ
ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help.
問題分析
上記エラーメッセージは、block_reasonフィールドを追加した結果、行サイズが最大許容値(8126バイト)を超えたことを示しています。
解決策
-
行フォーマットの変更:
ROW_FORMAT=DYNAMICまたはROW_FORMAT=COMPRESSEDを使用します。デフォルト設定でinnodb_default_row_formatがdynamicに設定されているため、ROW_FORMATを指定せずにテーブルを作成すると自動的に適用されます。 -
ページサイズの調整:
innodb_page_sizeを32KB以上に設定し、データベースを再初期化します。 -
厳格モードの無効化:
innodb_strict_mode=OFFに設定します。ただし、これは一時的な回避策であり、長期的には推奨されません。
行フォーマットの詳細
- DYNAMIC:BLOB/TEXT型のデータを完全にオーバーフローページに保存し、行内には20バイトのポインタのみを保持します。
- COMPACT:VARCHARやTEXT型の最初の768バイトをB-treeノード内のインデックスレコードに保存し、残りをオーバーフローページに保存します。
- COMPRESSED:DYNAMICと同様の機能を持ちつつ、データ圧縮もサポートしています。