Files
asd-backend/docs/MIGRATIONS.md

4.6 KiB
Raw Permalink Blame History

数据库迁移

概述

所有数据库结构变更通过 SQL 迁移脚本管理,存储在 migrations/ 目录,按序号命名。

部署时 deploy.sh 自动检测并执行未运行的迁移:

upload_dir "迁移文件" migrations    → 上传到服务器
run_migrations                       → 逐条执行未迁移的脚本

已执行的迁移记录在数据库 _migrations 表中。

迁移文件清单

序号 文件 操作 说明
001 001_add_payment_fields.sql ALTER TABLE users ADD COLUMN 添加 is_member, is_admin, membership_expires_at 字段
002a 002_add_payment_orders.sql CREATE TABLE 创建 payment_orders
002b 002_add_user_profile_fields.sql ALTER TABLE users ADD COLUMN 添加 avatar_url, nickname 字段
003 003_set_all_users_paid.sql SELECT 1(空操作) 历史遗留:原将所有用户设为付费,已改为空操作
004 004_add_refresh_tokens.sql CREATE TABLE 创建 refresh_tokens 表(双 Token 机制)
005 005_add_web_login_codes.sql CREATE TABLE 创建 web_login_codes 表(网页端扫码登录)
006 006_add_performance_indexes.sql CREATE INDEX 添加性能索引(user_id, date, is_favorite
007 007_add_spot_check_count.sql ALTER TABLE weather_data 添加 spotcheckcount 字段
009 009_add_payment_audit_log.sql CREATE TABLE 创建 payment_audit_log 表(支付审计日志)
010 010_rename_paid_fields.sql ALTER TABLE RENAME COLUMN is_paidis_member, paid_expires_atmembership_expires_at
011 011_add_notifications.sql CREATE TABLE 创建 notifications 表(通知系统)

注意:序号不连续(无 008是因为跳过了一个已撤销的迁移。新迁移请继续使用下一可用序号如 012

迁移说明

003 — 历史遗留

此迁移最初执行了 UPDATE users SET is_paid = true,将所有已有用户设为永久付费会员(用于早期测试)。发现后已改为空操作 SELECT 1 WHERE 1 = 1已有的被修改的数据需要用脚本手动回退

009 — 自动建表

此迁移对应的代码中有幂等 CREATE TABLE IF NOT EXISTS 逻辑,即使未通过迁移系统执行,代码也会自动建表。迁移文件本身保留以确保正式部署时 _migrations 表记录完整。

010 — 字段重命名

is_paidis_member(会员身份凭证,即使过期也保留) paid_expires_atmembership_expires_atNULL 表示永久会员)

如何创建新迁移

# 1. 创建迁移文件
touch migrations/012_your_description.sql

# 2. 写入 SQL
vim migrations/012_your_description.sql

# 3. 部署时自动执行
./deploy.sh production          # 会自动运行新迁移
./deploy.sh development         # 开发环境同理

迁移编写规范

规则 说明
幂等 使用 IF NOT EXISTS / IF EXISTS,可重复执行
事务 关键操作使用 BEGIN / COMMIT
回滚 考虑失败场景,避免不可逆操作
注释 文件头部写清目的、日期、依赖关系

示例:

-- ============================================
-- 迁移: 012_add_example.sql
-- 目的: 创建示例表
-- 日期: 2026-05-26
-- ============================================

CREATE TABLE IF NOT EXISTS example (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    created_at TIMESTAMPTZ DEFAULT NOW()
);

如何手动执行迁移

在服务器上直接运行:

ssh root@1panel-server
docker exec -i 1Panel-postgresql-FtMo psql -U milkydata -d milkydata \
  < /root/rust/rust_backend/migrations/012_your_migration.sql

# 记录到 _migrations 表
docker exec 1Panel-postgresql-FtMo psql -U milkydata -d milkydata \
  -c "INSERT INTO _migrations (name) VALUES ('012_your_migration.sql');"

迁移测试

部署后 test_migration_status 会自动检查:

  • _migrations 表是否存在
  • 已执行的迁移数量
  • 最后一次执行的迁移文件名

当前执行状态

开发库 milkydata_dev

001_add_payment_fields.sql
002_add_payment_orders.sql
002_add_user_profile_fields.sql
003_set_all_users_paid.sql
004_add_refresh_tokens.sql
005_add_web_login_codes.sql
006_add_performance_indexes.sql
007_add_spot_check_count.sql
009_add_payment_audit_log.sql
010_rename_paid_fields.sql

生产库 milkydata

_migrations 表尚未创建。缺失的迁移:

  • 004 (refresh_tokens)
  • 005 (web_login_codes)
  • 009 (payment_audit_log)
  • 011 (notifications)