运行迁移文件报错,引出的一些疑问.

学习教程《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.125.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字符的字节长度,算不算是一个官方的疏忽?

《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 2
leo

你的第二个结论是错的,Laravel 并没有指定使用什么引擎,创建的表是什么引擎取决于 MySQL 的默认设置。

3年前 评论
Young_Tao (楼主) 3年前

config 里,我加了 'engine' => 'InnoDB',好像不起作用

3年前 评论
Young_Tao (楼主) 3年前

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