解决迁移数据库错误,索引长度过长
- 环境: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 协议》,转载必须注明作者和本文链接
:grinning:
楼主总结很好,公司买了阿里的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了