Files
msgexchange-v2/src/main/resources/db/migration/V1__flight_state_baseline.sql
T
windyboy 879d658159 refactor(flight-state): 按 flight-state.md 审计定稿全量重构脚手架与 SQL (ACM2-31)
- SQL 基线 V1__flight_state_baseline.sql 整体取代 V1.0.0–V1.4.0:
  PIPELINE_LOCK/PROC_STATE/MSG_EVENT/REQ_TRACK/BACKFILL_TODO/FLIGHT_SCHD
  + 8 张资源明细表 + FLIGHT_ROUTE_POINT + SCHD_SNAP_LOG 留痕层
- 废除 FDAY 日代/SCHD_GEN/名单差删:OPERATION_DAY 不可变(应用层校验 +
  条件更新强化 §7.4),STATE 仅 ACTIVE/DELETED,物理清除只在历史归档后
- 处理器化:applyScheduleRecords(§5.1 七步同一事务,重放判定/整包
  DEAD(PROTOCOL)/归属冲突不落地)+ FLOP/FDEL/ADFT(tombstone 仅
  ACTIVE→DELETED,重复 FDEL 幂等不推进版本)
- 投递:KAFKA_SCHD 同 FLID 按最新 STATE_VERSION 合并,被压掉事件关闭,
  TOMBSTONE 发 null 值消息(键缺失=删除旧值 §7.3)
- 回填待办改为业务事务内预登记,消除提交后写待办的崩溃窗口(§7.2/§10)
- XML 解码改为 jackson-dataformat-xml 数据类直接映射(SIS 信封强类型,
  FLTR 开放标签泛型承载)
- 历史归档/物理清除顺序不可颠倒:归档确认成功集才物理删除,未接通删 0 条
- 移除 PUMP_JOB 队列/ReferenceService/FlightStoreDiffTool 等旧机制与测试,
  新增运营日/引擎/快照/FDEL/归档顺序不变性回归测试
2026-09-09 17:53:08 +08:00

