恢复 Django-mailer 数据库时出现 MySQL 错误 1118(行大小太大)
Posted
技术标签:
【中文标题】恢复 Django-mailer 数据库时出现 MySQL 错误 1118(行大小太大)【英文标题】:MySQL Error 1118 (Row size too large) when restoring Django-mailer database 【发布时间】:2014-10-07 14:13:15 【问题描述】:我从 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.
我在网上阅读了很多关于这个错误的资料,但没有一个能解决我的问题。
注意此错误不是来自表的创建,而是插入了包含大量数据的行。
注意事项:
-
innodb_file_format 和 innodb_file_format_max 变量设置为 Barracuda。
在创建表时将 ROW_FORMAT 设置为 DYNAMIC。
该表没有很多列。架构如下:
+----------------+------------+------+-----+---------+----------------+
| 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
【问题讨论】:
这可能对MySQL "Row size too large" when saving many text fields
有帮助
【参考方案1】:
根据this 问题的答案之一,您的问题可能是由 MySQL 5.6 中的更改引起的(请参阅http://dev.mysql.com/doc/relnotes/mysql/5.6/en/news-5-6-20.html 上的 InnoDB 注释):
InnoDB 笔记
重要更改:为大型外部存储的 BLOB 重做日志写入 字段可能会覆盖最近的检查点。 5.6.20 补丁 将重做日志 BLOB 写入的大小限制为重做日志文件的 10% 尺寸。 5.7.5 补丁解决了该错误,但没有施加限制。 对于 MySQL 5.5,该错误仍然是一个已知限制。
由于 MySQL 5.6 引入了重做日志 BLOB 写入限制, innodb_log_file_size 设置应该比 在表的行中找到的最大 BLOB 数据大小加上 其他可变长度字段的长度(VARCHAR、VARBINARY 和 TEXT 类型字段)。如果您的 innodb_log_file_size 不需要任何操作 设置已经足够大或您的表不包含 BLOB 数据。
注意在 MySQL 5.6.22 中,redo log BLOB 写入限制放宽到 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)。
【讨论】:
谢谢,这对我也有用,但起初我不愿意增加对建议大小的限制。我在 InnoDB 中存储了 20 个 meg 文件作为 blob,我真的必须将 log_file_size 增加到 200M 并将缓冲区大小增加到 800M 才能正确导入它们。生病了。【参考方案2】:如果这对任何人有用,@klasske 解决方案对我不起作用,但是在 'my.cnf' 中写下这一行:
innodb_file_format=Barracuda
【讨论】:
这实际上是做什么的? 允许数据库以较新的梭子鱼格式创建表。但这并不意味着它会(取决于您的 MySQL 版本和其他设置)。您可能还需要在表创建语句中添加innodb_file_per_table
和ROW_FORMAT=COMPRESSED
或ROW_FORMAT=DYNAMIC
。这解决了我在 MySQL 5.5 上的行大小问题【参考方案3】:
我在我的项目中遇到了同样的错误。我尝试了很多建议,例如增加innodb_log_file_size
、innodb_buffer_pool_size
甚至在my.cnf
文件中禁用严格模式innodb_strict_mode=0
,但对我没有任何效果。
对我有用的是:
-
将带有大
max_length
的有问题的 CharFields 更改为 TextFields。例如,models.CharField(max_length=4000)
到 models.TextField(max_length=4000)
仅在第一个解决方案之后将表拆分为多个表是不够的。
只有在这样做之后我才摆脱了错误。
最近,在同一个项目中,同样的错误再次困扰着我。这一次,当我运行python manage.py test
时。我很困惑,因为我已经拆分了表格并将CharFields
更改为TextFields
。
所以我创建了另一个虚拟 Django 项目,其数据库与我的主项目不同。我将主项目中的models.py
复制到虚拟项目中并运行迁移。令我惊讶的是,一切都很顺利。
我突然意识到我的主要项目迁移可能有问题。也许运行 manage.py test
会使用我之前的迁移与有问题的 CharFields?我不确定。
所以我在运行测试时通过编辑 settings.py
并在文件末尾添加以下 sn-p 来禁用迁移。它在测试时禁用迁移并解决错误。
class DisableMigrations(object):
def __contains__(self, item):
return True
def __getitem__(self, item):
return None
if 'test' in sys.argv[1:]:
MIGRATION_MODULES = DisableMigrations()
这样做为我解决了测试时的问题。我希望其他人觉得它有用。
sn-p 的来源settings_test_snippet.py
【讨论】:
【参考方案4】: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]
【讨论】:
以上是关于恢复 Django-mailer 数据库时出现 MySQL 错误 1118(行大小太大)的主要内容,如果未能解决你的问题,请参考以下文章