diff --git a/docs/database-v2/00_readme.md b/docs/database-v2/00_readme.md
new file mode 100644
index 000000000..ce1e6f0c1
--- /dev/null
+++ b/docs/database-v2/00_readme.md
@@ -0,0 +1,78 @@
+# RailwaySystem 数据库 V2 DDL 生成与设计审查概览 (Round 2 最终静态收尾版)
+
+> **设计状态**:数据库 V2 物理 DDL 最终静态收尾就绪(已完成 Round 2 全部 7 项缺陷修复,达到“允许进入测试迁移”标准)
+> **最高依据**:[`RailwaySystem 数据库 V2 字段设计与 Kingbase DDL 规范 V1.0.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/doc/RailwaySystem%20数据库%20V2%20字段设计与%20Kingbase%20DDL%20规范%20V1.0.md)
+> **业务背景参考**:[`RailwaySystem 智慧培训系统一期 PRD V1.0.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/doc/RailwaySystem%20智慧培训系统一期%20PRD%20V1.0.md)
+> **技术基线**:`main@4b450f46`,KingbaseES V009R003C018 (`database=training`, `schema=public`, `database_mode=mysql`)
+> **操作定位**:**纯静态收尾与审查阶段**(严禁执行 SQL、严禁修改真实库、严禁改动业务代码、严禁自动 git commit)。
+
+---
+
+## 1. 阶段目标与执行边界
+
+本阶段严格依据技术负责人 Final Static Review 指示,修复 DDL 中剩余的 7 个问题(R2-01 ~ R2-07),使数据库 V2 DDL 达到“允许进入测试迁移”的标准。
+
+### 核心执行边界
+- [x] **21 张核心业务表模型冻结**:8 新增 + 13 保留/重构 + 淘汰 `train_score_info` + 严禁 `train_dorm_bed`;
+- [x] **删除业务选择型默认值**:核验结果、考勤方式、场地类型、住宿需求、来源类型等必须由应用层明确提供;
+- [x] **解耦两个同名 `source_type`**:区分学员主档进入来源与名单进入来源;
+- [x] **删除正式迁移对象的 `IF NOT EXISTS`**:避免因已有错误对象导致 DDL 静默跳过;
+- [x] **建立 DDL 事务能力探针 (Gate A)**:实证验证实例是否支持 DDL 回滚;
+- [x] **骨架校验升级**:Preflight (Gate B) 采用集合比对,Verify 采用定义级深度验收;
+- [x] **架构决策冻结**:固化排课/住宿并发控制与跨班一致性 Service 校验边界;
+- [x] **绝对零写操作与零代码污染**:未向数据库执行写操作,未修改 Java/Vue 代码,未执行 git commit。
+
+---
+
+## 2. 成果物资产全景清单
+
+### 2.1 物理 SQL 脚本清单 (`RuoYi-Vue/sql/train/v2/`)
+
+| 序号 / 关卡 | 脚本文件 | 事务边界 | 核心职责 |
+| :---: | :--- | :---: | :--- |
+| **Gate A** | [`000_tx_capability_probe.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/000_tx_capability_probe.sql) | 探针显式事务 | **执行前能力探针**:测试 DDL 事务回滚能力,若表残留强行阻断 |
+| **Gate B** | [`000_preflight.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/000_preflight.sql) | 纯只读骨架断言 | **Phase 0.5 骨架强校验**:集合差集校验 14 PK + 24 FK + 7 UNIQUE + 6 Identity + 9 Triggers |
+| **Stage 1** | [`001_backup_current_schema.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/001_backup_current_schema.sql) | `BEGIN ... COMMIT` | 备份当前 14 张表数据快照;增加防覆盖强校验,禁止 DROP CASCADE |
+| **Stage 2** | [`002_create_new_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql) | `BEGIN ... COMMIT` | 创建 8 张 V2 新表(无 `IF NOT EXISTS`,住宿默认0预分配,无业务默认值) |
+| **Stage 3** | [`003_alter_master_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/003_alter_master_tables.sql) | `BEGIN ... COMMIT` | 卸载旧触发器与外键,调整 8 张主表(严格 `ADD COLUMN`,加容量 CHECK) |
+| **Stage 4** | [`004_rebuild_business_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/004_rebuild_business_tables.sql) | `BEGIN ... COMMIT` | 校验 0 行后重构 5 张表(删除 `verify_result`/`checkin_way` 业务默认值) |
+| **Stage 5** | [`005_constraints.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/005_constraints.sql) | `BEGIN ... COMMIT` | 集中定义 13 组 UNIQUE、26 组 `ON DELETE NO ACTION` 外键与 9 条单行 CHECK |
+| **Stage 6** | [`006_indexes.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/006_indexes.sql) | `BEGIN ... COMMIT` | 建立外键索引、排课复合冲突索引与双非空过滤的部分唯一索引(无 `IF NOT EXISTS`) |
+| **-** | [`007_dicts.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/007_dicts.sql) | - | 声明 16 组业务字典注册脚本(**本结构迁移阶段跳过不执行**,留待权限阶段) |
+| **Stage 7** | [`008_migrate_teacher.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/008_migrate_teacher.sql) | `BEGIN ... COMMIT` | 平滑迁移 1 条教师真实数据,校验完整后固化 `status`/`del_flag` 为 NOT NULL 并删除旧列 |
+| **Stage 8** | [`009_drop_legacy_score.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/009_drop_legacy_score.sql) | `BEGIN ... COMMIT` | 前置 0 行强阻断校验后,显式解绑旧约束,常规 DROP 淘汰旧表 `train_score_info` |
+| **Stage 9** | [`010_verify.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/010_verify.sql) | 纯只读深度断言 | **“定义级深度验收”** 全量自动化强断言(逐表、列列表、外键删除规则、CHECK定义、默认值) |
+
+### 2.2 应急回滚资产清单 (`RuoYi-Vue/sql/train/v2/rollback/`)
+
+| 序号 | 回滚文件 | 核心职责 |
+| :---: | :--- | :--- |
+| **0** | [`000_phase05_exact_schema.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/rollback/000_phase05_exact_schema.sql) | **Phase 0.5 真实物理基线 DDL**(14表字段、PK、24个FK、7组UNIQUE、9个触发器) |
+| **1** | [`001_rollback_new_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/rollback/001_rollback_new_tables.sql) | 显式解除外键依赖,按拓扑反序常规 DROP 8 张 V2 新增表(`BEGIN ... COMMIT`) |
+| **2** | [`002_rollback_modified_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/rollback/002_rollback_modified_tables.sql) | 基于 `000_phase05_exact_schema.sql` 精确结构重建 13 张表,灌回 `bak_v1_*` 数据并核验教师行数 |
+| **3** | [`003_restore_legacy_score.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/rollback/003_restore_legacy_score.sql) | 基于精确 DDL 重建历史 `train_score_info` 表及 3 个外键与唯一约束 |
+| **4** | [`README.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/rollback/README.md) | 应急回滚指南(解耦结构与数据,明确依赖 `000` 结构与 `bak_v1_*` 数据的执行规范) |
+
+### 2.3 架构与设计审查技术文档 (`docs/database-v2/`)
+
+| 序号 | 文档名称 | 主要内容 |
+| :---: | :--- | :--- |
+| **1** | [`00_readme.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/00_readme.md) | 本阶段全景综述、规范基线与资产索引导航 |
+| **2** | [`01_table_inventory.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/01_table_inventory.md) | 21 张正式业务表清单、新旧对比、三大核心 ID 落地映射、字段默认值修正 |
+| **3** | [`02_migration_plan.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/02_migration_plan.md) | 迁移执行流水线、双门禁 (Gate A/B) 准入机制、单文件显式事务边界与断点恢复 |
+| **4** | [`03_constraint_index_review.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/03_constraint_index_review.md) | PK、26 组 NO ACTION 外键、13 组 UNIQUE、9 条 CHECK 与复合索引全面审查 |
+| **5** | [`04_risk_review.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/04_risk_review.md) | **R-01 至 R-17** 全景风险深度剖析(固化架构决策 A/B,解耦双 source_type) |
+| **6** | [`05_execution_contract.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/05_execution_contract.md) | **执行契约**(Gate A 事务探针 + Gate B 精确骨架 + 显式事务与即刻熔断) |
+| **7** | [`06_review_round1_changes.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/06_review_round1_changes.md) | **Round 1 修订闭环记录表**(17 项评审意见落实明细) |
+| **8** | [`07_review_round2_changes.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/07_review_round2_changes.md) | **Round 2 修订闭环记录表**(R2-01 ~ R2-07 最终静态收尾明细) |
+
+---
+
+## 3. 人工 Review 准入与优先建议
+
+建议高级技术负责人优先 Review 以下关键文件:
+1. **优先审查 Round 2 修订记录表**:[`docs/database-v2/07_review_round2_changes.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/07_review_round2_changes.md)(核验 R2-01 ~ R2-07 修复明细);
+2. **优先审查执行契约与探针**:[`docs/database-v2/05_execution_contract.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/05_execution_contract.md) 与 [`RuoYi-Vue/sql/train/v2/000_tx_capability_probe.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/000_tx_capability_probe.sql)(核验 Gate A 事务原子性实证机制);
+3. **优先审查 Preflight 骨架校验**:[`RuoYi-Vue/sql/train/v2/000_preflight.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/000_preflight.sql)(核验集合比对 14 PK + 24 FK + 7 UNIQUE + 6 Identity + 9 Triggers);
+4. **优先审查 Verify 定义级验收**:[`RuoYi-Vue/sql/train/v2/010_verify.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/010_verify.sql)(核验定义级断言、CHECK 逻辑与默认值强断言);
+5. **优先审查核心建表与重构脚本**:[`002_create_new_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql) 与 [`004_rebuild_business_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/004_rebuild_business_tables.sql)(核验无 `IF NOT EXISTS`、无业务默认值及住宿状态 0)。
diff --git a/docs/database-v2/01_table_inventory.md b/docs/database-v2/01_table_inventory.md
new file mode 100644
index 000000000..1121375da
--- /dev/null
+++ b/docs/database-v2/01_table_inventory.md
@@ -0,0 +1,199 @@
+# RailwaySystem 数据库 V2 表结构清单与模型比对 (Round 1 修订版)
+
+> **技术依据**:[`RailwaySystem 数据库 V2 字段设计与 Kingbase DDL 规范 V1.0.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/doc/RailwaySystem%20数据库%20V2%20字段设计与%20Kingbase%20DDL%20规范%20V1.0.md)
+> **状态**:一期 21 张培训业务表全覆盖冻结清单(已完成 Round 1 字段与约束精确审查修订)。
+
+---
+
+## 1. 21 张正式表全景分类
+
+```mermaid
+mindmap
+ root((RailwaySystem V2 业务表))
+ 基础资料表 (9张)
+ train_teacher (教师主档)
+ train_student (学员长期主档)
+ train_course (课程基础主档)
+ train_resource (新增: 统一教学资源)
+ train_course_resource (新增: 课程资源关联)
+ train_classroom_info (教室信息)
+ train_training_site (实训场地)
+ train_electronic_board (电子班牌设备)
+ train_dormitory_info (宿舍房间)
+ 培训组织表 (4张)
+ train_class_plan (培训班主档)
+ train_plan_course (新增: 培训班课程实例)
+ train_enrollment (新增: 学员参训档案)
+ train_lesson (新增: 教学活动课次)
+ 培训执行表 (4张)
+ train_accommodation (新增: 学员住宿安排)
+ train_dorm_auth (门禁授权同步)
+ train_class_report (现场报到记录)
+ train_student_checkin (课次考勤打卡)
+ 培训结果表 (4张)
+ train_score_item (新增: 考核成绩项配置)
+ train_student_score (新增: 学员单项成绩明细)
+ train_study_duration (自主学习时长记录)
+ train_student_portrait (学员全期画像评估)
+ 淘汰表 (1张)
+ train_score_info (彻底下线)
+```
+
+---
+
+## 2. 三大核心 ID 架构映射
+
+V2 架构通过三个领域核心 ID 彻底取代旧模型中跨多表重复冗余的复合外键串(`student_id + plan_id + c_id + lesson_time`):
+
+| 核心 ID 标识 | 业务实体表 | 业务语义 | 衍生与引用的业务表 |
+| :--- | :--- | :--- | :--- |
+| **`enrollment_id`** | [`train_enrollment`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql#L72) | **某学员参加某一期培训班的参训全生命周期档案** | `train_accommodation`
`train_class_report`
`train_student_checkin`
`train_student_score`
`train_study_duration`
`train_student_portrait` |
+| **`plan_course_id`** | [`train_plan_course`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql#L52) | **某一期培训班中包含的某一门具体课程实例** | `train_lesson`
`train_score_item`
`train_study_duration` |
+| **`lesson_id`** | [`train_lesson`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql#L106) | **本期某门课程中的具体一次教学活动(课表课次)** | `train_student_checkin` |
+
+---
+
+## 3. 21 张正式表详细结构与新旧比对 (含 Round 1 修订)
+
+### 3.1 基础资料模块 (9 张)
+
+#### 1. `train_teacher` (保留并结构升级)
+- **主键**:`t_id` (varchar(32))
+- **数据保留**:保留当前生产环境唯一 1 行数据。
+- **字段变更**:
+ - 新增:`user_id` (bigint), `org_name` (varchar(100)), `job_title` (varchar(50)), `status` (smallint NOT NULL), `create_by` (varchar(64)), `update_by` (varchar(64)), `del_flag` (char(1) NOT NULL);
+ - 调整列宽:`t_name` varchar(50), `t_email` varchar(100), `remark` varchar(500);
+ - 数据迁移:由 `008_migrate_teacher.sql` 将 `t_department` -> `org_name`, `t_title` -> `job_title`, `create_user` -> `create_by`,并在校验后将 `status` 与 `del_flag` 固化为 `NOT NULL`;
+ - 淘汰删除:`t_department`, `t_title`, `create_user`。
+
+#### 2. `train_student` (保留并重构为企业培训主档)
+- **主键**:`s_id` (varchar(32))
+- **字段变更**:
+ - 彻底淘汰高校概念旧列:删除 `s_department`, `s_major`, `s_class`, `create_user`;
+ - 新增:`user_id` (bigint), `org_name` (varchar(100)), `s_email` (varchar(100)), `id_card_ciphertext` (text, 密文), `id_card_hash` (varchar(128), 精确防重哈希), `id_card_last4` (varchar(4), 脱敏展示), `face_ref` (varchar(255), 人脸凭据), `source_type` (smallint NOT NULL, 1管理员录入/2Excel导入/3平台同步), `status` (smallint NOT NULL), `create_by`, `update_by`, `del_flag`;
+ - 约束:`UNIQUE(id_card_hash)` (允许为 NULL)。
+
+#### 3. `train_course` (保留并解耦资源附件)
+- **主键**:`c_id` (varchar(32))
+- **字段变更**:
+ - 彻底淘汰集中附件旧列:删除 `attach_doc`, `attach_video`, `attach_model_link`, `model_resource_ids`, `create_user`;
+ - 新增:`c_code` (varchar(50), 统一编码), `status` (smallint NOT NULL), `create_by`, `update_by`, `del_flag`;
+ - 约束:`UNIQUE(c_code)`。
+
+#### 4. `train_resource` (V2 全新建表)
+- **主键**:`resource_id` (varchar(32))
+- **字段**:`resource_id`, `resource_name`, `resource_type` (1文档/2视频/3 3D模型/4 VR资源/5外部链接/6其他), `resource_url`, `description`, `status`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`, `del_flag`。
+
+#### 5. `train_course_resource` (V2 全新建表)
+- **主键**:`id` (bigint identity)
+- **字段**:`id`, `c_id`, `resource_id`, `sort_no`, `create_by`, `create_time`。
+- **约束**:`UNIQUE(c_id, resource_id)`, 外键指向 `train_course` 与 `train_resource`。
+
+#### 6. `train_classroom_info` (保留并补齐审计)
+- **主键**:`class_room_id` (varchar(32))
+- **字段变更**:删除 `create_user`;补齐 `create_by`, `update_by`, `del_flag`;设置 `room_status` NOT NULL。
+
+#### 7. `train_training_site` (保留并补齐审计)
+- **主键**:`site_id` (varchar(32))
+- **字段变更**:删除 `create_user`;补齐 `create_by`, `update_by`, `del_flag`;设置 `site_status` NOT NULL。
+
+#### 8. `train_electronic_board` (保留并升级交互架构)
+- **主键**:`board_id` (varchar(32))
+- **字段变更**:
+ - 解绑旧关系:删除 `bind_plan_id`, `board_content`, `board_playmode`, `create_user`;
+ - 新增:`board_name` (varchar(100) NOT NULL, 必填无默认空串), `api_endpoint` (varchar(255)), `create_by`, `update_by`, `del_flag`;
+ - 约束:`UNIQUE(board_sn)`。
+
+#### 9. `train_dormitory_info` (保留并优化房态模型)
+- **主键**:`dorm_id` (varchar(32))
+- **字段变更**:
+ - 移除旧计数列:删除 `bed_total`, `bed_used`;
+ - 新增:`dorm_floor` (varchar(20) NOT NULL, 无猜测默认值), `capacity` (integer NOT NULL, 无猜测默认值), `gender_type` (smallint, 0不限/1男/2女), `create_by`, `update_by`, `del_flag`;
+ - 约束:`UNIQUE(dorm_building, dorm_room)`, `CHECK (capacity > 0)`。
+ - **特别声明**:严禁增加 `train_dorm_bed` 表。
+
+---
+
+### 3.2 培训组织模块 (4 张)
+
+#### 10. `train_class_plan` (保留并重构为一班多课)
+- **主键**:`plan_id` (varchar(32))
+- **字段变更**:删除旧单课 `c_id` 与旧教师 `t_id` 及 `create_user`;新增 `report_deadline`, `create_by`, `update_by`, `del_flag`。
+
+#### 11. `train_plan_course` (V2 全新建表)
+- **主键**:`plan_course_id` (bigint identity)
+- **字段**:`plan_course_id`, `plan_id`, `c_id`, `sort_no`, `create_by`, `create_time`, `remark`。
+- **约束**:`UNIQUE(plan_id, c_id)`。
+
+#### 12. `train_enrollment` (V2 全新建表 - 系统最核心关系)
+- **主键**:`enrollment_id` (bigint identity)
+- **字段**:`enrollment_id`, `plan_id`, `student_id`, `source_type` (smallint NOT NULL, 参训名单来源,由 train_enrollment_source 字典定义,无默认值), `enrollment_status` (DEFAULT 0 待报到), `accommodation_required` (smallint NOT NULL, 无默认值), `join_time`, `complete_time`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`。
+- **约束**:`UNIQUE(plan_id, student_id)`。
+- **注意**:此处 `source_type` 表示学员进入本期培训班名单的来源,与 `train_student.source_type`(长期人员主档来源)语义完全不同,严禁混用。
+
+#### 13. `train_lesson` (V2 全新建表)
+- **主键**:`lesson_id` (bigint identity)
+- **字段**:`lesson_id`, `plan_course_id`, `t_id` (varchar(32) NOT NULL, 课次必要组成), `start_time`, `end_time`, `venue_type` (smallint NOT NULL, 1普通教室/2实训场地,无默认值), `class_room_id`, `site_id`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`。
+- **约束**:
+ - `CHECK (start_time < end_time)`;
+ - `CHECK ((venue_type = 1 AND class_room_id IS NOT NULL AND site_id IS NULL) OR (venue_type = 2 AND site_id IS NOT NULL AND class_room_id IS NULL))` (场地单行互斥)。
+
+---
+
+### 3.3 培训执行模块 (4 张)
+
+#### 14. `train_accommodation` (V2 全新建表)
+- **主键**:`accommodation_id` (bigint identity)
+- **字段**:`accommodation_id`, `enrollment_id`, `dorm_id`, `bed_no`, `assigned_time`, `accommodation_status` (smallint NOT NULL DEFAULT 0, 0预分配/1已入住/2已退宿), `create_by`, `create_time`, `update_by`, `update_time`, `remark`。
+- **约束**:`UNIQUE(enrollment_id)`。
+
+#### 15. `train_dorm_auth` (重构重建)
+- **主键**:`auth_id` (bigint identity)
+- **字段**:`auth_id`, `accommodation_id`, `auth_start`, `auth_end`, `face_sync_status` (DEFAULT 0 待下发), `retry_count` (DEFAULT 0), `last_error`, `external_auth_id`, `last_sync_time`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`。
+- **约束**:`UNIQUE(accommodation_id)`。
+
+#### 16. `train_class_report` (重构重建)
+- **主键**:`report_id` (bigint identity)
+- **字段**:`report_id`, `enrollment_id`, `report_way` (smallint NOT NULL), `report_device_sn`, `report_time`, `verify_result` (smallint NOT NULL, 1通过/2不匹配/3人工放行,无默认值), `verify_note`, `create_by`, `create_time`, `remark`。
+- **约束**:`UNIQUE(enrollment_id)`。
+
+#### 17. `train_student_checkin` (重构重建)
+- **主键**:`checkin_id` (bigint identity)
+- **字段**:`checkin_id`, `enrollment_id`, `lesson_id`, `board_id`, `checkin_way` (smallint NOT NULL, 1人脸/2刷卡/3扫码/4代签,无默认值), `sign_in_time`, `sign_out_time`, `attendance_status` (DEFAULT 0 缺勤), `manual_flag` (DEFAULT 0 自动), `create_by`, `create_time`, `update_by`, `update_time`, `remark`。
+- **约束**:`UNIQUE(enrollment_id, lesson_id)`。
+
+---
+
+### 3.4 培训结果模块 (4 张)
+
+#### 18. `train_score_item` (V2 全新建表)
+- **主键**:`score_item_id` (bigint identity)
+- **字段**:`score_item_id`, `plan_id`, `plan_course_id`, `item_name`, `item_type`, `weight`, `full_score`, `sort_no`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`。
+- **约束**:`CHECK (weight >= 0.00 AND weight <= 100.00)`, `CHECK (full_score > 0.00)`。
+
+#### 19. `train_student_score` (V2 全新建表)
+- **主键**:`score_id` (bigint identity)
+- **字段**:`score_id`, `enrollment_id`, `score_item_id`, `score` (numeric(7,2) NOT NULL, 无默认0), `source_type`, `source_system`, `source_event_id`, `import_time`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`。
+- **约束**:`UNIQUE(enrollment_id, score_item_id)`, `CHECK (score >= 0.00)`。
+
+#### 20. `train_study_duration` (重构重建)
+- **主键**:`dur_id` (bigint identity)
+- **字段**:`dur_id`, `enrollment_id`, `plan_course_id`, `resource_id`, `learning_content`, `source_system`, `source_event_id`, `start_time`, `end_time`, `study_seconds`, `sync_time`, `create_by`, `create_time`, `remark`。
+- **约束**:
+ - `CHECK (study_seconds >= 0)`;
+ - `CHECK (end_time IS NULL OR start_time IS NULL OR end_time >= start_time)`;
+ - `CHECK (source_event_id IS NULL OR source_system IS NOT NULL)`;
+ - 双非空部分唯一索引:`UNIQUE(source_system, source_event_id) WHERE source_system IS NOT NULL AND source_event_id IS NOT NULL`。
+
+#### 21. `train_student_portrait` (重构重建)
+- **主键**:`portrait_id` (bigint identity)
+- **字段**:`portrait_id`, `enrollment_id`, `attendance_rate`, `theory_score`, `practical_score`, `total_study_hour`, `label_tag`, `portrait_content`, `generated_time`, `create_by`, `create_time`, `update_by`, `update_time`, `remark`。
+- **约束**:`UNIQUE(enrollment_id)`。
+
+---
+
+## 4. 淘汰旧表说明
+
+### `train_score_info`
+- **处理方式**:彻底下线并从 public 生产 schema 中 DROP;
+- **现状保障**:实测当前行数精确为 0,无任何真实数据迁移风险。
diff --git a/docs/database-v2/02_migration_plan.md b/docs/database-v2/02_migration_plan.md
new file mode 100644
index 000000000..dc6238af5
--- /dev/null
+++ b/docs/database-v2/02_migration_plan.md
@@ -0,0 +1,84 @@
+# RailwaySystem 数据库 V2 迁移执行计划 (Round 1 修订版)
+
+> **执行基线**:KingbaseES V009R003C018 (`schema=public`)
+> **设计依据**:[`RailwaySystem 数据库 V2 字段设计与 Kingbase DDL 规范 V1.0.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/doc/RailwaySystem%20数据库%20V2%20字段设计与%20Kingbase%20DDL%20规范%20V1.0.md) 及 Round 1 审查要求
+> **前置条件**:当前正式库中 `train_teacher` 精确包含 1 行数据,其余 13 张现有表均为 0 行。
+
+---
+
+## 1. 迁移执行总体流水线 (含 Preflight 与单文件事务)
+
+整个迁移任务划分为 6 个严格阶段,每个主脚本均自包含显式 `BEGIN ... COMMIT` 事务边界:
+
+```mermaid
+flowchart TD
+ S0[Stage 0: 000 只读基线预检 Preflight] -->|核验通过| S1[Stage 1: 001 数据快照与结构备份]
+ S1 -->|防覆盖校验通过| S2[Stage 2: 物理结构准备]
+ subgraph Stage 2: 物理结构准备 (各脚本独立事务)
+ S2_1[002_create_new_tables.sql] --> S2_2[003_alter_master_tables.sql]
+ S2_2 --> S2_3[004_rebuild_business_tables.sql]
+ end
+ S2 --> S3[Stage 3: 完整性约束与索引注入]
+ subgraph Stage 3: 完整性建立 (各脚本独立事务)
+ S3_1[005_constraints.sql] --> S3_2[006_indexes.sql]
+ end
+ S3 --> S4[Stage 4: 数据平滑迁移与旧表淘汰]
+ subgraph Stage 4: 数据平滑处理 (各脚本独立事务)
+ S4_1[008_migrate_teacher.sql] --> S4_2[009_drop_legacy_score.sql]
+ end
+ S4 --> S5[Stage 5: 010 全面自动化强断言验收]
+ S5 -->|验收全部 PASS| DONE((迁移阶段成功闭环))
+ S5 -.->|任何断言 FAIL| ROLLBACK[触发 rollback 逆向流水线]
+```
+
+---
+
+## 2. 阶段明细与操作规范
+
+### Stage 0: 只读基线预检 Preflight
+- **执行脚本**:[`000_preflight.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/000_preflight.sql)
+- **目标**:纯只读排查当前环境确实精确处于 Phase 0.5 初始状态。
+- **核验准则**:
+ - 14 张旧表全部存在,8 张 V2 新表均不存在;
+ - `train_teacher` 精确为 1 行,其余 13 张旧表精确为 0 行;
+ - 旧外键 `fk_classplan_course`、旧唯一约束及 9 个旧触发器全部完备。
+- **阻断控制**:任何一项不符合,立即抛出异常中止,拒绝进入未知环境。
+
+### Stage 1: 数据快照备份
+- **执行脚本**:[`001_backup_current_schema.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/001_backup_current_schema.sql)
+- **目标**:在显式事务中为当前 14 张培训旧表建立物理快照(`bak_v1_*`)。
+- **防覆盖控制**:若检测到既有 `bak_v1_*` 已存在,立即抛出异常强阻断,杜绝二次执行覆盖最初 V1 备份。
+
+### Stage 2: 物理结构准备
+- **执行脚本**:
+ 1. [`002_create_new_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql):新建 8 张 V2 表(`t_id` 必填,场地互斥 CHECK,分数非负 CHECK);
+ 2. [`003_alter_master_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/003_alter_master_tables.sql):卸载主数据旧触发器,显式解除旧外键,调整 8 张主数据表结构(移除猜测默认值,加 `capacity > 0` CHECK);
+ 3. [`004_rebuild_business_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/004_rebuild_business_tables.sql):校验 0 行后,显式解绑旧外键并常规 DROP,按照 `enrollment_id` / `lesson_id` 重建 5 张业务表(增加学时时间与单号系统匹配 CHECK)。
+
+### Stage 3: 完整性约束与索引注入
+- **执行脚本**:
+ 1. [`005_constraints.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/005_constraints.sql):集中为 21 张表建立 13 组 UNIQUE 约束、26 组 `ON DELETE NO ACTION` 外键与全量单行 CHECK 约束;
+ 2. [`006_indexes.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/006_indexes.sql):创建外键索引、排课多维复合冲突索引及双非空部分唯一索引。
+
+### Stage 4: 数据平滑迁移与旧表淘汰
+- **执行脚本**:
+ 1. [`008_migrate_teacher.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/008_migrate_teacher.sql):将教师历史数据映射至新列,校验数据完整性后将 `status` 与 `del_flag` 固化为 NOT NULL,安全删除旧列;
+ 2. [`009_drop_legacy_score.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/009_drop_legacy_score.sql):前置 0 行校验后,显式解除历史约束并安全常规 DROP。
+
+### Stage 5: 全面自动化强断言验收
+- **执行脚本**:[`010_verify.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/010_verify.sql)
+- **目标**:实现“失败即失败”,逐表逐项强断言,出现任何偏差直接抛异常报错。
+
+---
+
+## 3. 业务字典脚本定位特别说明
+
+[`007_dicts.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/007_dicts.sql) **在当前数据库结构迁移阶段明确跳过、不执行**。
+原因:该脚本向 `sys_dict_*` 系统表写入业务字典数据,属于 API 契约与权限设计范畴。当前阶段保持数据库结构与应用层配置解耦,待后续权限设计阶段统一执行。
+
+---
+
+## 4. 断点恢复与精确回滚机制
+
+- **单脚本失败自动撤销**:由于各脚本包含显式 `BEGIN ... COMMIT`,单脚本内部任何错误会自动触发事务 ROLLBACK,数据库保持在上一个脚本执行成功的整齐状态;
+- **精确全量回滚保障**:若需全量还原,严格基于 [`rollback/000_phase05_exact_schema.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/rollback/000_phase05_exact_schema.sql) 的真实物理 DDL 重建结构,结合 `bak_v1_*` 快照灌回数据,彻底消除 CTAS 丢失结构缺陷。
diff --git a/docs/database-v2/03_constraint_index_review.md b/docs/database-v2/03_constraint_index_review.md
new file mode 100644
index 000000000..64e18576c
--- /dev/null
+++ b/docs/database-v2/03_constraint_index_review.md
@@ -0,0 +1,126 @@
+# RailwaySystem 数据库 V2 约束与索引技术审查报告 (Round 1 修订版)
+
+> **审查依据**:[`RailwaySystem 数据库 V2 字段设计与 Kingbase DDL 规范 V1.0.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/doc/RailwaySystem%20数据库%20V2%20字段设计与%20Kingbase%20DDL%20规范%20V1.0.md) 及 Round 1 审查要求
+> **审查对象**:[`005_constraints.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/005_constraints.sql) 与 [`006_indexes.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/006_indexes.sql)
+
+---
+
+## 1. 主键(PRIMARY KEY)审查
+
+V2 模型包含 21 张正式业务表,主键设计清晰划分为两类:
+
+### 1.1 业务编码主键 (8 张基础表,varchar(32))
+- 适用表:`train_teacher` (t_id), `train_student` (s_id), `train_course` (c_id), `train_resource` (resource_id), `train_classroom_info` (class_room_id), `train_training_site` (site_id), `train_electronic_board` (board_id), `train_dormitory_info` (dorm_id), `train_class_plan` (plan_id)。
+- **审查结论**:保持既有若依与业务系统自定义编码惯例,支持业务前缀与分布式生成;在 Kingbase 中具备唯一 B-Tree 聚集索引。
+
+### 1.2 数字自增主键 (13 张关系/过程表,bigint identity)
+- 适用表:`train_course_resource` (id), `train_plan_course` (plan_course_id), `train_enrollment` (enrollment_id), `train_lesson` (lesson_id), `train_accommodation` (accommodation_id), `train_dorm_auth` (auth_id), `train_class_report` (report_id), `train_student_checkin` (checkin_id), `train_score_item` (score_item_id), `train_student_score` (score_id), `train_study_duration` (dur_id), `train_student_portrait` (portrait_id)。
+- **语法形式**:`BIGINT GENERATED BY DEFAULT AS IDENTITY`。
+- **审查结论**:严格杜绝 MySQL 方言 `AUTO_INCREMENT`,在 KingbaseES 下生成标准序列并被 JDBC 驱动识别。
+
+---
+
+## 2. 外键约束(FOREIGN KEY)审查
+
+### 2.1 26 组业务外键全量拓扑
+
+```text
+train_course_resource (c_id) -> train_course (c_id)
+train_course_resource (resource_id) -> train_resource (resource_id)
+
+train_electronic_board (bind_classroom_id) -> train_classroom_info (class_room_id)
+
+train_plan_course (plan_id) -> train_class_plan (plan_id)
+train_plan_course (c_id) -> train_course (c_id)
+
+train_enrollment (plan_id) -> train_class_plan (plan_id)
+train_enrollment (student_id) -> train_student (s_id)
+
+train_lesson (plan_course_id) -> train_plan_course (plan_course_id)
+train_lesson (t_id) -> train_teacher (t_id)
+train_lesson (class_room_id) -> train_classroom_info (class_room_id)
+train_lesson (site_id) -> train_training_site (site_id)
+
+train_accommodation (enrollment_id) -> train_enrollment (enrollment_id)
+train_accommodation (dorm_id) -> train_dormitory_info (dorm_id)
+
+train_dorm_auth (accommodation_id) -> train_accommodation (accommodation_id)
+
+train_class_report (enrollment_id) -> train_enrollment (enrollment_id)
+
+train_student_checkin (enrollment_id) -> train_enrollment (enrollment_id)
+train_student_checkin (lesson_id) -> train_lesson (lesson_id)
+train_student_checkin (board_id) -> train_electronic_board (board_id)
+
+train_score_item (plan_id) -> train_class_plan (plan_id)
+train_score_item (plan_course_id) -> train_plan_course (plan_course_id)
+
+train_student_score (enrollment_id) -> train_enrollment (enrollment_id)
+train_student_score (score_item_id) -> train_score_item (score_item_id)
+
+train_study_duration (enrollment_id) -> train_enrollment (enrollment_id)
+train_study_duration (plan_course_id) -> train_plan_course (plan_course_id)
+train_study_duration (resource_id) -> train_resource (resource_id)
+
+train_student_portrait (enrollment_id) -> train_enrollment (enrollment_id)
+```
+
+### 2.2 删除规则原则审查
+- **核心合规**:所有 26 组外键规则均为 `ON DELETE NO ACTION`,**零级联删除(CASCADE)**;
+- **业务依据**:培训班作废、课程停用或学员离校,绝不可导致学员考勤、历史成绩、学时记录与住宿轨迹发生连带物理抹除,系统必须保留可追溯痕迹;
+- **系统表解耦**:所有培训表未对 `sys_user` 建立物理外键约束,仅在业务代码层做逻辑关联,避免跨领域强耦合。
+
+---
+
+## 3. 唯一约束(UNIQUE)审查
+
+V2 DDL 共注入 13 组核心业务 UNIQUE 约束:
+
+| 序号 | 约束名称 | 作用表 | 约束字段 | 业务防重目标 |
+| :--- | :--- | :--- | :--- | :--- |
+| 1 | `uq_student_idcard_hash` | `train_student` | `id_card_hash` | 学员身份证精确防重(允许 NULL) |
+| 2 | `uq_course_code` | `train_course` | `c_code` | 课程业务编码全局唯一 |
+| 3 | `uq_board_sn` | `train_electronic_board` | `board_sn` | 班牌设备硬件序列号全局唯一 |
+| 4 | `uq_dorm_building_room` | `train_dormitory_info` | `(dorm_building, dorm_room)` | 楼栋与房间组合唯一 |
+| 5 | `uq_course_resource` | `train_course_resource` | `(c_id, resource_id)` | 课程与资源绑定防重复 |
+| 6 | `uq_plan_course` | `train_plan_course` | `(plan_id, c_id)` | 同一培训班不可重复配置相同课程 |
+| 7 | `uq_enrollment` | `train_enrollment` | `(plan_id, student_id)` | 同一学员不可重复加入同一培训班 |
+| 8 | `uq_accommodation` | `train_accommodation` | `(enrollment_id)` | 一次参训单期唯一有效住宿分配 |
+| 9 | `uq_dorm_auth` | `train_dorm_auth` | `(accommodation_id)` | 一次住宿安排对应唯一门禁同步记录 |
+| 10 | `uq_class_report` | `train_class_report` | `(enrollment_id)` | 一次参训对应唯一现场报到结论 |
+| 11 | `uq_student_checkin` | `train_student_checkin` | `(enrollment_id, lesson_id)` | 一个学员一堂课只有一条考勤结论 |
+| 12 | `uq_student_score` | `train_student_score` | `(enrollment_id, score_item_id)` | 一个学员在某考核项只有一条最终得分 |
+| 13 | `uq_student_portrait` | `train_student_portrait` | `(enrollment_id)` | 一次参训对应一份全周期评价画像 |
+
+---
+
+## 4. 检查约束(CHECK)审查 (Round 1 扩充)
+
+在 Round 1 审查中,单行检查约束由原先的 4 条大幅扩充至 9 条,全面覆盖时间有效性、场地互斥、数值合法与系统字段联动:
+
+| 序号 | 约束名称 | 作用表 | 约束定义 | 校验逻辑目标 |
+| :---: | :--- | :--- | :--- | :--- |
+| 1 | `chk_lesson_time` | `train_lesson` | `start_time < end_time` | 课次开始时间必须早于结束时间 |
+| 2 | `chk_lesson_venue` | `train_lesson` | `(venue_type = 1 AND class_room_id IS NOT NULL AND site_id IS NULL) OR (venue_type = 2 AND site_id IS NOT NULL AND class_room_id IS NULL)` | **场地互斥**:教室与实训场地二选一,杜绝混淆 |
+| 3 | `chk_score_item_weight` | `train_score_item` | `weight >= 0.00 AND weight <= 100.00` | 单项成绩权重必须在 0~100 之间 |
+| 4 | `chk_score_item_full` | `train_score_item` | `full_score > 0.00` | 满分设定必须大于 0 |
+| 5 | `chk_student_score_nonneg` | `train_student_score` | `score >= 0.00` | **分值非负**:未录入不建行,录入则必须非负 |
+| 6 | `chk_study_seconds` | `train_study_duration` | `study_seconds >= 0` | 累计学习秒数必须非负 |
+| 7 | `chk_study_time` | `train_study_duration` | `end_time IS NULL OR start_time IS NULL OR end_time >= start_time` | **学时先后**:学习结束时间不得早于开始时间 |
+| 8 | `chk_study_source_system` | `train_study_duration` | `source_event_id IS NULL OR source_system IS NOT NULL` | **单号匹配**:有外部单号时必须声明来源系统 |
+| 9 | `chk_dorm_capacity` | `train_dormitory_info` | `capacity > 0` | **容量正数**:宿舍房间核定床位数必须大于 0 |
+
+---
+
+## 5. 索引(INDEX)审查
+
+[`006_indexes.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/006_indexes.sql) 包含外键索引、排课多维复合索引与部分唯一索引:
+
+1. **外键索引**:为所有 26 组外键列配置独立 B-Tree 索引,杜绝父表更新锁定子表或关联全表扫描;
+2. **排课多维冲突高频复合索引**:
+ - 教师时间冲突检测:`idx_lesson_teacher_time (t_id, start_time, end_time)`;
+ - 教室时间冲突检测:`idx_lesson_classroom_time (class_room_id, start_time, end_time)`;
+ - 场地时间冲突检测:`idx_lesson_site_time (site_id, start_time, end_time)`;
+3. **双非空过滤的部分唯一索引(Partial Unique Index)**:
+ - `uq_idx_study_source_event` on `train_study_duration(source_system, source_event_id) WHERE source_system IS NOT NULL AND source_event_id IS NOT NULL`;
+ - **审查要点**:严格杜绝 `source_system` 为空而单号有值时的幂等逃逸。
diff --git a/docs/database-v2/04_risk_review.md b/docs/database-v2/04_risk_review.md
new file mode 100644
index 000000000..98482a4ed
--- /dev/null
+++ b/docs/database-v2/04_risk_review.md
@@ -0,0 +1,101 @@
+# RailwaySystem 数据库 V2 关键设计风险深度审查报告 (R-01 ~ R-17)
+
+> **审查定位**:数据库底层引擎兼容性、约束边界、数据一致性与应用层 Service 协同审查
+> **技术基线**:KingbaseES V009R003C018 (`schema=public`, `database_mode=mysql`)、MyBatis 3.5.x、RuoYi-Vue 基础架构
+> **版本状态**:Round 2 审查最终静态收尾版(固化架构决策 A/B,解耦 source_type 语义,清除业务选择型默认值)
+
+---
+
+## 风险全景概览
+
+| 风险编号 | 风险主题 | 风险等级 | 影响范畴 | 本次 DDL 应对方案 | 应用层/Service 协同要求 | 决策状态 |
+| :--- | :--- | :---: | :--- | :--- | :--- | :---: |
+| **R-01** | 旧外键阻塞 ALTER / DROP COLUMN | **高** | 迁移执行期阻断 | 在 DDL 步骤中前置显示 `DROP CONSTRAINT IF EXISTS` | 严格按迁移编排顺序执行 | 已关闭 |
+| **R-02** | identity 主键与 MyBatis 兼容性 | **中** | 写入与自增回填 | 采用标准 `GENERATED BY DEFAULT AS IDENTITY` | Mapper 继续配置 `useGeneratedKeys="true"` | 已闭环 |
+| **R-03** | Kingbase 下 UNIQUE + NULL 语义 | **中** | 数据防重有效性 | 遵循 SQL 标准语义(NULL 不等),关键组合列强制非空 | 业务关键组合列强制非空或用部分索引 | 已闭环 |
+| **R-04** | `id_card_hash` 唯一约束对 NULL 行为 | **低** | 学员未采身份证防重 | 建立单列 UNIQUE,允许多行 NULL 不冲突 | 应用层空串 `""` 必须显式转为 `NULL` 入库 | 已闭环 |
+| **R-05** | 学习记录幂等唯一约束中 NULL 行为 | **中** | 第三方学习数据幂等 | 采用双非空条件部分唯一索引 + 联动 CHECK | 上报接口对具备单号的数据做幂等截流 | 已闭环 |
+| **R-06** | 排课多维时间冲突无法靠 UNIQUE 实现 | **高** | 教学资源重叠与冲突 | 建立高频复合索引支撑区间检索,增加场地互斥 CHECK | **架构决策 A**:排课 Service 事务校验 + 行锁防重 | **已冻结决策** |
+| **R-07** | 宿舍容量超额无法靠 DB 静态约束 | **高** | 宿舍超员分配超售 | 废除静态 `bed_used` 字段,加 `capacity > 0` CHECK | **架构决策 A**:住宿 Service 事务内 `SELECT FOR UPDATE` | **已冻结决策** |
+| **R-08** | 成绩项目权重总和 100% 无法靠 CHECK | **中** | 成绩评估规则失衡 | 数据库仅设单行 `0~100` 标量 CHECK,不跨行聚合 | 开班与考核规则配置 Service 校验有效和等于 100% | 已闭环 |
+| **R-09** | V2 表与 RuoYi Generator / BaseEntity 差异 | **中** | 代码生成与 CRUD | 数据库采用标准蛇形命名,补齐 `del_flag` 等审计列 | 后续重构 Entity 继承 BaseEntity 并重新映射 Mapper | 已闭环 |
+| **R-10** | 现有 9 个 update_time 触发器安全移除 | **中** | 数据更新时间一致性 | 003 脚本显式前置 `DROP TRIGGER IF EXISTS` 卸载 | 应用层 Service 或 MyBatis 拦截器显式维护更新时间 | 已闭环 |
+| **R-11** | 跨培训班核心关系一致性 (串班风险) | **高** | 业务逻辑穿透污染 | 不在子表反范式冗余 `plan_id`,保持规范化模型 | **架构决策 B**:Service 强制校验链条一致性 | **已冻结决策** |
+| **R-12** | 班牌设备与课次教室空间一致性 | **中** | 考勤打卡位置穿透 | 班牌绑定教室,签到关联 lesson 与 board | 考勤 Service 校验班牌物理教室与课次教室完全匹配 | 已闭环 |
+| **R-13** | 宿舍容量必须考虑培训周期时间重叠 | **高** | 跨期住宿容量误判 | 数据库不保存跨期占用,仅靠 status 会误杀 | 住宿 Service 必须按学员参训 plan 起止区间算重叠有效人数 | 已闭环 |
+| **R-14** | 报到流水与参训状态变更的原子性 | **高** | 状态与报到记录脱节 | 报到记录表与参训表解耦,依赖业务事务保证 | 报到操作必须在单个本地事务内执行“插报到+改状态” | 已闭环 |
+| **R-15** | 成绩记录存在性与真实 0 分语义 | **中** | 成绩录入状态失真 | 移除 DEFAULT 0,加非负 CHECK,无行代表未录成绩 | 查询综合成绩时通过左连接或外层逻辑区分未评与 0 分 | 已闭环 |
+| **R-16** | 业务选择型字段违规设置数据库默认值 | **高** | 业务意图被系统静默猜测 | 彻底清除核验结果、考勤方式、场地类型等 DEFAULT | 调用方必须显式传入真实业务值,严禁自动代填 | 已闭环 |
+| **R-17** | 两处 `source_type` 语义混淆与臆造枚举 | **中** | 字典定义混乱与流程固化 | 区分主档来源与参训来源,解除未定字典硬编码 | 独立字典维护,学员主档与名单来源彻底解耦 | 已闭环 |
+
+---
+
+## 核心架构决策正式固化 (技术负责人已拍板)
+
+### 架构决策 A:排课与住宿并发控制方案 (冻结)
+- **技术负责人拍板结论**:
+ 一期**坚决不引入**外部排课引擎、时间区间调度中间件或重型规则引擎。
+- **实施边界**:
+ 1. **数据库层**:提供针对性的多列复合索引(`idx_lesson_teacher_time`, `idx_lesson_classroom_time`, `idx_lesson_site_time`),确保范围查询毫秒级响应;
+ 2. **应用服务层**:排课与调课业务由 `TrainLessonService` 在 `@Transactional` 事务内执行区间交叉判断(`start_time < :newEnd AND end_time > :newStart`);
+ 3. **并发防护**:高并发场景下,使用 `SELECT ... FOR UPDATE` 悲观锁或分布式锁锁定教师日历/教室资源/宿舍房间,确保零时间冲突、零超售。
+
+### 架构决策 B:跨培训班一致性控制规范 (防串班,冻结)
+- **技术负责人拍板结论**:
+ **坚决不为了防止业务串班而在打卡、成绩、学习记录表中重复冗余增加 `plan_id`**,全面维持数据库 V2 的 3NF 规范化设计,防止数据更新异常与列冗余。
+- **实施边界**:
+ 由相关业务 Service 在执行写入前执行强一致性校验链条,任何不匹配必须当场抛出业务异常拒绝写入:
+ ```text
+ 1. 考勤打卡:
+ checkin.enrollment.plan_id == lesson.plan_course.plan_id
+ 2. 成绩录入:
+ student_score.enrollment.plan_id == score_item.plan_id
+ 3. 考核项关联课程:
+ IF score_item.plan_course_id IS NOT NULL:
+ score_item.plan_id == plan_course.plan_id
+ 4. 学习时长上报:
+ study_duration.enrollment.plan_id == plan_course.plan_id
+ ```
+
+---
+
+## 深度风险分析与防范对策
+
+### R-16: 业务选择型默认值删除与责任边界
+- **问题机制**:
+ 若数据库为 `train_class_report.verify_result` 配置 `DEFAULT 1`(核验通过),一旦前端或接口未传该字段,数据库将自动判定该学员“核验通过”,造成假通过的安全漏洞;同样,`venue_type DEFAULT 1`、`source_type DEFAULT 1`、`checkin_way DEFAULT 1` 等均属于业务必须明确作出的选择。
+- **DDL 改造方案**:
+ 全面移除以下字段的默认值,强制设为 `NOT NULL`,迫使应用层显式传参:
+ - `train_enrollment.source_type SMALLINT NOT NULL`
+ - `train_enrollment.accommodation_required SMALLINT NOT NULL`
+ - `train_lesson.venue_type SMALLINT NOT NULL`
+ - `train_student_score.source_type SMALLINT NOT NULL`
+ - `train_student_checkin.checkin_way SMALLINT NOT NULL`
+ - `train_class_report.verify_result SMALLINT NOT NULL`
+- **生命周期状态说明**:
+ 生命周期的初始状态仍保留合理默认值,例如:
+ - `train_class_plan.plan_status`: `DEFAULT 0` (未开始)
+ - `train_enrollment.enrollment_status`: `DEFAULT 0` (待报到)
+ - `train_accommodation.accommodation_status`: `DEFAULT 0` (预分配,由 1 修正为 0)
+ - `train_dorm_auth.face_sync_status`: `DEFAULT 0` (待下发)
+ - `train_dorm_auth.retry_count`: `DEFAULT 0`
+ - `train_student_checkin.manual_flag`: `DEFAULT 0` (自动)
+
+---
+
+### R-17: 两个 source_type 语义彻底解耦
+系统在两张核心表中存在同名字段 `source_type`,必须从业务与字典层面彻底隔离,杜绝混用:
+
+1. **`train_student.source_type` (学员长期主档来源)**:
+ - **业务含义**:自然人作为学员进入铁路培训系统长期资源库的注册渠道。
+ - **典型枚举**:
+ - `1`: 管理员手工录入
+ - `2`: Excel 花名册批量导入
+ - `3`: 铁路内部人力/教务业务平台同步
+ - **对应字典**:`train_student_source`
+
+2. **`train_enrollment.source_type` (参训名单进入来源)**:
+ - **业务含义**:已在库学员被选拔/加入到**具体某一期培训班名单**的业务途径。
+ - **设计准则**:
+ 清除“自主报名/单位推荐/统一调训”等未经正式拍板的臆造流程枚举,DDL 注释明确标记:“参训名单来源,具体字典值由 train_enrollment_source 定义”。
+ - **对应字典**:后续由独立业务字典 `train_enrollment_source` 承载,两字段严禁共用同一字典。
diff --git a/docs/database-v2/05_execution_contract.md b/docs/database-v2/05_execution_contract.md
new file mode 100644
index 000000000..b15f99593
--- /dev/null
+++ b/docs/database-v2/05_execution_contract.md
@@ -0,0 +1,92 @@
+# RailwaySystem 数据库 V2 迁移执行契约 (Execution Contract)
+
+> **适用范围**:数据库 V2 迁移在测试环境与未来生产环境中的正式执行规范
+> **技术基线**:KingbaseES V009R003C018 (`database=training`, `schema=public`, `database_mode=mysql`)
+> **核心原则**:**双门禁强准入 (Gate A/B)、单文件显式事务、纯 SQL 执行器兼容、失败即刻熔断**
+
+---
+
+## 1. 执行器与客户端兼容规范
+
+为杜绝因客户端专有指令导致的语法中断或解析失败,物理迁移 SQL 已全面实施去客户端化:
+1. **纯标准 SQL 语法**:
+ - 彻底移除 `\echo`、`\set`、`DELIMITER` 等特定客户端(如 psql/ksql/mysql)专有元命令;
+ - 进度提示统一采用 PL/pgSQL 标准内置机制:`RAISE NOTICE '...'`;
+ - 失败阻断统一采用标准异常中断:`RAISE EXCEPTION '...'`。
+2. **多客户端适配兼容性**:
+ - 支持通过 Kingbase 原生命令行工具 `ksql` 执行:`ksql -U kingbase -d training -f xxx.sql`;
+ - 支持通过通用数据库客户端(如 DBeaver、Navicat、DataGrip)以“执行脚本文件”模式执行;
+ - 支持通过自动化运维流水线或 JDBC Runner 顺序执行。
+
+---
+
+## 2. 迁移编排流水线与事务边界
+
+迁移必须严格按照以下阶段顺序串行执行。**任何前置 Gate 失败或 Stage 报错,必须立即停止,绝对禁止跳步骤继续!**
+
+```mermaid
+graph TD
+ GateA[Gate A: 000_tx_capability_probe.sql] -->|PASS| GateB[Gate B: 000_preflight.sql]
+ GateB -->|PASS| S1[Stage 1: 001_backup_current_schema.sql]
+ S1 --> S2[Stage 2: 002_create_new_tables.sql]
+ S2 --> S3[Stage 3: 003_alter_master_tables.sql]
+ S3 --> S4[Stage 4: 004_rebuild_business_tables.sql]
+ S4 --> S5[Stage 5: 005_constraints.sql]
+ S5 --> S6[Stage 6: 006_indexes.sql]
+ S6 -.->|跳过字典初始化| S7[Stage 7: 008_migrate_teacher.sql]
+ S7 --> S8[Stage 8: 009_drop_legacy_score.sql]
+ S8 --> S9[Stage 9: 010_verify.sql]
+ S9 --> Done[迁移完成 交付测试验收]
+```
+
+### 详细阶段契约表
+
+| 阶段 | 脚本文件 | 事务边界 | 失败处理与影响 |
+| :---: | :--- | :---: | :--- |
+| **Gate A** | [`000_tx_capability_probe.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/000_tx_capability_probe.sql) | 探针显式事务 | **强阻断**:实证探测实例 DDL 回滚能力。若表残留立即抛出异常并中止,严禁进入后续阶段 |
+| **Gate B** | [`000_preflight.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/000_preflight.sql) | 纯只读骨架断言 | **强阻断**:集合差集校验 14旧表PK、24旧表FK、7组UNIQUE、6个identity主键、9触发器与行数基线,任何不符立即中止 |
+| **Stage 1** | [`001_backup_current_schema.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/001_backup_current_schema.sql) | `BEGIN ... COMMIT` | **强阻断**:全量快照 14 张表至 `bak_v1_*`;若已存在备份表则阻断;失败全单回滚 |
+| **Stage 2** | [`002_create_new_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql) | `BEGIN ... COMMIT` | 创建 V2 新增 8 张表;严禁 `IF NOT EXISTS`;失败事务回滚,新表全部撤销 |
+| **Stage 3** | [`003_alter_master_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/003_alter_master_tables.sql) | `BEGIN ... COMMIT` | 调整 8 张主数据表;移除旧触发器与阻断外键,添加 V2 新列;失败事务回滚 |
+| **Stage 4** | [`004_rebuild_business_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/004_rebuild_business_tables.sql) | `BEGIN ... COMMIT` | 断言 0 行后重构 5 张业务表;失败事务回滚,原表结构保持不变 |
+| **Stage 5** | [`005_constraints.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/005_constraints.sql) | `BEGIN ... COMMIT` | 集中注入 13 组 UNIQUE、26 组 FK (NO ACTION)、9 组 CHECK;失败事务回滚 |
+| **Stage 6** | [`006_indexes.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/006_indexes.sql) | `BEGIN ... COMMIT` | 创建外键索引、排课多维复合索引及双非空部分唯一索引;失败事务回滚 |
+| **-** | [`007_dicts.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/007_dicts.sql) | - | **【本迁移流水线跳过不执行】** 业务字典留待应用接口及权限配置阶段接入 |
+| **Stage 7** | [`008_migrate_teacher.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/008_migrate_teacher.sql) | `BEGIN ... COMMIT` | 迁移并断言教师 1 行数据,固化 NOT NULL,安全清理旧列;失败事务回滚 |
+| **Stage 8** | [`009_drop_legacy_score.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/009_drop_legacy_score.sql) | `BEGIN ... COMMIT` | 断言 0 行后下线旧表 `train_score_info`;失败事务回滚,旧表完好保留 |
+| **Stage 9** | [`010_verify.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/010_verify.sql) | 纯只读深度断言 | **强阻断**:定义级全量验收 21 表、UNIQUE 列清单、FK NO ACTION、CHECK 表达式、12 Identity、默认值及系统表零受损 |
+
+---
+
+## 3. 已冻结的核心架构决策 (技术负责人正式拍板)
+
+在数据库 V2 迁移及后续业务开发中,以下两项设计原则已作为**已冻结架构决策**执行:
+
+### 决策 A:排课与住宿并发控制
+- **决策结论**:一期**绝不引入**外部排课引擎或复杂时间区间调度框架。
+- **技术实现**:
+ 1. 数据库层面配置针对性复合检索索引(`idx_lesson_teacher_time`, `idx_lesson_classroom_time`, `idx_lesson_site_time`);
+ 2. 业务层面由排课与住宿分配 Service 在单个本地事务内执行区间交叉检索;
+ 3. 必要时使用 `SELECT ... FOR UPDATE` 悲观锁锁定宿位或教师日历,保障并发一致性。
+
+### 决策 B:跨培训班核心业务一致性 (防串班)
+- **决策结论**:**绝不**为了防止串班而在考勤、成绩、自主学习时长等细粒度业务表冗余增加 `plan_id` 反范式列,严格保持数据库 V2 的 3NF 规范化设计。
+- **技术实现**:
+ 由应用层业务 Service 在写入和处理业务时强制校验一致性链条:
+ - `checkin.enrollment.plan_id = lesson.plan_course.plan_id` (考勤打卡班级一致)
+ - `student_score.enrollment.plan_id = score_item.plan_id` (成绩录入班级一致)
+ - 当 `score_item.plan_course_id IS NOT NULL` 时,`score_item.plan_id = plan_course.plan_id`
+ - `study_duration.enrollment.plan_id = plan_course.plan_id` (学习记录班级一致)
+ 任何不一致均由 Service 抛出业务异常阻断入库。
+
+---
+
+## 4. 失败处理与应急回滚规范
+
+1. **单点失败即刻熔断**:
+ - 若流水线中任何一个脚本执行报错,**严禁跳过该步骤继续执行后续脚本**!
+ - 单文件具备 `BEGIN ... COMMIT`,当前失败脚本的所有物理改动会自动回滚撤销。
+2. **应急回滚调用准则**:
+ - 若在 Stage 2 ~ Stage 8 中途发生不可调和的异常,必须立即暂停,并由 DBA 评估调用 [`rollback/`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/rollback/) 脚本;
+ - 回滚流水线严格按照:`001_rollback_new_tables.sql` -> `002_rollback_modified_tables.sql` -> `003_restore_legacy_score.sql` 倒序执行;
+ - 回滚完毕后,必须运行 `000_preflight.sql` 校验是否完全恢复至 Phase 0.5 精确基线。
diff --git a/docs/database-v2/06_review_round1_changes.md b/docs/database-v2/06_review_round1_changes.md
new file mode 100644
index 000000000..667d78bdd
--- /dev/null
+++ b/docs/database-v2/06_review_round1_changes.md
@@ -0,0 +1,29 @@
+# RailwaySystem 数据库 V2 DDL Review 修订记录表 (Round 1)
+
+> **评审周期**:Round 1
+> **评审基线**:高级技术负责人第一轮人工 Review 意见
+> **状态**:**已全部闭环解决 (100% Resolved)**
+
+---
+
+## 修改明细汇总表
+
+| 问题编号 | 模块分类 | 原问题描述 | 涉及修改文件 | 具体修改内容与工程落地 | 解决状态 |
+| :---: | :---: | :--- | :--- | :--- | :---: |
+| **REV-01** | **P0 架构** | 破坏性迁移脚本无事务边界,遇错可能部分提交;包含客户端 `\echo` 指令 | [`001`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/001_backup_current_schema.sql)~[`009`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/009_drop_legacy_score.sql), [`05_execution_contract.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/05_execution_contract.md) | 所有物理 DDL 脚本全面使用 `BEGIN ... COMMIT` 包裹,彻底删除 `\echo` 改造为纯 SQL,建立统一执行契约文档 | **已解决** |
+| **REV-02** | **P0 基线** | 缺乏迁移前置环境基线校验,可能在未知或已被破坏的环境中误执行 | [`000_preflight.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/000_preflight.sql) | 新增前置纯只读检查脚本,强校验当前环境必须精确符合 Phase 0.5 状态(14表、行数、触发器等),任何不符立即抛出异常中止 | **已解决** |
+| **REV-03** | **P0 备份** | 001 脚本使用 `DROP TABLE IF EXISTS bak_v1_*`,误执行可能覆盖最初 V1 备份 | [`001_backup_current_schema.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/001_backup_current_schema.sql) | 增加强防重校验,若已存在任意 `bak_v1_*` 表立即抛异常阻断,严禁自动 DROP 覆盖既有历史备份 | **已解决** |
+| **REV-04** | **P0 回滚** | CTAS 无法保留约束、默认值、触发器和 Identity,不能作为回滚结构来源 | [`rollback/000_phase05_exact_schema.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/rollback/000_phase05_exact_schema.sql), [`rollback/002`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/rollback/002_rollback_modified_tables.sql), [`rollback/003`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/rollback/003_restore_legacy_score.sql) | 新增标准 Phase 0.5 完整物理 DDL;重构回滚脚本,严格基于真实 DDL 重建结构,仅用 `bak_v1_*` 还原数据,解耦结构与数据 | **已解决** |
+| **REV-05** | **P0 验收** | 010_verify 很多检查仅输出文本,最终未强行阻断,存在假阳性漏报隐患 | [`010_verify.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/010_verify.sql) | 重构为真正的“失败即失败”,逐表、逐列、逐外键(删除规则)、逐唯一约束、逐索引进行 PL/pgSQL 强断言,出现任何不符立即抛异常终止 | **已解决** |
+| **REV-06** | **字段规范** | `train_lesson.t_id` 原定义为可空,与排课必要性要求冲突 | [`002_create_new_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql) | 将 `train_lesson.t_id` 设为 `VARCHAR(32) NOT NULL`,并在 010 中强断言 | **已解决** |
+| **REV-07** | **字段规范** | `train_teacher` 新增的 `status` 与 `del_flag` 未在迁移后固化为 NOT NULL | [`008_migrate_teacher.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/008_migrate_teacher.sql) | 迁移历史教师数据并完成数据完整性校验后,显式执行 `ALTER COLUMN SET NOT NULL` | **已解决** |
+| **REV-08** | **字段规范** | `train_student_score.score` 存在未经确认的 `DEFAULT 0`,掩盖未录入状态 | [`002_create_new_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql), [`005_constraints.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/005_constraints.sql) | 删除 `DEFAULT 0`,保留 `NOT NULL`,增加 `CHECK (score >= 0.00)`;未录成绩不建行,0 分代表真实得分 | **已解决** |
+| **REV-09** | **字段规范** | 宿舍表 `dorm_floor` 默认值 `'1'` 和 `capacity` 默认值 `4` 属于 AI 猜测 | [`003_alter_master_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/003_alter_master_tables.sql), [`005_constraints.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/005_constraints.sql) | 移除所有业务默认值猜测,字段保持 NOT NULL 由管理员录入,增加 `CHECK (capacity > 0)` 约束 | **已解决** |
+| **REV-10** | **字段规范** | `train_electronic_board.board_name` 包含 `DEFAULT ''` 空串伪造合法值 | [`003_alter_master_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/003_alter_master_tables.sql) | 彻底移除 `DEFAULT ''`,改为 `VARCHAR(100) NOT NULL`,由用户录入明确设备名 | **已解决** |
+| **REV-11** | **业务语义** | 学员来源出现“统招学员”等高校概念,两处 `source_type` 含义含糊 | [`002`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql), [`003`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/003_alter_master_tables.sql), [`007_dicts.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/007_dicts.sql) | 彻底剥离高校术语,区分:`student.source_type` 为主档来源(管理员/Excel/平台同步);`enrollment.source_type` 为参训名单来源(指派/报名/推荐/调训) | **已解决** |
+| **REV-12** | **业务语义** | 教学资源类型字典与 V2 冻结稿存在分类差异 | [`002_create_new_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql), [`007_dicts.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/007_dicts.sql) | 严格对齐 V2 冻结稿:1文档, 2视频, 3 3D模型, 4 VR资源, 5外部教学链接, 6其他 | **已解决** |
+| **REV-13** | **约束安全** | 学习记录部分唯一索引当 `source_system = NULL` 且 `source_event_id != NULL` 时发生幂等逃逸 | [`004`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/004_rebuild_business_tables.sql), [`005`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/005_constraints.sql), [`006_indexes.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/006_indexes.sql) | 索引条件修正为双非空 `WHERE source_system IS NOT NULL AND source_event_id IS NOT NULL`;增加 CHECK 约束强制单号非空时系统名必填 | **已解决** |
+| **REV-14** | **依赖解耦** | 脚本滥用 `DROP TABLE ... CASCADE` 掩盖未预期依赖 | [`004`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/004_rebuild_business_tables.sql), [`009`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/009_drop_legacy_score.sql), [`rollback`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/rollback/) | 迁移与回滚脚本全面显式解除已知约束,改用常规 `DROP TABLE`,禁止使用 CASCADE 掩盖隐式依赖 | **已解决** |
+| **REV-15** | **数据一致** | 排课场地类型与教室/实训场地未在数据库层实现单行互斥;学时时间未核验先后 | [`002`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql), [`004`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/004_rebuild_business_tables.sql), [`005_constraints.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/005_constraints.sql) | `train_lesson` 增加 `chk_lesson_venue` 互斥 CHECK;`train_study_duration` 增加 `end_time >= start_time` CHECK 约束 | **已解决** |
+| **REV-16** | **风险扩展** | 风险报告需要补充跨班级关联、班牌一致性、宿舍重叠计算等高级业务风险 | [`04_risk_review.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/04_risk_review.md) | 在文档中新增 **R-11 至 R-15** 五项重大业务与并发一致性风险深度剖析 | **已解决** |
+| **REV-17** | **执行控制** | 结构迁移阶段执行 007_dicts 会污染空库测试基线 | [`02_migration_plan.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/02_migration_plan.md), [`05_execution_contract.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/05_execution_contract.md) | 正式明确 007 在本阶段暂不执行,等后续 API/权限设计阶段统一执行 | **已解决** |
diff --git a/docs/database-v2/07_review_round2_changes.md b/docs/database-v2/07_review_round2_changes.md
new file mode 100644
index 000000000..888a424a3
--- /dev/null
+++ b/docs/database-v2/07_review_round2_changes.md
@@ -0,0 +1,143 @@
+# RailwaySystem 数据库 V2 DDL Review Round 2 变更记录 (最终静态收尾)
+
+> **修订阶段**:数据库 V2 DDL Review Round 2(最终静态收尾)
+> **最高依据**:`RailwaySystem 数据库 V2 字段设计与 Kingbase DDL 规范 V1.0.md`
+> **修订目标**:解决高级技术负责人 Final Static Review 提出的 7 个核心静态问题(R2-01 ~ R2-07),使数据库 V2 DDL 达到“允许进入测试迁移”状态。
+
+---
+
+## 变更明细清单 (R2-01 ~ R2-07)
+
+### R2-01: 修正住宿状态默认值
+- **问题**:`train_accommodation.accommodation_status` 原默认值为 `1`(已入住)。而正式业务流程为:名单确定 -> 报到前宿舍预分配 -> 学员报到核验 -> 展示已分配宿舍 -> 实际入住。若默认直接为已入住,与真实业务全生命周期相悖。
+- **原实现**:
+ ```sql
+ accommodation_status SMALLINT NOT NULL DEFAULT 1
+ ```
+- **修改文件**:
+ - [`002_create_new_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql#L142)
+ - [`010_verify.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/010_verify.sql)
+- **修改后实现**:
+ ```sql
+ accommodation_status SMALLINT NOT NULL DEFAULT 0
+ ```
+ 字段注释保持为:`住宿状态 (0:预分配, 1:已入住, 2:已退宿)`;`010_verify.sql` 中新增对 `accommodation_status` 默认值精确为 0 的强断言。
+- **验证方式**:静态文本检索与 `010_verify.sql` 自动化断言规则核验。
+- **是否解决**:**已彻底解决**。
+
+---
+
+### R2-02: 删除“业务选择型默认值”
+- **问题**:原 SQL 中对部分必须由调用方主动选择的业务输入字段设置了 `DEFAULT 0` 或 `DEFAULT 1`,特别是 `verify_result DEFAULT 1`(核验通过),会导致应用层若漏传该参数,数据库自动判定通过,掩盖业务逻辑缺陷;同样,考勤方式、场地类型、住宿需求、来源类型等必须由业务明确提供,不允许数据库代替调用方猜测。
+- **原实现**:
+ - `train_enrollment.source_type`: `DEFAULT 1`
+ - `train_enrollment.accommodation_required`: `DEFAULT 0`
+ - `train_lesson.venue_type`: `DEFAULT 1`
+ - `train_student_score.source_type`: `DEFAULT 1`
+ - `train_student_checkin.checkin_way`: `DEFAULT 1`
+ - `train_class_report.verify_result`: `DEFAULT 1`
+- **修改文件**:
+ - [`002_create_new_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql)
+ - [`004_rebuild_business_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/004_rebuild_business_tables.sql)
+ - [`010_verify.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/010_verify.sql)
+- **修改后实现**:
+ 上述 6 个字段全部移除 `DEFAULT` 声明,仅保留 `SMALLINT NOT NULL`。`010_verify.sql` 中增加只读断言:上述字段的 `column_default` 必须全部为 `NULL`,若存在默认值当场抛异常。
+- **验证方式**:静态 grep 全局检索与 `010_verify.sql` 断言校验。
+- **是否解决**:**已彻底解决**。
+
+---
+
+### R2-03: 清除 Enrollment 来源的臆造枚举并解耦双 source_type
+- **问题**:`train_enrollment.source_type` 注释中原先硬编码了“1:组织指派, 2:自主报名, 3:单位推荐, 4:统一调训”,这属于未经正式会议冻结的臆造业务流程枚举;且容易与 `train_student.source_type`(学员长期主档来源)发生混淆。
+- **原实现**:
+ ```sql
+ COMMENT ON COLUMN train_enrollment.source_type IS '进入本期培训名单的来源 (1:组织指派, 2:自主报名, 3:单位推荐, 4:统一调训)';
+ ```
+- **修改文件**:
+ - [`002_create_new_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql#L94)
+ - [`04_risk_review.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/04_risk_review.md)
+ - [`01_table_inventory.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/01_table_inventory.md)
+- **修改后实现**:
+ - 注释修改为:
+ ```sql
+ COMMENT ON COLUMN train_enrollment.source_type IS '参训名单来源,具体字典值由 train_enrollment_source 定义';
+ ```
+ - 文档中明确解耦定义:
+ 1. `train_student.source_type`:学员长期主档进入系统的来源(管理员录入/Excel导入/平台同步);
+ 2. `train_enrollment.source_type`:人员进入“本期培训名单”的来源,由独立字典承载,严禁共用同一模糊枚举。
+- **验证方式**:审查注释与文档的一致性。
+- **是否解决**:**已彻底解决**。
+
+---
+
+### R2-04: Preflight 升级为真正 Phase 0.5 精确骨架校验
+- **问题**:原 `000_preflight.sql` 仅做了表存在性、行数和少量代表性约束判断,未能覆盖完整的 Phase 0.5 物理结构骨架,若存在“少一个正确FK + 多一个错误FK”的对冲情况可能假阳性通过。
+- **原实现**:部分抽检 + 触发器循环判断。
+- **修改文件**:
+ - [`000_preflight.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/000_preflight.sql)
+- **修改后实现**:
+ 采用 CTE `VALUES(...)` 构造预期基线集合,与系统目录做全集合差集比对:
+ - 14 个旧表 PK (table_name + constraint_name + column_name)
+ - 6 个 Phase 0.5 identity 自增主键 (table_name + column_name + is_identity = 'YES')
+ - 7 组业务 UNIQUE 约束 (table_name + constraint_name + column_list)
+ - 24 组业务 FK 约束 (table_name + constraint_name + column_name + foreign_table_name + foreign_column_name)
+ - 9 个 update_time 触发器 (table_name + trigger_name)
+ - 行数基线:`train_teacher` 精确 1 行,其余 13 张旧表精确 0 行
+ - 8 张 V2 表均不得存在,public.sys_* 表零受损
+ - 任何 missing / unexpected / definition mismatch 立即抛出 `RAISE EXCEPTION`。
+- **验证方式**:对比 `rollback/000_phase05_exact_schema.sql` 校验集合完备性。
+- **是否解决**:**已彻底解决**。
+
+---
+
+### R2-05: 010_verify 升级为“定义级验收”
+- **问题**:原 010 验收脚本主要核验对象名称存在性,对约束内部的具体列排序、外键删除规则、CHECK 表达式逻辑等未做定义级校验。
+- **原实现**:检查约束名称与 `count(*) = 26` 等数量判断。
+- **修改文件**:
+ - [`010_verify.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/010_verify.sql)
+- **修改后实现**:
+ - **UNIQUE 验收**:必须断言 `table_name` + `constraint_name` + `column_list`(如 `train_enrollment(plan_id, student_id)`);
+ - **FK 验收**:必须断言源表、源列、目标表、目标列及 `delete_rule = 'NO ACTION'`,严禁 CASCADE;
+ - **CHECK 验收**:按约束名逐项检索表达式,校验包含预期表达式(时间先后、场地二选一、权重0~100、满分>0、得分非负、时长非负、单号系统联动、容量>0);
+ - **Identity 验收**:逐项确认 12 张业务表的主键列名且 `is_identity = 'YES'`;
+ - **Index 验收**:确认 3 组排课复合时间列排序;确认 `uq_idx_study_source_event` 的 `(source_system, source_event_id)` 及双非空 WHERE 条件;
+ - **默认值验收**:强断言 `accommodation_status` 默认为 0,强断言 6 个业务选择型字段无默认值。
+- **验证方式**:静态代码比对与逻辑推演。
+- **是否解决**:**已彻底解决**。
+
+---
+
+### R2-06: 正式迁移对象删除 IF NOT EXISTS
+- **问题**:V2 是一次从已知 Phase 0.5 基线出发的严格版本迁移,已有 Preflight 保证环境纯净。若正式建表或建索引保留 `IF NOT EXISTS`,一旦因历史残留存在同名但结构错误的脏对象,DDL 将静默跳过真正正确的对象创建,掩盖严重隐患。
+- **原实现**:
+ - `CREATE TABLE IF NOT EXISTS train_...` (002)
+ - `ADD COLUMN IF NOT EXISTS ...` (003)
+ - `CREATE INDEX IF NOT EXISTS ...` (006)
+- **修改文件**:
+ - [`002_create_new_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/002_create_new_tables.sql)
+ - [`003_alter_master_tables.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/003_alter_master_tables.sql)
+ - [`006_indexes.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/006_indexes.sql)
+- **修改后实现**:
+ - 002 中 8 张新增表全部改为严格 `CREATE TABLE`;
+ - 003 中新增字段全部改为严格 `ADD COLUMN`;
+ - 006 中所有索引全部改为严格 `CREATE INDEX` 与 `CREATE UNIQUE INDEX`;
+ - 仅保留防御性卸载旧对象的 `DROP CONSTRAINT IF EXISTS` 和 `DROP TRIGGER IF EXISTS`。
+- **验证方式**:全局 grep 检查 `IF NOT EXISTS` 出现位置并逐一确认合理性。
+- **是否解决**:**已彻底解决**。
+
+---
+
+### R2-07: 增加 DDL Transaction Probe Gate
+- **问题**:迁移执行契约依赖事务的原子性(`BEGIN ... COMMIT / ROLLBACK`)。当前环境为 KingbaseES V009R003C018 (`database_mode=mysql`),需在正式执行 V2 前实证验证当前数据库实例对 DDL 的事务回滚支持能力。
+- **原实现**:未设立 DDL 事务能力前置探针。
+- **修改文件**:
+ - 新增:[`RuoYi-Vue/sql/train/v2/000_tx_capability_probe.sql`](file:///Users/wzb/Desktop/项目/RailwaySystem/RuoYi-Vue/sql/train/v2/000_tx_capability_probe.sql)
+ - [`05_execution_contract.md`](file:///Users/wzb/Desktop/项目/RailwaySystem/docs/database-v2/05_execution_contract.md)
+- **修改后实现**:
+ - 创建独立的安全探针脚本(作为 Gate A):
+ - **Phase A**:`BEGIN -> CREATE TABLE public.__railway_v2_tx_probe -> ALTER TABLE -> ROLLBACK`;
+ - **Phase B**:只读断言 `__railway_v2_tx_probe` 是否存在。若残留则强行抛出 `RAISE EXCEPTION` 阻断后续所有迁移;
+ - 绝不读取或修改任何业务表或系统表,仅使用专用临时对象。
+ - 在执行契约中将 Gate A 设定为执行流水线第一道强制关卡。
+- **验证方式**:审查探针脚本的幂等性与零副作用安全性。
+- **是否解决**:**已彻底解决**。