Ошибка MySQL 1118 (слишком большой размер строки) при восстановлении базы данных Django-mailer

Я выгрузил рабочую базу данных из приложения django и пытаюсь перенести ее в свою локальную среду разработки. На рабочем сервере работает MySQL 5.1, а локально у меня 5.6.

При переносе таблицы «messagelog» django-mailer я сталкиваюсь с ужасной ошибкой 1118:

ERROR 1118 (42000) at line 2226: 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.

Я много читал в Интернете об этой ошибке, но ни одна из них не решила мою проблему.

Н.Б. Эта ошибка возникает не из-за создания таблицы, а из-за вставки строки с довольно большими данными.

Примечания:

  1. Для переменных innodb_file_format и innodb_file_format_max установлено значение Barracuda.
  2. Для ROW_FORMAT устанавливается значение DYNAMIC при создании таблицы.
  3. В таблице не очень много столбцов. Схема ниже:

    +----------------+------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +----------------+------------+------+-----+---------+----------------+ | id | int(11) | NO | PRI | NULL | auto_increment | | message_data | longtext | NO | | NULL | | | when_added | datetime | NO | | NULL | | | priority | varchar(1) | NO | | NULL | | | when_attempted | datetime | NO | | NULL | | | result | varchar(1) | NO | | NULL | | | log_message | longtext | NO | | NULL | | +----------------+------------+------+-----+---------+----------------+

Опять же, ошибка возникает ТОЛЬКО, когда я пытаюсь вставить довольно большую (message_data около 5 мегабайт) строку; создание таблицы работает нормально, и до сбоя добавляется около 500 000 строк.

У меня нет идей; Я пробовал форматы строк DYANMIC и COMPRESSED и трижды проверял значения соответствующих переменных innodb:

mysql> show 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 | +--------------------------+-----------+

Код создания (из SHOW CREATE TABLE) выглядит так:

CREATE TABLE `mailer_messagelog` ( `id` int(11) NOT NULL AUTO_INCREMENT, `message_data` longtext NOT NULL, `when_added` datetime NOT NULL, `priority` varchar(1) NOT NULL, `when_attempted` datetime NOT NULL, `result` varchar(1) NOT NULL, `log_message` longtext NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=869906 DEFAULT CHARSET=latin1 ROW_FORMAT=DYNAMIC


person Greg Humphreys    schedule 14.08.2014    source источник
comment
Может быть, это поможет MySQL "Row size too large" when saving many text fields   -  person M Khalid Junaid    schedule 17.08.2014


Ответы (3)


Согласно одному из ответов на этот вопрос, ваша проблема может быть вызвана изменениями в MySQL 5.6 (см. http://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-20.html):

Примечания InnoDB

Важное изменение. Записи журнала повторов для больших полей BLOB, хранящихся во внешнем хранилище, могут перезаписывать самую последнюю контрольную точку. Патч 5.6.20 ограничивает размер записи BLOB журнала повторов до 10 % от размера файла журнала повторов. Патч 5.7.5 исправляет ошибку, не накладывая ограничений. Для MySQL 5.5 ошибка остается известным ограничением.

В результате введенного для MySQL 5.6 лимита записи BLOB-журнала повторного выполнения параметр innodb_log_file_size должен быть в 10 раз больше, чем максимальный размер данных BLOB, найденный в строках ваших таблиц, плюс длина других полей переменной длины (VARCHAR, VARBINARY и поля типа ТЕКСТ). Никаких действий не требуется, если ваш параметр innodb_log_file_size уже достаточно велик или ваши таблицы не содержат данных BLOB.

Примечание. В MySQL 5.6.22 ограничение записи больших двоичных объектов в журнал повторов снижено до 10 % от общего размера журнала повторов (innodb_log_file_size * innodb_log_files_in_group).

(Ошибка № 16963396, Ошибка № 19030353, Ошибка № 69477)

Это поможет, если вы измените innodb_log_file_size на что-то большее, чем 50M? (Чтобы изменить эту переменную, нужно выполнить несколько шагов для правильной работы:

https://dba.stackexchange.com/questions/1261/how-to-safely-change-mysql-innodb-variable-innodb-log-file-size ).

person klasske    schedule 19.08.2014
comment
Спасибо, это сработало и для меня, но сначала я не хотел увеличивать пределы до предложенного размера. У меня было 20 мегабайтных файлов, хранящихся в виде больших двоичных объектов в InnoDB, и мне действительно пришлось увеличить log_file_size до 200M и размер буфера до 800M, чтобы их правильно импортировать. Больной. - person CodeTwice; 06.11.2014

Если это полезно для кого-то, решение @klasske не сработало для меня, однако запись этой строки в «my.cnf» сработала:

innodb_file_format=Barracuda
person gorcajo    schedule 31.05.2016
comment
Что это на самом деле делает? - person Goose; 23.09.2016
comment
Позволяет базе данных создавать таблицы в более новом формате Barracuda. Но это не значит, что так и будет (в зависимости от вашей версии MySQL и других настроек). Вам также может понадобиться добавить innodb_file_per_table и иметь ROW_FORMAT=COMPRESSED или ROW_FORMAT=DYNAMIC в операторе создания таблицы. Это решило проблему с размером строки для меня в MySQL 5.5. - person swbandit; 24.09.2016

Я столкнулся с той же ошибкой в ​​​​своем проекте. Я пробовал много предложений, таких как увеличение innodb_log_file_size, innodb_buffer_pool_size или даже отключение строгого режима innodb_strict_mode=0 в файле my.cnf, но у меня ничего не получалось.

Что сработало для меня, так это следующее:

  1. Изменение оскорбительных CharFields с большим max_length на TextFields. Например, от models.CharField(max_length=4000) до models.TextField(max_length=4000)
  2. Разделение таблицы на несколько таблиц после первого решения само по себе было недостаточно.

Только после этого я избавился от ошибки.


Недавно та же ошибка снова преследовала меня на том же проекте. На этот раз, когда я запускал python manage.py test. Я был в замешательстве, потому что я уже разделил таблицы и изменил CharFields на TextFields.

Поэтому я создал еще один фиктивный проект Django с другой базой данных, отличной от моего основного проекта. Я скопировал models.py из основного проекта в фиктивный проект и запустил миграцию. К моему удивлению, все прошло нормально.

Меня осенило, что что-то может быть не так с миграциями моего основного проекта. Возможно, запуск manage.py test использует мои более ранние миграции с оскорбительными CharFields? Я не знаю наверняка.

Поэтому я отключил миграцию при запуске тестов, отредактировав settings.py и добавив следующий фрагмент в конец файла. Он отключает миграции при тестировании и устраняет ошибку.

class DisableMigrations(object):                                                                                                                     
                                                                                                                                                     
    def __contains__(self, item):                                                                                                                    
        return True                                                                                                                                  
                                                                                                                                                     
    def __getitem__(self, item):                                                                                                                     
        return None                                                                                                                                  
                                                                                                                                                     
                                                                                                                                                     
if 'test' in sys.argv[1:]:                                                                                                                           
    MIGRATION_MODULES = DisableMigrations() 

Это решило проблему для меня при тестировании. Я надеюсь, что кто-то еще найдет это полезным.

Источник фрагмента settings_test_snippet.py

person Stanley Ulili    schedule 12.05.2021