MySQL: Как побороть ошибку Row size too large?

Столкнулся с такой ошибкой:
OperationalError: (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.')

В интернете почитал варианты решения. Сделал:
innodb_file_format = Barracuda
innodb_file_per_table = ON

Перезапустил сервер
mysql> show global variables like 'innodb_file%';
+--------------------------+-----------+
| Variable_name            | Value     |
+--------------------------+-----------+
| innodb_file_format       | Barracuda |
| innodb_file_format_check | ON        |
| innodb_file_format_max   | Barracuda |
| innodb_file_per_table    | ON        |
+--------------------------+-----------+

Делаю:
mysql> ALTER TABLE market_offer ROW_FORMAT=DYNAMIC;

В итоге отваливается с ошибкой:
ERROR 1118 (42000): Row size too large. The maximum row size for the used table type, not counting BLOBs, is 8126. This includes storage overhead, check the manual. You have to change some columns to TEXT or BLOBs

Подскажите, как можно её решить?

Структура таблицы:
CREATE TABLE `market_offer` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `company_id` int(11) DEFAULT NULL,
  `rubrica_id` int(11) DEFAULT NULL,
  `category_id` int(11) unsigned DEFAULT NULL,
  `artno` varchar(50) DEFAULT NULL,
  `pub_date` datetime NOT NULL,
  `keyword` varchar(100) NOT NULL,
  `slug` varchar(100) NOT NULL DEFAULT '',
  `title` varchar(300) NOT NULL,
  `tizer` text NOT NULL,
  `quantity` smallint(5) unsigned NOT NULL DEFAULT '0',
  `unit` char(3) NOT NULL DEFAULT 'PCE',
  `price` decimal(13,2) NOT NULL,
  `currency` char(3) NOT NULL DEFAULT 'RUR',
  `picture` varchar(100) NOT NULL,
  `pictureurl` varchar(500) NOT NULL,
  `url` varchar(500) NOT NULL,
  `text` text NOT NULL,
  `info` longtext NOT NULL,
  `lastmodified` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `is_active` tinyint(1) NOT NULL DEFAULT '1',
  PRIMARY KEY (`id`),
  KEY `rubrica_id` (`rubrica_id`),
  KEY `company_id` (`company_id`),
  KEY `user_id` (`user_id`),
  KEY `category_id` (`category_id`),
  KEY `category_pubdate` (`category_id`,`pub_date`),
  KEY `rubrica_title` (`rubrica_id`,`title`(255)),
  KEY `market_offer_e01be369` (`is_active`),
  KEY `lastmodified` (`lastmodified`),
  KEY `market_offer_c4ebad10` (`lastmodified`),
  KEY `picture` (`picture`),
  CONSTRAINT `market_offer_ibfk_8` FOREIGN KEY (`category_id`) REFERENCES `market_category` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `user_id_refs_id_3cfc06ff` FOREIGN KEY (`user_id`) REFERENCES `users_user` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=14943895749 DEFAULT CHARSET=utf8
  • Вопрос задан
  • 20851 просмотр
Решения вопроса 1
MikeVL
@MikeVL Автор вопроса
Лишние индексы удалил. Но не получается сменить тип полей.

mysql> ALTER TABLE market_offer MODIFY `text` LONGTEXT, MODIFY `tizer` LONGTEXT, MODIFY title TEXT, MODIFY picture TEXT, MODIFY pictureurl TEXT, MODIFY url TEXT, ROW_FORMAT=COMPRESSED;
ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
Error (Code 1118): Row size too large (> 8126). Changing some columns to TEXT or BLOB may help. In current row format, BLOB prefix of 0 bytes is stored inline.
Error (Code 1030): Got error 139 from storage engine

Еще одна интересная вешь, за пару дней таблицы выросла в 4 раза.

mysql> SHOW TABLE STATUS LIKE 'market_offer'\G
*************************** 1. row ***************************
           Name: market_offer
         Engine: InnoDB
        Version: 10
     Row_format: Compact
           Rows: 24329782
 Avg_row_length: 1333
    Data_length: 32445038592
Max_data_length: 0
   Index_length: 1818722304
      Data_free: 950009856
 Auto_increment: 14943874034
    Create_time: 2014-09-19 19:30:18
    Update_time: NULL
     Check_time: NULL
      Collation: utf8_general_ci
       Checksum: NULL
 Create_options:
        Comment:
1 row in set (0.05 sec)

Rows: 24329782

А по факту в БД находится:
mysql> select count(*) from market_offer\G
*************************** 1. row ***************************
count(*): 4956036
Ответ написан
Пригласить эксперта
Ответы на вопрос 4
Смените тип поля на которое ругается на longtext и всё
Ответ написан
Для начала, я бы вынес поля 'picture' и 'pictureurl' в отдельную таблицу, а в эту добавил бы только ссылку на нее ('picture_id'). Также можно избавиться от поля 'url', которое, скорее всего, можно сгенерировать в коде из поля 'slug'. Если от 'url' невозможно избавиться, то сделайте его TEXT. Удалите ненужные индексы: 'rubrica_id' (дублируется в 'rubrica_title'), 'category_id' (дублируется в 'category_pubdate') и 'lastmodified' (дублируется в 'market_offer_c4ebad10'). Еще небольшое замечание по индексу 'rubrica_title' - если вы ищете по началу поля 'title', то все нормально (хотя можно и уменьшить до 20-40), а если сортируете по этому полю или ищите по середине ( LIKE '%something%'), то этот индекс не используется, т.к. в индексе используется только часть поля 'title'.
После этих шагов, ошибка должна исчезнуть.

UPD: Если не хотите выносить picture в отдельную таблицу, то смените тип 'pictureurl' на TEXT.
Ответ написан
Комментировать
@WebmasterW3S
Веб-программист
Самое простое - сменить движок на MyISAM
Ответ написан
Комментировать
@tomazov
проверяйте параметры Mysql innodb_page_size и innodb_strict_mode
https://mariadb.com/kb/en/troubleshooting-row-size...
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы