Laravel5.4 数据库迁移错误 SQLSTATE [42000] Syntax error or access violation 1071
laralve5.4版本中我写好了数据库迁移文件, 在本机的mysql5.7.23中执行没有问题.
但是提交git后同事(mysql5.6.*)执行该迁移就报错了很是奇怪.
从网上查找解决方案后,又尝试着深入写分析了下问题
以下记录了查找错误的过程.
In Connection.php line 647:
SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `password_reset
s` add index `password_resets_email_index`(`email`))
从报错信息可以看出:索引长度的最大限制是767bytes, 而欲在email字段创建的索引长度超过了这个范围
计算email字段索引长度
首先查看创建email字段并加索引的文件
table->string('email')->index();
这样创建的email字段默认类型varchar默认长度为255, 编码(Collation)类型会读取laravelProject/config/database.php
中的配置
<?php
return [
'connections' => [
//...
'mysql' => [
//...
'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',
],
//...
],
];
可以看出varchar会使用utf8mb4编码, utf8mb4编码(4bytes)
属于utf8编码(3bytes)的
扩展类型,
由此可以计算索引长度为255*4+2=1022
>767
分析错误原因
对比laravel5.3和laravel5.4的laravelProject/config/database.php
文件 可以看出
laravel5.4中改变了默认的编码类型(utf8 => utf8mb4)
, 从而使email字段索引长度超过了的默认限制长度.
而新版本mysql>= 5.7.7
(mysql5.7.7更新日志):默认打开了innodb_large_prefix
,使索引长度限制由767bytes
增加到了3072bytes
. 所以不会导致迁移报错.
四种解决方案
知道原因后解决方案就很明显了
-
编辑AppServiceProvider.php
use Illuminate\Support\Facades\Schema; public function boot() { Schema::defaultStringLength(191); }
原理:改变了默认的
string()
方法生成的varchar长度,而191*4+2 = 766 < 767
合法; -
修改
laravelProject/config/database.php
配置文件<?php return [ 'connections' => [ //... 'mysql' => [ //... 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', ], //... ], ];
原理: 将默认编码仍然修改为utf8编码.
-
升级mysql>=5.7.7
-
修改mysql配置
如果由于某些原因你不能升级你的数据库版本,则可以单独修改数据库的配置,解除innodb_large_prefix的限制.(需FQ)
以上解决方案任选其一即可!!!
本作品采用《CC 协议》,转载必须注明作者和本文链接
大赞,很有用