307 lines
18 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- =====================================================================
-- 航班运行数据接入与当前状态管理 · 全量基线
-- ---------------------------------------------------------------------
-- 权威设计:docs/flight-state.md(审计定稿)。本脚本整体取代历史迁移
-- V1.0.0V1.4.0 已删除),按 §3.2 表职责建立全部分层:
-- · 决策层:FLIGHT_SCHD + 8 张资源明细表 + FLIGHT_ROUTE_POINT —— 承担正确性;
-- · 管道层:PIPELINE_LOCK / PROC_STATE / MSG_EVENT(outbox) / REQ_TRACK / BACKFILL_TODO
-- · 留痕层:SCHD_SNAP_LOG —— 只追加、不参与决策、可重建;
-- · 证据层:报文原文归档 —— 冷路径,尚未交付(ARCHIVE_KEY 仅留引用位)。
-- 核心定案(对照文档章节):
-- · 身份:FLID 主键;OPERATION_DAY 一经确定不可变(§3.1/§5.3,应用层校验);
-- STATE ∈ {ACTIVE, DELETED},无 ARCHIVED —— 物理清除只发生在历史归档成功之后(§8.2);
-- · 无名单差删:主链路无集合删除;删除入口只有 FDEL(§6.2)与历史归档(§8.2);
-- · 版本:每次成功写入推进 STATE_VERSIONKafka 判旧 = (FLID, STATE_VERSION, UPDATED_AT)(§7.3);
-- · 出站:COUTMSGS 是共享 MySQL 信箱(他人系统库,本系统不建表,迁移不覆盖)。
-- 类型口径:TIMESTAMP(6) WITH TIME ZONE 统一 UTC 语义;无 JSONB/CLOB 依赖;
-- BIGSERIAL 为 PostgreSQL 方言(Oracle 适配见 §10,未定前不预设)。
-- =====================================================================
-- ① 单行锁:串行化状态写事务(§1 边界:只串行化 DB 事务,不代替消息认领/选主/故障切换)
CREATE TABLE PIPELINE_LOCK (
LOCK_ID INT NOT NULL PRIMARY KEY, -- 恒为 1
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL
);
INSERT INTO PIPELINE_LOCK (LOCK_ID, UPDATED_AT) VALUES (1, now());
-- ② 处理伴生状态:与共享信箱 CMINMSGS 一一对应(MSG_ID = CMINMSGS_ID)。
-- 兼作快照重放判定(§5.1 步骤 2):MSG_ID 已有成功终态 → 重放,直接记幂等成功。
CREATE TABLE PROC_STATE (
MSG_ID BIGINT NOT NULL PRIMARY KEY,
STATE VARCHAR(16) NOT NULL, -- PENDING/FAILED/SUCCEEDED/SKIPPED/DEAD
IDENTITY_KEY VARCHAR(200), -- SNDR|TYPE|STYP|SEQNdecode 后首次绑定;SEQN 同会话顺序观测 §5.5)
ATTEMPTS INT NOT NULL DEFAULT 0,
NEXT_ATTEMPT_AT TIMESTAMP(6) WITH TIME ZONE,
ERROR_CLASS VARCHAR(20), -- MALFORMED/PROTOCOL/INFRA/UNSUPPORTED/EXHAUSTED(§9
LAST_ERROR VARCHAR(1000),
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
CONSTRAINT uk_proc_identity UNIQUE (IDENTITY_KEY)
);
CREATE INDEX idx_proc_head ON PROC_STATE (STATE, MSG_ID); -- 主泵队头查询(严格 FIFO
-- ③ 航班当前态主行:一行一 FLID(决策层权威;展示视图是投影,不是权威 §3.3)
CREATE TABLE FLIGHT_SCHD (
FLID VARCHAR(32) NOT NULL PRIMARY KEY, -- AODB 实例 IDNumber(1-12)SIS §3.16.2
OPERATION_DAY DATE NULL, -- 运营保障日;一经确定不可变(§3.5);NULL=尚未被快照收录
STATE VARCHAR(8) NOT NULL, -- ACTIVE/DELETED(§3.1,无第三态)
STATE_VERSION BIGINT NOT NULL DEFAULT 0, -- 每次成功写入 +1(§4
LAST_MSG_ID BIGINT NULL, -- 最近一次成功写入的消息 ID
-- ==== SCHD.FLTR 标量字段(值保持 AODB 字符串原样;缺失语义由处理层决定,§5.4)====
ALCD VARCHAR(64) NULL, -- 航空公司代码
ALSC VARCHAR(64) NULL, -- 航空公司简称
FLNO VARCHAR(64) NULL, -- 航班号(展示用,不参与身份判定 §3.1)
MVIN VARCHAR(64) NULL, -- 进离港标识(A/D
SODT VARCHAR(64) NULL, -- 计划运行时间(ddMMMyyHHmmOPERATION_DAY 计算源 §3.5
FLTY VARCHAR(64) NULL, -- 航班类型
FLIN VARCHAR(64) NULL, -- 国内/国际/混合
ACFT VARCHAR(64) NULL, -- 机型
RENO VARCHAR(64) NULL, -- 机尾号
TAOP VARCHAR(64) NULL, -- 过站实际承运人代码(§3.4:过站关联,非代码共享)
TAFL VARCHAR(64) NULL, -- 过站实际承运航班号
TAID VARCHAR(64) NULL, -- 过站关联航班 FLID
TRML VARCHAR(64) NULL, -- 航站楼
MAXP VARCHAR(64) NULL, -- 最大旅客数
CSOP VARCHAR(64) NULL, -- 共享承运人代码(§3.4
CSFT VARCHAR(64) NULL, -- 共享航班号
MAID VARCHAR(32) NULL, -- 共享主航班 FLID
ESTT VARCHAR(64) NULL, -- 预计时间
ACTT VARCHAR(64) NULL, -- 实际时间
STND VARCHAR(64) NULL, -- 备降站/机位
PHAG VARCHAR(64) NULL, -- 地服代理(值机)
CNCL VARCHAR(64) NULL, -- 取消时间(§8.1 历史判定依据)
REMC VARCHAR(256) NULL, -- 备注
BOTM VARCHAR(64) NULL, -- 摆渡车时间
LACL VARCHAR(64) NULL, -- 行李确认时间
FINT VARCHAR(64) NULL, -- 完成时间
APPT VARCHAR(64) NULL, -- 旅客到达时间
EGSR VARCHAR(64) NULL, -- 保障开始时间
EGST VARCHAR(64) NULL, -- 保障结束时间
FHAG VARCHAR(64) NULL, -- 地服代理(货运)
MHAG VARCHAR(64) NULL, -- 地服代理(机务)
VIPP VARCHAR(64) NULL, -- VIP 旅客数
VIPR VARCHAR(64) NULL, -- VIP 等级
LBNO VARCHAR(64) NULL, -- 行李件数
LBWT VARCHAR(64) NULL, -- 行李重量
PAXC VARCHAR(64) NULL, -- 旅客计数
EXSC VARCHAR(64) NULL, -- 例外代码
EXSR VARCHAR(256) NULL, -- 例外原因
FTSS VARCHAR(64) NULL, -- 航班状态
PEDT VARCHAR(64) NULL, -- 前序估计时间
NAAT VARCHAR(64) NULL, -- 到港终态时间(§8.1;业务含义待术语表确认 §10)
NEAT VARCHAR(64) NULL, -- 离港终态时间(§8.1;业务含义待术语表确认 §10)
PADT VARCHAR(64) NULL, -- 旅客登机时间
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL
);
CREATE INDEX idx_flight_schd_opday ON FLIGHT_SCHD (OPERATION_DAY);
CREATE INDEX idx_flight_schd_state ON FLIGHT_SCHD (STATE);
-- OPERATION_DAY 不可变的数据库层强化(§7.4):快照 upsert 一律带
-- WHERE OPERATION_DAY IS NULL OR OPERATION_DAY = :day,行级条件更新即满足;
-- 不使用触发器(Oracle/PG 双方言成本)。
-- ④ 资源明细表 ×8 + 路线点表(每 FLID 多行;明细集合按组先删后插 §3.3;
-- ORDINAL 保留输入顺序,SOURCE_SEQ 只存上游序号 §3.2
-- 删除一律标记在主行 STATE,明细物理清除只发生在历史归档 §8.2)
-- ④-1 登机门 GTDT
CREATE TABLE FLIGHT_GATE (
FLID VARCHAR(32) NOT NULL,
ORDINAL INT NOT NULL,
SOURCE_SEQ VARCHAR(64),
GATE VARCHAR(64),
PGOT VARCHAR(64), -- 计划登机开始
PGCT VARCHAR(64), -- 计划登机结束
GOTM VARCHAR(64), -- 实际登机开始
GCTM VARCHAR(64), -- 实际登机结束
GTYP VARCHAR(64),
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
PRIMARY KEY (FLID, ORDINAL)
);
-- ④-2 值机柜台 CKDT
CREATE TABLE FLIGHT_CHECKIN (
FLID VARCHAR(32) NOT NULL,
ORDINAL INT NOT NULL,
SOURCE_SEQ VARCHAR(64),
CHKC VARCHAR(64),
CCLS VARCHAR(64),
PCOT VARCHAR(64), -- 计划开柜
PCCT VARCHAR(64), -- 计划关柜
COTM VARCHAR(64), -- 实际开柜
CCTM VARCHAR(64), -- 实际关柜
CTYP VARCHAR(64),
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
PRIMARY KEY (FLID, ORDINAL)
);
-- ④-3 行李转盘 CLDT
CREATE TABLE FLIGHT_BELT (
FLID VARCHAR(32) NOT NULL,
ORDINAL INT NOT NULL,
SOURCE_SEQ VARCHAR(64),
BELT VARCHAR(64),
BCLS VARCHAR(64),
PCOT VARCHAR(64), -- 计划开转盘(转盘专属前缀,避免与柜台同名)
PCCT VARCHAR(64), -- 计划关转盘
FBAG VARCHAR(64), -- 首件行李
LBAG VARCHAR(64), -- 末件行李
BTYP VARCHAR(64),
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
PRIMARY KEY (FLID, ORDINAL)
);
-- ④-4 计划机位 PSDT
CREATE TABLE FLIGHT_STAND_PLAN (
FLID VARCHAR(32) NOT NULL,
ORDINAL INT NOT NULL,
SOURCE_SEQ VARCHAR(64),
PSST VARCHAR(64),
STST VARCHAR(64), -- 计划开始
STET VARCHAR(64), -- 计划结束
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
PRIMARY KEY (FLID, ORDINAL)
);
-- ④-5 滑槽 CHDT
CREATE TABLE FLIGHT_CHUTE (
FLID VARCHAR(32) NOT NULL,
ORDINAL INT NOT NULL,
SOURCE_SEQ VARCHAR(64),
CHUT VARCHAR(64),
CHCLS VARCHAR(64),
PCBT VARCHAR(64), -- 计划开始(SIS 线格式 PCBT
PCET VARCHAR(64), -- 计划结束(PCET
CBTM VARCHAR(64), -- 实际开始(CBTM
CETM VARCHAR(64), -- 实际结束(CETM
CHTYP VARCHAR(64),
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
PRIMARY KEY (FLID, ORDINAL)
);
-- ④-6 延误 DELY(业务上任意时刻仅 1 个有效延误,保留多行能力以无损承接)
CREATE TABLE FLIGHT_DELAY (
FLID VARCHAR(32) NOT NULL,
ORDINAL INT NOT NULL,
SOURCE_SEQ VARCHAR(64),
CODE VARCHAR(64),
STRT VARCHAR(64),
DURA VARCHAR(64),
REMC VARCHAR(256),
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
PRIMARY KEY (FLID, ORDINAL)
);
-- ④-7 靠撤桥 ABTM(桥号 ABDGA/D 各一条)
CREATE TABLE FLIGHT_BRIDGE_OP (
FLID VARCHAR(32) NOT NULL,
ORDINAL INT NOT NULL,
SOURCE_SEQ VARCHAR(64),
ABDG VARCHAR(64),
ABOP VARCHAR(64), -- A=靠桥 D=撤桥
AOTM VARCHAR(64), -- 动作时间
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
PRIMARY KEY (FLID, ORDINAL)
);
-- ④-8 轮挡 CHOT(机位 CHIDON/OFF 各一条)
CREATE TABLE FLIGHT_CHOCK_OP (
FLID VARCHAR(32) NOT NULL,
ORDINAL INT NOT NULL,
SOURCE_SEQ VARCHAR(64),
CHID VARCHAR(64),
CHST VARCHAR(64), -- ON/OFF
CHTM VARCHAR(64), -- 动作时间
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
PRIMARY KEY (FLID, ORDINAL)
);
-- ④-9 路线点 ROUT/ERUT 共用(ROUTE_KIND 区分 §3.210 类集合 9 张表)
CREATE TABLE FLIGHT_ROUTE_POINT (
FLID VARCHAR(32) NOT NULL,
ORDINAL INT NOT NULL,
SOURCE_SEQ VARCHAR(64),
ROUTE_KIND VARCHAR(8) NOT NULL, -- ROUT/ERUT
APCD VARCHAR(64), -- 机场代码
SCAT VARCHAR(64), -- 计划到达时间
SCDT VARCHAR(64), -- 计划出发时间
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
PRIMARY KEY (FLID, ROUTE_KIND, ORDINAL)
);
CREATE INDEX idx_flight_gate_flid ON FLIGHT_GATE (FLID);
CREATE INDEX idx_flight_checkin_flid ON FLIGHT_CHECKIN (FLID);
CREATE INDEX idx_flight_belt_flid ON FLIGHT_BELT (FLID);
CREATE INDEX idx_flight_stand_flid ON FLIGHT_STAND_PLAN (FLID);
CREATE INDEX idx_flight_chute_flid ON FLIGHT_CHUTE (FLID);
CREATE INDEX idx_flight_delay_flid ON FLIGHT_DELAY (FLID);
CREATE INDEX idx_flight_bridge_flid ON FLIGHT_BRIDGE_OP (FLID);
CREATE INDEX idx_flight_chock_flid ON FLIGHT_CHOCK_OP (FLID);
-- ⑤ 统一投递事件 outbox(§7.3KAFKA_MSG 只通知变化;KAFKA_SCHD 发整态;
-- tombstone 仅在 ACTIVE→DELETED 时与删除同事务登记,投递失败持续重试)
CREATE TABLE MSG_EVENT (
EVENT_ID BIGSERIAL PRIMARY KEY,
TARGET VARCHAR(30) NOT NULL, -- KAFKA_MSG / KAFKA_SCHD
PARTITION_KEY VARCHAR(32) NOT NULL, -- 恒为 FLID
EVENT_TYPE VARCHAR(16) NOT NULL DEFAULT 'UPSERT', -- UPSERT / TOMBSTONE
STATE_VERSION BIGINT NOT NULL, -- 发布时航班版本;聚合按 FLID 取最新(§7.3)
PAYLOAD_JSON TEXT NOT NULL, -- TOMBSTONE 时至少含 FLID/STATE_VERSION/DELETED
STATE VARCHAR(16) NOT NULL, -- PENDING/SENT/DEAD
ATTEMPTS INT NOT NULL DEFAULT 0,
NEXT_ATTEMPT_AT TIMESTAMP(6) WITH TIME ZONE,
ERROR_CLASS VARCHAR(20),
LAST_ERROR VARCHAR(1000),
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL
);
CREATE INDEX idx_evt_head ON MSG_EVENT (TARGET, STATE, EVENT_ID); -- 每 target 队头
CREATE INDEX idx_evt_flid ON MSG_EVENT (PARTITION_KEY, STATE_VERSION); -- 同 FLID 未发事件合并
-- ⑥ 请求状态机(§7.1:只有 RESP 完成 RQFD 请求,按(运营日、发送方、请求类型)
-- 匹配最新一条 PENDING;同类请求只留一条有效,新请求置旧为 EXPIRED)
CREATE TABLE REQ_TRACK (
REQ_ID BIGSERIAL PRIMARY KEY,
REQ_TYPE VARCHAR(20) NOT NULL,
OPERATION_DAY DATE NOT NULL, -- 请求覆盖运营日
SENDER VARCHAR(64) NOT NULL, -- 请求发送方(匹配键之一)
STATE VARCHAR(16) NOT NULL, -- PENDING/SENT/DONE/EXPIRED
COUTMSGS_ID BIGINT,
SENT_AT TIMESTAMP(6) WITH TIME ZONE,
COMPLETED_AT TIMESTAMP(6) WITH TIME ZONE,
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL
);
CREATE INDEX idx_req_open ON REQ_TRACK (REQ_TYPE, OPERATION_DAY, SENDER, STATE);
-- ⑦ 共享信箱回填补偿待办(§7.2:提交后回填;回填失败不得把 SUCCEEDED 改回 FAILED
-- 目标形态 = 业务事务内预登记,消除「提交后写待办」的崩溃窗口,§10 当前偏差)
CREATE TABLE BACKFILL_TODO (
MSG_ID BIGINT NOT NULL PRIMARY KEY,
SNDR VARCHAR(64) NOT NULL,
TYPE VARCHAR(32) NOT NULL,
STYP VARCHAR(32),
SEQN BIGINT,
ATTEMPTS INT NOT NULL DEFAULT 0,
NEXT_ATTEMPT_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
LAST_ERROR VARCHAR(512),
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL,
UPDATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL
);
CREATE INDEX idx_backfill_todo_due ON BACKFILL_TODO (NEXT_ATTEMPT_AT);
-- ⑧ SCHD 快照留痕(§5.5):事务外追加,只追加留痕、不参与决策;一行=一次尝试,重放也记;
-- RESULT 与 FLAGS 分列(可「成功且告警」);写失败只记指标;保留 90 天,按 (SCOPE_END, RECV_AT) 清理
CREATE TABLE SCHD_SNAP_LOG (
LOG_ID BIGSERIAL PRIMARY KEY,
MSG_ID BIGINT NOT NULL,
RECV_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL, -- 接收时刻(UTC
SCOPE_START DATE NOT NULL, -- 报文覆盖运营日范围(单日时两者相等)
SCOPE_END DATE NOT NULL,
RECS INT NOT NULL, -- 报文声明记录数
UPSERTED INT NOT NULL, -- 实际写入数
DURATION_MS BIGINT NOT NULL,
RESULT VARCHAR(20) NOT NULL, -- COMMITTED/REPLAY_SKIPPED/ROLLED_BACK
FLAGS VARCHAR(200) NOT NULL DEFAULT '', -- 逗号分隔:EMPTY/RECS_DROP/SEQN_REGRESSION/DAY_MISMATCH/SCHD_REVIVE_CONFLICT
ARCHIVE_KEY VARCHAR(200), -- 原文归档引用(证据层,尚未交付)
CREATED_AT TIMESTAMP(6) WITH TIME ZONE NOT NULL
);
CREATE INDEX idx_snaplog_cleanup ON SCHD_SNAP_LOG (SCOPE_END, RECV_AT);
CREATE INDEX idx_snaplog_msg ON SCHD_SNAP_LOG (MSG_ID);