# 数据库迁移总结 ## 迁移版本:000004_create_personal_customer_relations **执行时间**:2026-01-10 **执行状态**:✅ 成功 **执行耗时**:307ms --- ## 创建的表 ### 1. personal_customer_phone(个人客户手机号绑定表) **用途**:存储个人客户绑定的手机号信息,支持一对多关系 **字段列表**: | 字段名 | 类型 | 说明 | |--------|------|------| | id | INTEGER | 主键ID | | customer_id | INTEGER | 个人客户ID(关联 personal_customer 表) | | phone | VARCHAR(20) | 手机号 | | is_primary | BOOLEAN | 是否主手机号(默认 false) | | verified_at | TIMESTAMP | 验证通过时间 | | status | INTEGER | 状态(0=禁用 1=启用,默认 1) | | created_at | TIMESTAMP | 创建时间 | | updated_at | TIMESTAMP | 更新时间 | | deleted_at | TIMESTAMP | 删除时间(软删除) | **索引**: - ✅ `idx_personal_customer_phone_customer_phone` - 唯一索引 (customer_id, phone) WHERE deleted_at IS NULL - ✅ `idx_personal_customer_phone_phone` - 普通索引 (phone) - ✅ `idx_personal_customer_phone_deleted_at` - 普通索引 (deleted_at) - ✅ `personal_customer_phone_pkey` - 主键索引 (id) --- ### 2. personal_customer_iccid(个人客户ICCID绑定表) **用途**:记录个人客户使用过的 ICCID,支持多对多关系 **字段列表**: | 字段名 | 类型 | 说明 | |--------|------|------| | id | INTEGER | 主键ID | | customer_id | INTEGER | 个人客户ID(关联 personal_customer 表) | | iccid | VARCHAR(20) | ICCID(20位数字) | | bind_at | TIMESTAMP | 绑定时间 | | last_used_at | TIMESTAMP | 最后使用时间 | | status | INTEGER | 状态(0=禁用 1=启用,默认 1) | | created_at | TIMESTAMP | 创建时间 | | updated_at | TIMESTAMP | 更新时间 | | deleted_at | TIMESTAMP | 删除时间(软删除) | **索引**: - ✅ `idx_personal_customer_iccid_customer_iccid` - 唯一索引 (customer_id, iccid) WHERE deleted_at IS NULL - ✅ `idx_personal_customer_iccid_iccid` - 普通索引 (iccid) - ✅ `idx_personal_customer_iccid_deleted_at` - 普通索引 (deleted_at) - ✅ `personal_customer_iccid_pkey` - 主键索引 (id) --- ### 3. personal_customer_device(个人客户设备号绑定表) **用途**:记录个人客户使用过的设备号/IMEI,支持多对多关系(可选) **字段列表**: | 字段名 | 类型 | 说明 | |--------|------|------| | id | INTEGER | 主键ID | | customer_id | INTEGER | 个人客户ID(关联 personal_customer 表) | | device_no | VARCHAR(50) | 设备号/IMEI | | bind_at | TIMESTAMP | 绑定时间 | | last_used_at | TIMESTAMP | 最后使用时间 | | status | INTEGER | 状态(0=禁用 1=启用,默认 1) | | created_at | TIMESTAMP | 创建时间 | | updated_at | TIMESTAMP | 更新时间 | | deleted_at | TIMESTAMP | 删除时间(软删除) | **索引**: - ✅ `idx_personal_customer_device_customer_device` - 唯一索引 (customer_id, device_no) WHERE deleted_at IS NULL - ✅ `idx_personal_customer_device_device_no` - 普通索引 (device_no) - ✅ `idx_personal_customer_device_deleted_at` - 普通索引 (deleted_at) - ✅ `personal_customer_device_pkey` - 主键索引 (id) --- ## 数据库设计原则 ### 核心设计理念 1. **无外键约束**:所有表之间不建立 Foreign Key 约束,提高灵活性和性能 2. **软删除支持**:所有表都包含 `deleted_at` 字段,支持软删除 3. **唯一性保证**:通过唯一索引(带 WHERE deleted_at IS NULL 条件)保证业务唯一性 4. **查询优化**:为常用查询字段创建普通索引 ### 业务模型关系 ``` PersonalCustomer (1) ──< (N) PersonalCustomerPhone PersonalCustomer (N) ──< (M) PersonalCustomerICCID PersonalCustomer (N) ──< (M) PersonalCustomerDevice ``` - **个人客户 ←→ 手机号**:一对多(一个客户可以绑定多个手机号) - **个人客户 ←→ ICCID**:多对多(一个客户可以使用多个 ICCID,一个 ICCID 可以被多个客户使用) - **个人客户 ←→ 设备号**:多对多(一个客户可以使用多个设备,一个设备可以被多个客户使用) --- ## Makefile 命令 为了方便后续的数据库迁移操作,已添加以下 Makefile 命令: ```bash # 执行所有待执行的迁移(升级数据库) make migrate-up # 回滚最后一次迁移(降级数据库) make migrate-down # 查看当前迁移版本 make migrate-version # 创建新的迁移脚本 make migrate-create ``` --- ## 迁移验证 ### 表验证 ```bash ✅ 个人客户相关表列表: - personal_customer_device - personal_customer_iccid - personal_customer_phone ``` ### 索引验证 所有表的索引都已成功创建: - ✅ 主键索引 - ✅ 唯一索引(带软删除过滤) - ✅ 查询优化索引 - ✅ 软删除索引 --- ## 下一步 1. **数据初始化**(可选) - 如需初始化测试数据,可以创建 seed 脚本 2. **业务逻辑实现** - 已完成:Service 层、Handler 层、路由注册 - 待完成:单元测试、集成测试 3. **性能监控** - 监控索引使用情况 - 监控查询性能 - 根据实际使用情况优化索引 --- ## 注意事项 ⚠️ **生产环境部署前的检查清单**: 1. 确认数据库备份已完成 2. 在预发布环境测试迁移脚本 3. 确认索引创建不会影响现有查询性能 4. 准备回滚方案(已提供 .down.sql 脚本) 5. 评估迁移执行时间,选择合适的维护窗口 --- **迁移完成时间**:2026-01-10 **文档版本**:v1.0