Ошибка MySQL InnoDB "1118 Row size too large" - причины и лечение

Приветствую тебя, читатель! Если ты, как и я однажды, столкнулся с этой ошибкой, скорее всего ты либо работаешь над крупным проектом, в базе данных которого встретилась таблица с большим количеством текстовых полей, либо схему данных твоего проекта нельзя назвать слишком-то оптимальной. В моём случае большое количество полей типа TEXT было действительно необходимо, что и привело к данной ошибке, которая стала для меня совершенной неожиданностью.


Вот её полный текст:

1118 Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.

Возможен ещё такой вариант:

Got error 139 from storage engine.

Неявные ограничения InnoDB

В InnoDB по умолчанию существует ограничение на объем данных, которые можно хранить в одной строке таблицы. Оно составляет 8 килобайт (половина от объема страницы памяти, с которыми работает MySQL). Поскольку первые 768 байтов каждого текстового поля хранится непосредственно в табличных строках, максимальное количество текстовых полей длиной больше 768 байт, которое можно безопасно создать в таблице InnoDB - 10.

Надо сказать, что эта особенность относится не только к полям типа TEXT, но и к полям любого другого типа, просто с помощью текстовых полей у нас больше шансов достигнуть лимита. Если архитектура проекта всё же требует именно такой структуры данных, ошибку можно победить в 3 несложных шага:

Шаг первый: формат InnoDB файлов Barracuda

Для включения нового формата файлов InnoDB в MySQL >=5.5 достаточно указать в файле my.cnf:


innodb_file_format = Barracuda
                    

Включая новый формат, можно за одно добавить опцию innodb_file_per_table, благодаря которой каждая таблица InnoDB будет храниться в отдельном файле. Это гораздо удобней и безопасней:


innodb_file_per_table = 1
                    

Для более ранних версий MySQL формат Barracuda можно подключить через специальный плагин.

Шаг второй: innodb_strict_mode

В целях предотвращения неожиданностей стоит добавить в my.cnf innodb_strict_mode. Теперь, если таблица не будет удовлетворять ограничениям InnoDB, при её создании будет происходить ошибка.


innodb_strict_mode = ON
                    

Шаг третий: формат строк Dynamic

А для тех таблиц, которые не влезают в ограничения InnoDB нужно установить ROW_FORMAT = Dynamic:


ALTER TABLE tableName ENGINE = InnoDB ROW_FORMAT = Dynamic;
                    

Проделав эти шаги, можно начать наслаждаться отсутствием ошибок, а можно ещё разок подумать над структурой данных, которую разработчики MySQL, видимо, сочли бы невероятной и недостижимой ;)