Исправляем ошибку MySQL «Row size too large» в 1с-Битрикс

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Если Вы используете в своих проектах инфоблоки 2.0 и таблицы InnoDB, то есть шанс в один прекрасный момент столкнуться с ошибкой MySQL «SQL Error (1118): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. You have to change some columns to TEXT or BLOBs» (или «Got error 139 from storage engine»). Ниже рассмотрены причины и условия ее возникновения, а также различные методы устранения, с вмешательством в настройки сервера или без него.

Причины

Данная ошибка возникает в таблицах InnoDB при попытке чтения строки с большим количеством заполненных текстовых полей. Сумма длин всех текстовых полей (но не более 768 байтов каждого поля) не должна превышать половины страницы памяти, которая указана в настройках MySQL. В моем случае это было 16кб, отсюда и цифра 8126 байт в названии ошибки.

Условия возникновения в 1с-Битрикс

К ошибке приводит совокупность факторов:
- использование инфоблоков 2.0, т.е. хранение свойств в отдельных таблицах;
- MySQL в качестве сервера базы данных;
- тип InnoDB для таблицы свойств инфоблока;
- большое количество свойств строкового типа. Точная цифра зависит от настроек сервера.

Методы решения

Условно решения можно разделить на 2 группы — с необходимостью правки конфигурации сервера и без нее. Все советы даны применительно к битриксу. Естественно перед экспериментами нужно сделать резервную копию.

Без правки конфигурации:

1. Перевести таблицу в MyISAM. В моем случае это вызвало 2 проблемы — битрикс неправильно конвертировал заполненные значения свойств и при первом добавлении элемента инфоблока пропали половина свойств других элементов. Почему именно так получилось не ясно, но факт остается фактом — риск поломать таблицу есть.

2. Вернуться на инфоблоки 1.0. В этом случае каждое свойство будет храниться в отдельной строке общей таблицы, строка «влезет» в отведенную ей память и ошибка пропадет. Метод не всегда применим, потому что есть некоторые различия в форматах объектов, возвращаемых функцией CIBlockElement::GetList(), и в некоторых случаях придется переписывать код.

С вмешательством в настройки сервера:

1. Увеличить размер страницы памяти. Для этого в файле univ.i установить значения

#define UNIV_PAGE_SIZE (8 * 8192)
#define UNIV_PAGE_SIZE_SHIFT 16

и пересобрать MySQL.

Минусы подхода хорошо описаны в этой статье.

2. Для MySQL версии > 5.5 изменить формат таблиц на DYNAMIC

ALTER TABLE tableName ENGINE = InnoDB ROW_FORMAT = Dynamic;

Для MySQL версии > 5.0 нужно сначала подключить InnoDB через плагин, поддерживающий формат файлов barracuda.

Хостинг TimeWeb точно подвержен этой ошибке. Будьте внимательны и заранее продумывайте архитектуру проекта.

Интересные статьи

Интересные статьи

Если вы последние лет десять следите за обновлениями «коробочной версии» Битрикса (не 24), то давно уже заметили, что обновляется только модуль магазина и его окружение. Все остальные модули как ...
Здравствуйте! Меня зовут Максим Матюхин, я PHP-программист Badoo. В своей работе мы активно используем MySQL. Но иногда нам не хватает её производительности, поэтому мы постоянно ищем возможн...
Одной из «киллер-фич» 12й версии Битрикса была объявлена возможность отдавать статические файлы из CDN, тем самым увеличивая скорость работы сайта. Попробуем оценить практический выигрыш от использова...
Реализация ORM в ядре D7 — очередная интересная, перспективная, но как обычно плохо документированная разработка от 1с-Битрикс :) Призвана она абстрагировать разработчика от механики работы с табл...
Один из самых острых вопросов при разработке на Битрикс - это миграции базы данных. Какие же способы облегчить эту задачу есть на данный момент?