运行迁移文件报错,引出的一些疑问.
学习教程《L02 Laravel 教程 - Web 开发实战进阶 ( Laravel 6.x ) 》过程中遇到数据库迁移命令php artisan migrate
的使用.在运行迁移命令的时候,Laravel自带的用户认证迁移文件产生报错.由于我使用的环境不是教程推荐的环境,所以我不确定这一系列问题是否适合由环境引起.但是首先确定一点,laravel项目文件是通过composer创建的6.*
版本.错误如下:
C:\Users\Administrator\MyCode\blog>php artisan migrate
Migration table created successfully.
Migrating: 2014_10_12_000000_create_users_table
Illuminate\Database\QueryException : 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_email_unique`(`email`))
...
...
Exception trace:
1 PDOException::("SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 1000 bytes")
C:\Users\Administrator\MyCode\blog\vendor\laravel\framework\src\Illuminate\Database\Connection.php:463
2 PDOStatement::execute()
C:\Users\Administrator\MyCode\blog\vendor\laravel\framework\src\Illuminate\Database\Connection.php:463
查了一下论坛之前的问题也有人提过这个问题.解决方法:
问答:最新的修改方案,提示 specified key was too long,怎么解决?
在评论里有提到的解决方式:
1.即在 AppServiceProvider
中调用 Schema::defaultStringLength
use Illuminate\Support\Facades\Schema;
/**
* 引导任何应用程序服务。
*
* @return void
*/
public function boot()
{
Schema::defaultStringLength(191);
}
这种方式全局修改了字符串长度,似乎不够灵活.
在查资料的过程中我看到有的说法是mysql 5.7.7
以上版本不会出现这个问题,我尝试了将mysql
更换成8.0.12
版本再次运行迁移文件,还是同样的报错.
后面的评论中还对数据库知识进行了补充:
对于 myisam 和 innodb 存储引擎,prefixes 的长度限制分别为 1000 字节和 767 字节。注意 prefix 的单位是 字节,但是建表时我们指定的长度单位是 字符 。utf8 下 3 字节表示一个字符,utf8mb4 是 4 字节表示一个字符,以 innodb 存储引擎来换算:utf8 下长度 255 的字符索引占 255X3=765 字节,但 Laravel 默认使用 utf8mb4 ,这样 255X4=1020,超过了 767 字节,改称 191 后,191X4=764 字节。这也是为什么要指定默认字符串长度191,其实如果你用不么这么长,指定小于191的也可以。
我去查看了数据库的表引擎,发现迁移文件默认生成表的引擎是MyISMA
,根据laravel文档给迁移文件添加了命令$table->engine = 'InnoDB'
尝试使用InnoDB
引擎:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->engine = 'InnoDB';//添加引擎定义命令
$table->bigIncrements('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('users');
}
}
并在8.0.12
和5.7.26
版本中的mysql中运行均成功.
所以引发几点疑问:
1.根据上述的数据库知识补充,InnoDB索引长度为767个字节,不能满足255个utf8mb4格式字符的字节长度.为什么使用了InnoDB的引擎后运行成功.是Mysql默认开启了上述解决办法链接评论中的提到的innodb_large_prefix选项吗?
2.Laravel在Blueprint中table的string默认设置长度为255,并且默认使用utf8mb4的格式.但是却又默认使用MyISMA的表引擎,这是否是一个自相矛盾的设置?
3.Laravel自带的用户认证迁移文件,并没有使用修改引擎的命令.根据上文的数据库知识,MyISMA也不能满足255个utf8mb4字符的字节长度,算不算是一个官方的疏忽?
推荐文章: