恢复Django-mailer数据库时MySQL Error 1118(行大小太大)

时间:2014-08-14 03:03:54

标签: mysql django innodb django-mailer

我从django应用程序中转储了一个正在运行的生产数据库,并尝试将其迁移到我的本地开发环境。生产服务器运行MySQL 5.1,本地我有5.6。

在迁移django-mailer的“messagelog”表时,我遇到了可怕的错误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.

我在网上看到很多关于这个错误的东西,但没有一个能解决我的问题。

N.B。这个错误来自创建表,而是插入一个包含相当大数据的行。

注意:

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

  4. 同样,只有当我尝试插入一个非常大的(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

4 个答案:

答案 0 :(得分:19)

根据this问题的答案之一,您的问题可能是由MySQL 5.6中的更改引起的(请参阅http://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-20.html上的InnoDB Notes):

  

InnoDB Notes

     

重要更改:重做日志写入大型外部存储的BLOB   字段可能会覆盖最近的检查点。 5.6.20补丁   将重做日志的大小限制为BLOB写入重做日志文件的10%   尺寸。 5.7.5补丁解决了bug而没有施加限制。   对于MySQL 5.5,该bug仍然是一个已知的限制。

     

由于为MySQL 5.6引入了重做日志BLOB写入限制,   innodb_log_file_size设置应该比10倍大   在表格的行中找到的最大BLOB数据大小加上   其他可变长度字段的长度(VARCHAR,VARBINARY和TEXT   类型字段)。如果你的innodb_log_file_size不需要任何操作   设置已经足够大或您的表不包含BLOB   数据

     

注意在MySQL 5.6.22中,重做日志BLOB写入限制放宽到10%   总重做日志大小(innodb_log_file_size *)   innodb_log_files_in_group)。

     

(Bug#16963396,Bug#19030353,Bug#69477)

如果将innodb_log_file_size更改为大于50M的内容,会有帮助吗? (更改该变量需要一些步骤才能正常工作:

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

答案 1 :(得分:1)

如果这对任何人都有用,那么@klasske解决方案对我来说不起作用,不过在my.cnf'做的:

innodb_file_format=Barracuda

答案 2 :(得分:0)

ERROR 1118 (42000) at line 1852: 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.
[mysqld]
innodb_log_file_size = 512M
innodb_strict_mode = 0

ubuntu 16.04 edit path : nano /etc/mysql/mysql.conf.d/mysqld.cnf
it work!!….

[http://dn59-kmutnb.blogspot.com/2017/06/error-1118-42000-at-line-1852-row-size.html][1]

答案 3 :(得分:0)

我在我的项目中遇到了同样的错误。我尝试了很多建议,例如在 innodb_log_file_size 文件中增加 innodb_buffer_pool_sizeinnodb_strict_mode=0 甚至禁用严格模式 my.cnf,但没有任何效果。

对我有用的是以下内容:

  1. 将带有大 max_length 的违规 CharFields 更改为 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

的来源