关于建立索引的 767 bytes 长度限制

生产环境执行

php artisan migrate 

Laravel 抛出错误:

Index column size too large. The maximum column size is 767 bytes.

然而在本地开发的时候是正常的。

搜索了一番。 原因定位在字段的长度设置

  • Laravel 建表使用的是 utf8mb4 字符集。 这个一个4字节字符集
  • 如果说最大限制是 767 bytes。 那么一个 varchar 字段:767/4=191.75。
  • 所以我字段设置使用默认的(255),远远超出了限制。

为什么在本地开发时又正常呢?

  • 本地开发使用的 MySQL5.7 而线上环境是 MySQL5.6。
  • MySQL5.7 有默认参数 innodb_default_row_format=dynamicinnodb_large_prefix=on。这样的参数下是允许建立长字节索引的。
  • MySQL5.6 的参数 innodb_large_prefix 默认为 off ,并且没有一个默认参数可以在新建表时选择自己想要的 row_format,只能在 create tablealert table 时 加上 ROW_FORMAT=DYNAMIC

目前我试过可行的三种方法

  1. 将建立索引的 varchar 字段长度调低,使所有字段字节之和不超过 767 bytes。
  2. 建表时将 MySQL 的 charset 改为 utf8 ,collation 改为 utf8_general_ci。可在 config/database.php 中设置默认值。
  3. 将 MySQL 升级到 5.7 版本

未尝试的方法

  1. 设置 MySQL 的参数:set GLOBAL innodb_large_prefix=ON;
  2. 建表时添加 ROW_FORMAT=DYNAMIC

参考

MySQL 5.6 Reference Manual : DYNAMIC and COMPRESSED Row Formats
MySQL 5.7 Reference Manual : Limits on InnoDB Tables

本作品采用《CC 协议》,转载必须注明作者和本文链接
本帖由系统于 6年前 自动加精
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 6

使用 WordPress 搭建博客遇到类似问题,直接升级数据库版本解决

7年前 评论
leililei

MySQL数据库的编码应为utf8mb4,且要求MySQL版本在5.7.7以上或MariaDB版本在10.2.2以上。
laravel文档有说过这个问题
https://learnku.com/docs/laravel/5.6/migrations#cr...

6年前 评论

@leililei
文档并没强制要求。 MySQL 5.7以下也可以使用。只是需要注意字段长度。
而且文档也没细说索引长度限制是怎么回事

6年前 评论
滕勇志

@ealiwood 这是文档给的解决办法:

use Illuminate\Support\Facades\Schema;

/**
 * 引导任何应用程序服务。
 *
 * @return void
 */
public function boot()
{
    Schema::defaultStringLength(191);
}
6年前 评论

@轻色年华 不推荐这种解决方法,如果不是 MySQL5.7,就算是 utf8mb4 的情况下创建联合索引照样会超长。 最好就是直接升级到 MySQL 5.7

6年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!