Files
railwaysystem/docs/development/rbac-r2/06_migration_plan.md
T

5.6 KiB

RailwaySystem 数据库迁移方案设计 (Migration Plan)

  • 设计版本: R.2A Design Freeze
  • 设计日期: 2026-09-15
  • 适用数据库: 国产主库 KingbaseES V009R003C018 (JDBC 依赖 8.6.0, schema: public)
  • 核心目标: 规范 R.2B 阶段所需的数据库变更脚本清单、序号规则、幂等性保障与零风险回滚方案,确保 100% 兼容现有生产业务。

1. 现有正式 Migration 脚本全量排查

在设计新脚本前,已完成对代码库中所有既有 SQL 脚本的编号与职责排查:

1.1 RuoYi-Vue/sql/system/kingbase/ (系统级通用补丁)

  • 001_sys_oper_log_cost_time.sql: 操作日志表新增 cost_time 耗时列 (BIGINT DEFAULT 0)。
  • 002_legacy_analytics_permissions.sql: 学员画像与学习时长按钮权限补齐。
  • 003_report_attendance_action_permissions.sql: 报到确认与课次考勤核心 Action 权限补齐。
  • 最新可用起始编号: 004。

1.2 RuoYi-Vue/sql/train/v2/ (培训业务领域专用)

  • 000_preflight.sql ~ 010_verify.sql (覆盖 V2 架构演进全量表调整与数据过渡)。
  • 红线警示: 007_dicts.sql 严禁在生产或后续环节执行 (DO NOT EXECUTE)。

2. R.2 计划发布的数据库迁移脚本清单 (PROPOSED_MIGRATIONS)

为避免目录混杂,R.2 的 RBAC 迁移脚本统一归入 RuoYi-Vue/sql/system/kingbase/ 序列:

RuoYi-Vue/sql/system/kingbase/
├── 004_rbac_identity_binding.sql           # 物理约束与身份唯一性索引
└── 005_training_roles_permissions.sql      # 角色预置、菜单补全与权限映射

2.1 脚本 1: 004_rbac_identity_binding.sql

  • 执行目标:
    1. 幂等确认 train_teacher 和 train_student 的 user_id BIGINT 列。
    2. 建立针对非空 user_id 的部分唯一索引(Partial Unique Index),保障一个登录账户只能绑定一个业务主体。
    3. 增加注释与完整性元数据。
  • DDL 设计核心内容:
    BEGIN;
    
    -- 1. 确保列存在 (兼容早期分支)
    ALTER TABLE train_teacher ADD COLUMN IF NOT EXISTS user_id BIGINT;
    ALTER TABLE train_student ADD COLUMN IF NOT EXISTS user_id BIGINT;
    
    -- 2. 建立教师账号唯一索引 (无 DROP,安全幂等,忽略已删除 del_flag='2' 与空值)
    CREATE UNIQUE INDEX IF NOT EXISTS uq_train_teacher_user_id
    ON train_teacher(user_id)
    WHERE user_id IS NOT NULL AND del_flag = '0';
    
    -- 3. 建立学员账号唯一索引 (无 DROP,安全幂等)
    CREATE UNIQUE INDEX IF NOT EXISTS uq_train_student_user_id
    ON train_student(user_id)
    WHERE user_id IS NOT NULL AND del_flag = '0';
    
    COMMENT ON COLUMN train_teacher.user_id IS '关联sys_user.user_id (唯一绑定教师登录账号)';
    COMMENT ON COLUMN train_student.user_id IS '关联sys_user.user_id (唯一绑定学员登录账号)';
    
    COMMIT;
    

2.2 脚本 2: 005_training_roles_permissions.sql

  • 执行目标:
    1. 内置 ID Collision Guard:预检 role_id (3,4,5) 与 menu_id (2201..2240),若已被外部其他业务资源占用则显式 ABORT,严禁覆盖外来记录。
    2. 预置 3 个业务角色 (train_admin, train_teacher, train_student) 写入 sys_role。
    3. 补齐 sys_menu 中历史遗漏的基础模块按钮级权限(train:teacher:*, train:student:*, train:course:*, train:plan:*, train:lesson:* 等)。
    4. 将 system:board:* 权限标识收敛对齐为 train:board:*。
    5. 插入 Teacher 工作台菜单与 Student 个人中心菜单节点。
    6. 幂等配置 sys_role_menu 角色菜单权限映射。
  • DML 设计核心内容:
    BEGIN;
    
    -- 0. ID 碰撞守卫 (Collision Guard):检测 role_id 与 menu_id 是否有非预期占用,有则 RAISE EXCEPTION
    DO $$ ... $$;
    
    -- 1. 预置角色 (使用 WHERE NOT EXISTS 确保无重复)
    INSERT INTO sys_role (role_id, role_name, role_key, role_sort, data_scope, menu_check_strictly, dept_check_strictly, status, del_flag, create_by, create_time, remark)
    SELECT 3, '培训管理员', 'train_admin', 3, '1', 1, 1, '0', '0', 'admin', CURRENT_TIMESTAMP, '', NULL, '一期业务全局管理角色'
    WHERE NOT EXISTS (SELECT 1 FROM sys_role WHERE role_id = 3 OR role_key = 'train_admin');
    
    -- 2. 补齐基础管理模块按钮权限 (示例:教师管理按钮)
    -- 采用 WHERE NOT EXISTS 确保多次执行安全幂等
    -- ... (录入 train:teacher:list/add/edit/query 等节点)
    
    -- 3. 统一规范电子班牌命名空间
    UPDATE sys_menu SET perms = REPLACE(perms, 'system:board:', 'train:board:') 
    WHERE perms LIKE 'system:board:%';
    
    -- 4. 建立角色与菜单权限关联 (sys_role_menu)
    -- train_admin: 分配全部培训业务管理菜单及按钮
    -- train_teacher: 分配教师工作台与专属自服务权限
    -- train_student: 分配学员培训中心与专属自服务权限
    
    COMMIT;
    

3. 生产兼容性与无损回滚设计 (Rollback Safety)

  1. 绝对向前兼容 (Zero Breaking Change):
    • 现有超级管理员 admin (role_id=1) 依靠 *:*:* 拥有全量通配权限,新增角色与菜单对已有超管管理流程无任何不良影响。
    • 所有已有历史数据中 train_teacher.user_id 和 train_student.user_id 为 NULL 的记录完全保留,部分唯一索引不校验 NULL,历史数据不会产生约束冲突。
  2. 零 DDL 锁表风险:
    • KingbaseES / PostgreSQL 架构中,ADD COLUMN IF NOT EXISTS 与 CREATE INDEX ... WHERE ... 操作毫秒级完成,不锁死数据读写。
  3. 独立可执行与验证:
    • 脚本必须具备单向独立执行性,并在脚本末尾集成 DO $$ ... RAISE NOTICE ... $$; 自检核验块。