laravel 本身不提供部署回滚功能,仅支持数据库迁移回滚(migrate:rollback)和事务内局部回滚(db::rollbackto()),二者作用域与机制完全不同:前者撤回迁移操作,后者在事务中实现部分sql撤销,均非运维级部署回滚。

部署回滚不是 Laravel 自身的功能,而是运维层面的动作;Laravel 项目本身只负责数据库迁移回滚(migrate:rollback)和事务内局部回滚(DB::rollbackTo()),这两者完全不等价,别混用。
数据库迁移回滚:用 php artisan migrate:rollback
这是最常被误称为“部署回滚”的操作,实际只是撤回最近一次 up() 迁移:
- 默认只回滚上一批(即
migrations表里batch值最大的那组) - 加
--step=2可退回两批,加--path指定单个文件回滚(需手动写down()) - 如果
down()方法里写了破坏性操作(如DROP TABLE),且没加IF EXISTS,上线后立刻执行rollback可能报错 - 生产环境务必先备份再跑回滚,
migrate:rollback不做数据备份,删了就真没了
事务内回滚点:用 DB::savepoint() 和 DB::rollbackTo()
这是业务代码里的控制手段,和部署无关,但常被拿来“救急”——比如发版后某接口突然报错,想临时绕过失败步骤继续跑完事务:
-
DB::savepoint()返回一个字符串标识(如"sp_123"),必须保存下来供后续使用 -
DB::rollbackTo($sp)只撤销该点之后的 SQL,之前已执行的 INSERT/UPDATE 仍有效 - 若在
DB::transaction()闭包里用,未捕获的异常仍会触发整个事务回滚,rollbackTo失效 - MySQL 5.6+、PostgreSQL 支持,SQLite 部分版本不支持嵌套保存点,别在 SQLite 生产环境依赖它
真正意义上的部署回滚:靠发布系统或手动切源码
Laravel 本身不提供部署回滚能力,得靠外部机制:
- 用 Git 标签 + 部署脚本:上线前打 tag(如
v2.3.1),出问题时git checkout v2.3.0 && composer install --no-dev - 蓝绿部署或镜像回滚:Docker 环境下直接切回上一个镜像标签,比改代码快得多
- 环境变量开关:关键新功能用
config('feature.new_checkout')控制,出问题只需改 .env 重启 FPM,无需重新部署 - 注意缓存:
php artisan config:clear和php artisan view:clear必须跟在代码切换后执行,否则旧逻辑可能还在内存里
最容易被忽略的是:数据库迁移回滚和代码回滚必须同步。比如你用 Git 回滚了代码到旧版本,但没跑 migrate:rollback,而旧代码又读不到新字段,直接 500。反过来,只跑回滚命令却不切代码,也可能因模型里引用了已删字段而崩溃。











