MySQL 5.7执行rake db:schema:load报行过大错误,5.6正常原因?
为啥MySQL 5.7建表失败,5.6却没问题?
这个问题的核心是MySQL 5.6和5.7默认开启的InnoDB严格模式不一样,再加上InnoDB对行大小的检查逻辑有变化,咱们一步步拆解清楚:
1. 关键参数innodb_strict_mode的默认值差异
- 在MySQL 5.6里,
innodb_strict_mode默认是关闭的,InnoDB对行大小的限制检查比较宽松; - 到了MySQL 5.7,这个参数默认开启了,InnoDB会严格卡着行大小的阈值来检查。
InnoDB默认的页大小是16KB,它要求单条记录的核心存储大小(不算溢出到页外的内容)不能超过页的一半,也就是大概8126字节——这是为了保证页内至少能放下两条记录,维持索引的高效性。开启严格模式后,它会直接计算你表中所有字段的最大潜在字节数总和,如果超过这个阈值,直接报错拒绝建表。
2. 你的表为啥触发了这个限制?
看你的表结构,url字段是varchar(16383),如果你的数据库用的是utf8字符集(每个字符最多占3字节),这个字段的最大可能字节数是16383 × 3 = 49149字节,这已经远远超过了8126的阈值。再加上其他字段的大小(比如几个整数、datetime、其他varchar),总潜在大小直接超标。
3. 为啥5.6能成功?
在MySQL 5.6里,因为严格模式没开,哪怕计算出来的最大行大小超标,只要你的字段是可变长度类型(比如varchar、text),InnoDB会自动把超长的部分溢出到页外存储,所以不会拦着你建表。但5.7开了严格模式后,它不管你能不能溢出,先看最大潜在大小超不超标,超标就直接报错。
怎么解决这个问题?
如果要在MySQL 5.7里建好这个表,给你几个可行方案:
- 临时关闭严格模式:先执行
SET GLOBAL innodb_strict_mode=OFF;(需要管理员权限),然后再跑rake db:schema:load,之后可以根据需求决定要不要重新开启; - 把
url改成text类型:text字段本身就是设计来存大内容的,会直接溢出到页外,不会被计入行大小的严格检查; - 切换InnoDB行格式为
DYNAMIC或COMPRESSED:这两种行格式对可变长度字段的溢出处理更灵活,配合调整字段或者关闭严格模式也能解决。建表时可以指定行格式:CREATE TABLE `inv_audits` ( -- 你的字段定义不变 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;
内容的提问来源于stack exchange,提问作者David Moles
相关产品推荐
相关产品推荐

