解决迁移数据库错误,索引长度过长

  • 环境:phpstudy(apache2.4.39,mysql5.7.26,php7.3.4)

在使用laravel自带的迁移数据库的命令时报错:

  SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too
long; max key length is 1000 bytes (SQL: alter table `users` add unique `users_e
mail_unique`(`email`))

网上有很多文章的解决方案是手动配置迁移生成的默认字符串长度
修改 /app/Providers/AppServiceProvider.php 中的 Schema::defaultStringLength 方法来配置它

use Illuminate\Support\Facades\Schema;

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

但这个方案比较适合使用较老版本的mysql或者MariaDB

通过查看迁移的数据表使用的引擎发现是使用的myisam

myisam 存储引擎在创建索引的时候,索引键长度是有一个较为严格的长度限制的,所有索引键最大长度总和不能超过1000,而且不是实际数据长度的总和,而是索引键字段定义长度的总和。

编码 大小 字符
latin1 1 byte 1 character
gbk 2 byte 1 character
uft8 3 byte 1 character
uft8mb4 4 byte 1 character

根据这一发现我们可以选择另一种方案修改数据库使用引擎来解决,config/database.php配置数据库默认的引擎。

#参数改为InnoDB,也可以添加参数默认设置为 InnoDB ROW_FORMAT=DYNAMIC
return [
...
'mysql' => [
    ...
  'engine' => 'InnoDB ROW_FORMAT=DYNAMIC',
],
...
];

注意:mysql的版本的默认配置不同也会造成创建表时的ROW_FORMAT的默认值不同或innodb_large_prefix配置不同,当innodb_large_prefix为OFF的最大值为 767 bytes,当为ON时最大值为 3072bytes

总结:

查询资料,找到了几种方法,包括调整编码也可以在某些环境解决问题,应该根据自己的开发/生产环境以及自己的需求来作为解决方案,我个人偏向打开开启innodb_large_prefix后,修改默认引擎设置动态表来解决该问题,但不适合所有人特别是数据量大的数据库,根据自己的业务需要了解引擎特性和静态表和动态表之间的区别。

本作品采用《CC 协议》,转载必须注明作者和本文链接
嘉宝君
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 2

楼主总结很好,公司买了阿里的RDS,我部署的时候执行migrate命令,一直报Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes错误。试了在AppServiceProvider中添加Schema::defaultStringLength(191);虽然创建表成功了,但是项目中使用laravel-permission,创建表还是一直失败,因为索引长度过长。

然后又去查表引擎和ROW_FORMAT都没问题。

直到把innodb_large_prefix改成ON就OK了

3年前 评论

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