Laravel迁移MySQL字段类型异常 本地longText正常线上不符
Laravel迁移后字段类型不符合预期排查方案
运行环境
- Laravel 9
- PHP 8.1
- MySQL 5.7.38 (Linux x86_64)
核心成因
这类问题90%以上是迁移机制使用不规范导致,结合此前存在手动改库、修改历史迁移文件的操作,按出现概率排序可能原因如下:
- 修改的是已经在生产环境执行过的历史迁移文件。Laravel通过数据库里的
migrations表记录已经执行过的迁移文件,只要文件被标记为已执行,后续跑migrate命令会直接跳过,不会重新执行修改后的代码。本地验证生效是因为本地环境多为清空库后重新跑全量迁移,所有修改后的迁移文件会从头执行,生产环境是增量执行迁移,未新增的迁移文件不会触发执行。 - 生产环境部署时漏传修改后的迁移文件,或者Laravel缓存了旧的代码文件,实际执行的还是旧版本里
string('description')的逻辑,最终生成varchar(255)类型。 - 存在其他后置迁移文件在字段修改逻辑之后执行,又把
description字段改回了string类型,本地验证时没有完整跑完全部迁移流程没发现该问题。 - 小概率情况:生产数据库账号缺少ALTER权限,字段修改语句静默失败,但这类情况通常会抛出SQL异常,占比极低。
排查步骤
- 核对生产环境迁移状态
生产环境执行以下命令查看所有迁移的执行状态:
找到修改了php artisan migrate:statusdescription字段类型的对应迁移文件,查看执行时间,如果执行时间早于修改迁移文件的时间,即可确认是修改历史迁移不触发执行的问题。 - 确认生产环境实际代码版本
执行命令清除所有Laravel缓存,避免加载旧缓存文件:
直接打开生产服务器上对应迁移文件的源码,确认代码确实是php artisan optimize:clear$table->longText('description')->nullable();,排除部署漏传文件的问题。 - 排查冲突迁移
全局搜索所有迁移文件中对description字段的定义,确认是否存在其他迁移在后续执行时把字段类型改回string。 - 核对实际执行SQL
本地测试时开启数据库查询日志,查看迁移生成的对应DDL语句,确认生成的是LONGTEXT类型的修改逻辑,排除框架层面的SQL生成错误。
修复方案
全程不需要手动修改数据库结构,严格遵循Laravel迁移规范操作即可:
- 不要修改已经在任何环境执行过的历史迁移文件,这是迁移使用的核心原则,否则必然出现不同环境结构不一致的问题。
- 新建独立迁移做字段类型调整,执行以下命令生成迁移文件(将
tickets替换为实际的工单表名):php artisan make:migration modify_description_to_longtext_in_tickets_table --table=tickets - 先安装修改字段所需的依赖包:
composer require doctrine/dbal - 在新生成的迁移文件中编写调整逻辑:
public function up() { Schema::table('tickets', function (Blueprint $table) { $table->longText('description')->nullable()->change(); }); } public function down() { Schema::table('tickets', function (Blueprint $table) { $table->string('description')->nullable()->change(); }); } - 确认代码提交部署到生产环境后,执行
php artisan migrate即可完成字段类型调整,后续所有新环境部署全量迁移时,字段类型也会保持一致。
后续所有数据库结构变更必须通过新增迁移文件实现,禁止手动修改数据库结构、禁止修改已经执行过的历史迁移文件,从流程上避免环境结构不一致的问题。
内容的提问来源于stack exchange,提问作者j-bill
相关产品推荐
相关产品推荐

