php artisan migrate 默认不会删除任何数据,它仅执行未运行过的迁移文件,新增表、加字段等操作均不触碰已有数据;真正危险的是误用 schema::drop()、手改已提交迁移或在生产环境盲目使用 migrate:reset。

php artisan migrate 默认不会删除任何数据——它只执行尚未运行过的迁移文件,新增表、加字段、建索引等操作均不触碰已有行数据。真正危险的是误用 Schema::drop()、手改已提交迁移、或在生产环境盲目 php artisan migrate:reset。
为什么新迁移不会删数据?
Laravel 迁移本质是「按时间戳顺序执行的脚本队列」,不是结构比对工具。只要你不主动写 Schema::dropIfExists('users') 或 Schema::table('users', ...)->dropColumn('email'),就不可能删表或删列。
-
Schema::create('posts'):只建新表,不影响users表里的一条记录 -
Schema::table('users')中添加字段:$table->string('phone')->nullable()→ 所有旧用户该字段自动为NULL,无数据丢失 -
Schema::rename('old_table', 'new_table'):纯重命名,数据原封不动
修改字段类型必须装 doctrine/dbal
直接写 $table->text('content')->change() 会报错 Class 'Doctrine\DBAL\Types\TextType' not found,因为 Laravel 默认不带这个扩展。
- 先运行
composer require doctrine/dbal(Laravel 10+ 必须显式安装) - 迁移中必须写全变更链:
$table->string('title')->change(),不能只写$table->string('title')(后者会被当成新增字段) - MySQL 8.0.23+ 支持在线 DDL,但 MyISAM 引擎或低版本 MySQL 可能锁表甚至失败,建议在低峰期操作
生产环境迁移前必查三件事
很多“数据丢了”其实是迁移没跑完,或者状态错乱导致后续操作失败。
- 查
migrations表是否干净:SELECT * FROM migrations WHERE migration LIKE '%add_status%';,确认目标迁移未被标记为已执行 - 查目标表是否存在:
SHOW TABLES LIKE 'orders';,避免因手动删表却没清理migrations记录而报Base table or view not found - 查外键依赖顺序:如果
add_order_user_id_foreign迁移排在create_users_table前面,就会失败——时间戳决定执行顺序,别靠文件名直觉判断
回滚失败时别硬删 migrations 表记录
看到 Class CreateOrdersTable does not exist 就去数据库里删 migrations 行?这是最常见也最危险的操作。
- 先运行
composer dump-autoload,解决类找不到问题 - 再试
php artisan migrate:rollback --step=1,让框架自己处理 down() 逻辑 - 如果 rollback 仍失败,说明 down() 里写了非法操作(比如删了还没建的表),应人工检查该迁移文件的
down()方法是否与up()对称
关键点在于:迁移安全不靠“不犯错”,而靠“不绕过机制”。所有变更都走新迁移文件,所有删除都配对 down(),所有字段变更都验证 doctrine/dbal 是否就位——漏掉其中任一环,都可能在某个部署节点上静默损坏数据。











