初始化
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# Database Migration — 迁移模式与示例
|
||||
|
||||
> 主流程见 SKILL.md,本文档为幂等迁移、Expand-Contract、批量迁移、大表策略的完整实现。
|
||||
|
||||
## 幂等迁移
|
||||
|
||||
```php
|
||||
public function up(): void
|
||||
{
|
||||
if (!Schema::hasTable('production_orders')) {
|
||||
Schema::create('production_orders', function (Blueprint $table) {
|
||||
$table->bigIncrements('id');
|
||||
$table->string('order_no', 50)->unique();
|
||||
$table->timestamps();
|
||||
$table->softDeletes();
|
||||
});
|
||||
}
|
||||
if (!Schema::hasColumn('production_orders', 'priority')) {
|
||||
Schema::table('production_orders', function (Blueprint $table) {
|
||||
$table->tinyInteger('priority')->default(0)->after('status');
|
||||
});
|
||||
}
|
||||
if (!$this->hasIndex('production_orders', 'idx_orders_priority')) {
|
||||
Schema::table('production_orders', function (Blueprint $table) {
|
||||
$table->index('priority', 'idx_orders_priority');
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Expand-Contract 三阶段示例(字段重命名 username → display_name)
|
||||
|
||||
Phase 1 EXPAND: 添加 display_name nullable。部署 v2 双写。
|
||||
Phase 2 MIGRATE: 独立迁移文件批量 UPDATE 回填。部署 v3 读新写双。验证一致性。
|
||||
Phase 3 CONTRACT: 删除 username。部署 v4 仅新字段。
|
||||
|
||||
时间线:Day 1 加字段+双写,Day 2 回填,Day 3 读新写双+验证,Day 7 删旧字段。
|
||||
|
||||
## 批量数据迁移模板
|
||||
|
||||
```php
|
||||
$batchSize = 2000;
|
||||
$lastId = 0;
|
||||
while (true) {
|
||||
$affected = Db::update("UPDATE users SET normalized_email = LOWER(email) WHERE id > ? AND normalized_email IS NULL ORDER BY id LIMIT ?", [$lastId, $batchSize]);
|
||||
if ($affected === 0) break;
|
||||
$lastId = Db::selectOne("SELECT MAX(id) AS max_id FROM users WHERE normalized_email IS NOT NULL AND id > ?", [$lastId])->max_id ?? $lastId + $batchSize;
|
||||
usleep(100_000);
|
||||
}
|
||||
```
|
||||
|
||||
规则:1000–5000 行/批、批次间 sleep、游标 WHERE id > ?、低峰期执行。
|
||||
|
||||
## 大表变更策略(百万级+)
|
||||
|
||||
| 操作 | 风险 | 方案 |
|
||||
|------|------|------|
|
||||
| ADD COLUMN | 低 | 直接执行,nullable 或有默认值 |
|
||||
| ADD INDEX | 中 | ALGORITHM=INPLACE, LOCK=NONE |
|
||||
| DROP COLUMN | 高 | 先移除代码→部署→下版本迁移删除 |
|
||||
| ALTER TYPE | 高 | Expand-Contract |
|
||||
| RENAME COLUMN | 高 | Expand-Contract |
|
||||
| DROP TABLE | 极高 | 先重命名→观察一周→删除 |
|
||||
|
||||
## 危险操作清单
|
||||
|
||||
| 操作 | 缓解 |
|
||||
|------|------|
|
||||
| DROP TABLE | 先备份 |
|
||||
| DROP COLUMN | 先移除代码引用 |
|
||||
| ALTER TYPE | Expand-Contract |
|
||||
| TRUNCATE | 禁止生产 |
|
||||
| NOT NULL 无默认值 | 先 nullable→回填→再加约束 |
|
||||
@@ -0,0 +1,57 @@
|
||||
# 数据库回滚模式 (Hyperf Migration)
|
||||
|
||||
## 安全回滚策略
|
||||
|
||||
### 添加字段(可回滚)
|
||||
```php
|
||||
// Migration up()
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->string('avatar_url')->nullable()->after('email');
|
||||
});
|
||||
|
||||
// Migration down()
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('avatar_url');
|
||||
});
|
||||
```
|
||||
|
||||
### 删除字段(不可逆 — 需预备份)
|
||||
```sql
|
||||
-- 删除前先备份
|
||||
CREATE TABLE _backup_users_phone AS
|
||||
SELECT id, phone FROM users WHERE phone IS NOT NULL;
|
||||
```
|
||||
|
||||
### 重命名字段(分步迁移)
|
||||
```php
|
||||
// Step 1: 添加新列
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->string('display_name')->nullable()->after('name');
|
||||
});
|
||||
|
||||
// Step 2: 迁移数据
|
||||
DB::statement('UPDATE users SET display_name = name');
|
||||
|
||||
// Step 3: 删除旧列(下一个迁移文件)
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('name');
|
||||
});
|
||||
```
|
||||
|
||||
### 类型变更(分步迁移)
|
||||
```
|
||||
Step 1: 添加新列 → Step 2: 迁移数据 → Step 3: 删除旧列
|
||||
```
|
||||
|
||||
## 回滚命令
|
||||
|
||||
```bash
|
||||
# 回滚最近一次迁移
|
||||
php bin/hyperf.php migrate:rollback
|
||||
|
||||
# 回滚最近 N 次迁移
|
||||
php bin/hyperf.php migrate:rollback --step=3
|
||||
|
||||
# 查看迁移状态
|
||||
php bin/hyperf.php migrate:status
|
||||
```
|
||||
Reference in New Issue
Block a user