php artisan migrate:rollback 按 batch 回滚而非文件,--step=1 撤销 batch 值最大的一批迁移(可能含多个文件);batch 全为 0 表示未登记,回滚无效;精准回滚需手动篡改 migrations 表 batch 字段;db::transaction 与 migrate:rollback 作用域不同,不可替代;生产环境禁止使用 rollback。

php artisan migrate:rollback 只按 batch 回滚,不是按文件
它撤的是 migrations 表里 batch 值最大的那一批记录,而不是你想象中“最近改的两个迁移文件”。比如你一次 php artisan migrate 跑了 3 个新文件,它们共享同一个 batch = 5;那么 php artisan migrate:rollback --step=1 就会把这 3 个全部执行 down(),一个不留。
常见误判点:
- 看到
php artisan migrate:status列表里有 10 行,以为--step=2就能撤最后两行 —— 实际撤的是最后两个batch值(可能对应 8 行) - 某次
down()报错(如删表前没检查是否存在),整个--step就中断,后续批次不会继续执行 -
batch全是 0?说明迁移没被正式登记,migrate:rollback直接无效 —— 先查config/database.php连接是否指向正确库,再确认migrations表是否可写
想只撤 CreateUsersTable 和 AddStatusToPosts,必须手动调表
Laravel 官方不支持按文件名、类名或时间戳筛选回滚。硬要精准撤某几个,唯一办法是临时篡改 migrations 表里的 batch 字段:
- 先确认这两个迁移的
down()方法安全:用Schema::dropIfExists('users'),别用Schema::drop('users') - 查出它们在
migrations表中的id和当前batch值 - 把这两行的
batch改成一个极大值(比如999) - 运行
php artisan migrate:rollback --step=1—— 它会去找batch = 999的那批并执行 - 回滚完立刻把
batch改回原值,否则下次migrate会跳过或重复执行
这步操作没有自动校验,手抖填错数字或漏改回,后续迁移就乱了。
DB::transaction() 是业务层回滚,和 migrate:rollback 无关
很多人混淆“数据库事务回滚”和“迁移结构回滚”。前者是运行时数据操作的原子性保障,后者是版本控制层面的 schema 变更撤销。
PHP中文网提供Laravel 13.2.0版本下载,Laravel框架 是基于 PHP 8.3+ 的高性能框架,官方推荐通过 Composer 安装。它内置 AI SDK、JSON:API Resources 及原生向量搜索,支持属性驱动开发与队列路由,大幅提升开发效率。相比旧版,13.2.0 优化了缓存 TTL 管理与实时通信,无需 Redis 即可横向扩展。作为现代 Web 开发首选,它兼顾安全与极速体验,助您快速构建企业级应用。
如果你在控制器里做多条写入(比如创建订单 + 扣库存 + 发通知),应该用:
DB::transaction(function () {
Order::create([...]);
Inventory::decrement('stock');
Notification::send(...);
});
—— 异常时自动 ROLLBACK,不影响表结构。
而 php artisan migrate:rollback 不会碰任何业务数据,只调用迁移类的 down() 方法改表结构。两者作用域完全不同,不能互相替代。
生产环境禁止直接跑 migrate:rollback
哪怕你本地测了十遍,生产上仍不该执行任何迁移回滚命令。原因很实在:
-
down()方法如果含Schema::dropTable('orders'),而表里有 200 万行数据,执行过程锁表、超时、OOM 都可能发生 - 迁移历史被修改后,CI/CD 流水线里
migrate的判断逻辑可能失效 - 团队多人协作时,有人 rollback、有人 migrate,
migrations表状态极易不一致
真正稳妥的做法是:生产环境只允许新增迁移(up()),所有结构变更都通过正向迁移解决;历史问题靠新建迁移修复(比如加字段、改默认值、建索引),而不是倒着删。










