You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Laravel迁移默认使用不支持关联的MyISAM引擎的原因及最佳实践

关于Laravel迁移默认引擎与数据库关系的最佳实践

首先得澄清一个关键细节:Laravel 5.2及之后的版本,默认数据库引擎已经是InnoDB了。如果你遇到默认用MyISAM的情况,大概率是这两个原因:

  • 你在用比较老旧的Laravel版本(比如5.1及更早),当时MyISAM因读性能优势、以及部分服务器默认MySQL引擎为MyISAM,被设为默认;
  • 你的config/database.php配置文件里未明确指定引擎,或者engine配置项被手动设为了MyISAM

要不要在数据库中设置关系?

绝对要!Laravel的Eloquent ORM提供的关系是应用层面的语法便利,而数据库层面的外键约束是数据完整性的最后防线——两者是互补关系,完全不能互相替代。举个实际例子:如果有人直接通过SQL语句(绕过你的Laravel应用)往子表里插入一条不存在的父表ID记录,Eloquent的关系校验根本管不住,但数据库的外键约束会直接拒绝这条插入,避免出现“孤儿数据”。

不设置数据库外键的风险

最直接的问题就是数据不一致:比如你删除了users表中的某个用户,但posts表中关联该用户的文章还留在数据库里,后续查询用户的文章时就会出现逻辑错误,而且这种脏数据很难排查。另外,没有外键约束的话,数据库也无法帮你自动处理级联操作(比如删除用户时自动删除他的所有文章)。

相关最佳实践

  • 全局配置默认引擎为InnoDB:打开config/database.php,找到mysql配置数组,添加'engine' => 'InnoDB',,这样所有新迁移创建的表都会默认用InnoDB,不用每次在迁移里单独设置。
  • 迁移中正确定义外键:确保外键字段的类型和关联表的主键类型完全一致(比如关联users.id的话,外键字段要设为unsignedBigInteger),同时明确级联规则,示例代码:
    $table->foreign('user_id')
          ->references('id')
          ->on('users')
          ->onDelete('cascade'); // 删除用户时自动删除关联文章
    
  • 同时使用Eloquent关系和数据库外键:Eloquent的belongsTohasMany等关系让你可以用优雅的语法查询关联数据,而数据库外键保证数据不会被非法篡改,两者搭配使用才是最优解。
  • 确保外键约束在开发环境启用:有些人为了方便会关闭外键检查,但开发时一定要开着,这样能提前发现数据逻辑问题。Laravel中可以在数据库配置里设置'foreign_key_constraints' => true,
  • 旧项目引擎迁移注意事项:如果你的旧项目用了MyISAM,切换到InnoDB前一定要备份数据,然后可以用SQL批量修改表引擎,之后重新添加外键约束(MyISAM不支持外键,所以之前的外键定义其实没生效)。

内容的提问来源于stack exchange,提问作者Sitepose

火山引擎 最新活动