docs: add shadow v3 field operations package

This commit is contained in:
zgw
2026-09-03 17:08:13 +08:00
parent 169b64850d
commit 47190451ff
8 changed files with 748 additions and 249 deletions

View File

@@ -1,166 +1,89 @@
# FT546WMS 现场影子测试操作手册
# FT546WMS 影子 v3 现场操作手册
## 1. 适用范围
## 1. 这次部署做什么
本手册用于分支 `test/ft546wms-shadow-from-main-20260811` 的现场测试。该分支基于远端稳定版本:
目标分支:`test/ft546wms-shadow-v3-20260903`。
```text
origin/main = 916ac6bda32a5b102a3181cc8c5dbd5319c5656d
影子 v3 只观察算法建议,不改变 Legacy 分配结果。入库、自动出库、手动出库仍由原存储过程执行一次,原返回码、返回消息、库位和异常保持不变。正常业务请求只做固定大小的内存登记,不等待影子线程,也不在调用线程执行影子数据库、文件或同步日志操作。
影子后台会读取业务表,并且只写 `alg.*` 对象。它可能增加数据库 CPU 和 I/O,因此仍需低峰部署、监控和随时回滚。
## 2. 固定安全边界
- 现场只允许一个 FT546WMS JVM,稳定版和影子版不能同时运行。
- 仓库固定为 `01`;原始数据中的 `1` 与 `01` 等价,`W02` 只用于诊断,不能覆盖配置。
- SQL Server 必须使用 Windows 集成认证;脚本不接收用户名和密码。
- 当前现场已有 v2 包,安装必须使用 `upgrade`,不能使用 `clean`。
- v2 到 v3 升级保留 `alg.decision_log`;发现未知 `alg` 对象、清单不完整或 manifest 不匹配时脚本会停止。
- 影子失败、过期、并发、超时、配置错误或输入缺失均 fail-open:Legacy 继续,影子样本作废。
- 不执行正式 ACTIVE 切换,不增加 WCS/PDA/理库/预留/回放功能。
## 3. 部署前准备
现场负责人先记录:
- SQL Server 名称和数据库名;
- 当前 v2 测试开始时间和时区;
- IDEA 当前 Run Configuration;
- 当前稳定实例 PID 和端口;
- 本次交付给出的精确 v3 提交号 `<V3_COMMIT>`;
- 应用日志目录。
部署前先导出现有 v2 证据。不要卸载 v2:
```cmd
cd /d C:\project\FT546WMS-SHANDOW
call scripts\shadow-v3-export.cmd C:\project\FT546WMS-SHANDOW "<SQL_SERVER>" "<DATABASE>" "<V2_START_UTC>" "C:\project\FT546WMS-v2-before-v3" "<LOG_DIR>"
```
影子算法只提出候选结果并记录比较数据。原有 Legacy 存储过程仍执行一次且仅执行一次,Legacy 的库位分配、返回码和响应内容始终是最终结果。
如果当前代码还没有 v3 导出脚本,先用既有导出方式保存 `alg.decision_log`、诊断结果、日志、分支和提交号,再继续。
影子模式仍会读取 Legacy 表,并会在 `alg` schema 中刷新读模型和写入决策日志。因此“只观察”表示不改变 Legacy 业务数据和决策权,不表示完全没有数据库 CPU、I/O 或执行时间开销。
## 4. 按顺序部署 v3
## 2. 安全边界
### 第一步:停止 IDEA 中的 v2 稳定实例
- 默认配置 `FORTUCKY_SHADOW_ENABLED=false`,未显式开启时不执行影子规划。
- 启用时只允许 `FORTUCKY_ALGORITHM_MODE=SHADOW`;误设 `ACTIVE` 或 `LEGACY` 会导致应用拒绝启动。
- 影子事务使用 `REQUIRES_NEW`、`READ_UNCOMMITTED` 和 3 秒超时,并且只在名为 `ft546-shadow-observer` 的 daemon 工作线程执行。
- 专用执行器只有一个线程、队列容量为 0,拒绝策略不会回落到 Legacy 请求线程;忙时其他观察立即跳过。
- Legacy 线程仅提交任务和通知内存结果,不等待影子规划或比较,也不执行任何影子数据库操作。
- 影子异常、超时、输入缺失和比较日志写入失败都会 fail-open,不跳过 Legacy 流程。
- 安装包不在 `dbo.bas_cargo_space`、`dbo.bas_stock`、`dbo.mydo_job` 或其他 Legacy 表上创建触发器。
- 安装包不对 Legacy 业务表执行 `INSERT`、`UPDATE`、`DELETE` 或 `MERGE`。
- 影子模式不调用预留、深位锁、理库、回放、移库完成、WCS 完成或 PDA 回调写入过程。
- `alg.reservation` 和 `alg.deep_workflow_lock` 是规划器读取兼容表;影子包不安装修改它们的过程,SHADOW 模式也禁止进入这些写入口。
记录停止时间,在 IDEA 点 Stop。用下面命令确认最多只有一个相关 JVM,最好为 0:
## 3. 交付文件
```text
fortucky-algorithm/src/main/resources/db/sqlserver/install-shadow.sql
fortucky-algorithm/src/main/resources/db/sqlserver/diagnostics-shadow.sql
fortucky-algorithm/src/main/resources/db/sqlserver/uninstall-shadow.sql
```cmd
jps -lv | findstr /I "RuoYiApplication FT546WMS"
```
只使用名称带 `-shadow` 的脚本。该分支已移除原算法通用的 `install.sql`、`diagnostics.sql` 和 `uninstall.sql`,避免现场误装 ACTIVE 数据库对象。
停止和重新启动之间会有一次短暂停机,这是计划内中断。不要同时启动两个实例来消除停机,否则可能重复执行定时任务、消费或外部回调。
## 4. 上现场前必须完成的演练
### 第二步:同步精确分支和提交
1. 在现场数据库的最近备份副本上启动远端 `origin/main`,完成一次入库和一次出库基线测试。
2. 在备份副本执行 `install-shadow.sql`,确认脚本全部成功。
3. 用影子分支完成同样的入库和出库,确认业务结果仍来自 Legacy。
4. 导出 `alg.decision_log`,然后停止影子程序并执行 `uninstall-shadow.sql`。
5. 再次启动远端 `origin/main`,重复基线测试。
未完成数据库副本演练,不要直接在现场生产库安装。
## 5. 准备两个独立 IDEA 工作区
当前开发机的本地 `main` 已与 `origin/main` 分叉,不能作为稳定版回滚源。先执行 `git fetch origin`,确认 `origin/main` 的提交号,再从远端提交准备只读稳定工作区。
在仓库主目录执行。目标目录必须不存在;如果已存在,先人工确认它的来源,不要覆盖或删除:
```powershell
```cmd
cd /d C:\project\FT546WMS-SHANDOW
git fetch origin
$ExpectedStableCommit = "916ac6bda32a5b102a3181cc8c5dbd5319c5656d"
$RemoteMainCommit = git rev-parse origin/main
if ($RemoteMainCommit -ne $ExpectedStableCommit) { throw "origin/main 已变化,停止部署并重新合并验证" }
$StableWorktree = "D:\workSpace\PROJECT_SPACE\FT546\FT546MWS\worktrees\stable-origin-main-20260811"
if (Test-Path -LiteralPath $StableWorktree) { throw "稳定版 worktree 目标目录已存在,请人工核对" }
git worktree add --detach $StableWorktree origin/main
$CheckedOutCommit = git -C $StableWorktree rev-parse HEAD
if ($CheckedOutCommit -ne $ExpectedStableCommit) { throw "稳定版 worktree 提交校验失败" }
if (git -C $StableWorktree status --porcelain) { throw "稳定版 worktree 不是干净状态" }
git switch test/ft546wms-shadow-v3-20260903
git pull --ff-only
git rev-parse HEAD
git status --porcelain
```
两个 IDEA 窗口分别打开:
`git rev-parse HEAD` 必须等于交付的 `<V3_COMMIT>`,`git status --porcelain` 必须没有输出。若不一致,停止部署。
```text
稳定版:D:\workSpace\PROJECT_SPACE\FT546\FT546MWS\worktrees\stable-origin-main-20260811
影子版:D:\workSpace\PROJECT_SPACE\FT546\FT546MWS\worktrees\shadow-from-main-20260811
### 第三步:执行只读预检
```cmd
call scripts\shadow-v3-preflight.cmd C:\project\FT546WMS-SHANDOW <V3_COMMIT> "<SQL_SERVER>" "<DATABASE>"
```
为两个窗口分别创建 Run Configuration:
只有看到 `PREFLIGHT_OK` 才能继续。预检检查分支、精确提交、干净工作树、main 祖先、JVM 数量、SQL 连接、v2/v3 manifest 和当前快照;它不修改数据库。
- `FT546WMS-STABLE-origin-main`:完全沿用当前稳定现场参数,不增加任何 `FORTUCKY_*` 环境变量。
- `FT546WMS-SHADOW`:复制稳定配置的 JDK、profile、端口、数据库和 Redis 参数,只增加下一节列出的环境变量。
### 第四步:升级数据库包
禁止同时运行两个实例。即使使用不同 HTTP 端口,两个 WMS 实例也可能重复执行定时任务、消费任务或发送外部回调。切换时必须先停止当前实例,确认进程退出和端口释放,再启动另一个实例。
当前现场是 v2,只执行:
## 6. 安装影子数据库包
### 6.1 安装前检查
由 DBA 对现场数据库做可恢复的完整备份,并记录备份文件、时间和恢复负责人。随后执行:
```sql
SELECT SCHEMA_ID(N'alg') AS alg_schema_id;
SELECT trigger_object.name AS trigger_name,
schema_name(trigger_object.schema_id) AS trigger_schema,
schema_name(parent_object.schema_id) AS parent_schema,
parent_object.name AS parent_table
FROM sys.triggers trigger_object
JOIN sys.objects parent_object ON parent_object.object_id = trigger_object.parent_id
WHERE trigger_object.is_ms_shipped = 0
ORDER BY parent_schema, parent_object.name, trigger_schema, trigger_object.name;
SELECT schema_name(object.schema_id) AS schema_name,
object.name AS object_name,
object.type_desc
FROM sys.objects object
WHERE object.is_ms_shipped = 0
ORDER BY schema_name(object.schema_id), object.type_desc, object.name;
```cmd
call scripts\shadow-v3-install.cmd "<SQL_SERVER>" "<DATABASE>" upgrade
```
预期 `alg_schema_id` 为 `NULL`。安装脚本发现任何既有 `alg` schema 会以错误 51000 拒绝执行。如果现场已经存在 `alg` schema 或同名对象,停止安装并先确认所有权;不要覆盖,也不要执行本分支卸载脚本。
只有全新测试数据库、确认没有 `alg` schema 时才允许使用 `clean`。现场生产库不要使用 `clean`。
把两份查询结果连同执行时间保存为安装前基线。现场可能已有 Legacy 自身的触发器,安装后的全库 DML 触发器集合必须与安装前完全一致;用户对象清单只能新增本包定义的 `alg.*` 对象。
### 第五步:设置 IDEA 环境变量
### 6.2 执行安装
在低业务量时段使用 SQL Server Management Studio 打开并执行:
```text
fortucky-algorithm/src/main/resources/db/sqlserver/install-shadow.sql
```
脚本使用 `GO` 分批执行并在当前会话设置 `READ_UNCOMMITTED`。首次安装会全量建立读模型,可能扫描较多现场数据;如果副本演练时间超出可接受窗口,现场不要继续。
也可以使用已配置 Windows 集成认证的 `sqlcmd`:
```powershell
sqlcmd -S "<SQL Server>" -d "<数据库>" -E -b -r1 -i "<仓库>\fortucky-algorithm\src\main\resources\db\sqlserver\install-shadow.sql"
```
不要把数据库密码写进脚本、IDEA Run Configuration 截图或命令历史。
### 6.3 安装后检查
重新执行安装前的两份元数据查询。全库 DML 触发器结果必须完全一致,用户对象清单只能新增预期的 `alg.*` 对象。保存安装后结果和执行时间,再执行:
```sql
SELECT schema_name(object.schema_id) AS schema_name,
object.name,
object.type_desc
FROM sys.objects object
WHERE schema_name(object.schema_id) = N'alg'
ORDER BY object.type_desc, object.name;
SELECT warehouse_id,
COUNT(*) AS lane_count,
MAX(rebuilt_at) AS latest_rebuild_at
FROM alg.lane_state
GROUP BY warehouse_id;
```
本次新增对象只能位于 `alg` schema;`lane_state` 应存在目标仓库的数据。如果安装部分失败,不要启动影子程序,也不要执行本分支卸载脚本:拒绝式卸载会因对象缺失而报错 51014。保留完整输出和安装前后对象清单,由 DBA 决定从备份恢复,或依据清单人工清理本次未完成安装。不要补写 manifest、补建空对象或修改卸载脚本来绕过保护;清理完成且 `SCHEMA_ID(N'alg')` 再次为 `NULL` 后,才能重新完整安装。
确认包标记唯一且版本准确:
```sql
SELECT package_id, package_version, installed_at
FROM alg.shadow_package_manifest;
```
必须只有一行:`FT546WMS_SHADOW_ONLY` / `2026-08-12-1`。不一致时不要启动影子程序,也不要手工修改标记。
## 7. IDEA 启用影子模式
在 `FT546WMS-SHADOW` 的 Environment variables 中设置:
在影子 Run Configuration 中使用:
```text
FORTUCKY_SHADOW_ENABLED=true
@@ -168,137 +91,101 @@ FORTUCKY_ALGORITHM_MODE=SHADOW
FORTUCKY_ALGORITHM_DATABASE_WRITES_ENABLED=true
FORTUCKY_ALGORITHM_WAREHOUSE_ID=01
FORTUCKY_SHADOW_TIMEOUT_SECONDS=3
FORTUCKY_ALGORITHM_LEGACY_FALLBACK_ON_TECHNICAL_ERROR=false
FORTUCKY_SHADOW_SNAPSHOT_MAX_AGE_SECONDS=60
FORTUCKY_SHADOW_QUIET_INTERVAL_MILLIS=1000
```
将 `01` 替换为现场实际仓库号。保持 `FORTUCKY_SHADOW_WAREHOUSE_ID` 未设置,使影子入口统一回退到 `FORTUCKY_ALGORITHM_WAREHOUSE_ID`。不要设置 replay、tidy、ACTIVE 或 WCS callback 相关变量。
不要设置 `ACTIVE`,不要添加数据库密码,不要设置 replay、tidy、reservation 或 WCS callback 开关。
`FORTUCKY_ALGORITHM_DATABASE_WRITES_ENABLED=true` 是影子读模型与 `alg.decision_log` 所必需的应用开关;当前影子代码路径只执行已安装的 `alg.*` 写入,它不把 Legacy 决策权交给算法。该开关不是数据库权限隔离,安全性还依赖本分支的 SHADOW 启动保护、删减后的 SQL 包和现场变更审计。
### 第六步:只启动一次影子实例
切换步骤:
在 IDEA 启动 v3。不要重复点击 Run。启动时后台会认领唯一实例并建立第一代快照;认领或刷新失败只会关闭影子可用性,不应阻止 Legacy 启动。
1. 记录稳定实例停止时间,停止 `FT546WMS-STABLE-origin-main`。
2. 确认 Java 进程退出、端口释放,且没有第二个 WMS 实例运行。
3. 启动 `FT546WMS-SHADOW`。
4. 如果出现 `Shadow observation requires ...`,不要修改保护条件,直接回滚到稳定实例。
5. 先做只读登录和查询冒烟检查,再由现场人员执行一笔受控入库和一笔受控出库。
6. 确认 Legacy 返回码、库位和现场设备动作与稳定流程一致。
7. 确认 `alg.decision_log` 出现 `INBOUND`/`OUTBOUND` 记录,并至少有受控业务出现相应的 `*_COMPARE` 记录。
启动后检查:
影子任务在 Legacy 前提交,但 Legacy 不等待后台线程。线程调度和数据库时序可能导致影子读取与 Legacy 写入重叠,甚至在 Legacy 写入后读取;影子结果不是严格的“Legacy 前快照”,分析时必须结合时间和业务结果解释。
单线程零队列执行器忙时,被跳过的请求不会调用算法,也没有对应的计划/比较决策日志;如果规划或 Legacy 超过观察期限,也可能只有计划日志而没有比较日志。Legacy 存储过程仍按原流程立即执行。这是保护业务延迟和数据库负载的预期行为,不要据此重放业务请求。
## 8. 观察与停止条件
应用日志中的以下文本表示后台影子已失败开放,Legacy 仍继续执行:
```text
Shadow inbound observation failed open
Shadow outbound observation failed open
Shadow inbound observation interrupted
Shadow outbound observation interrupted
Inbound shadow submission failed open
Project outbound shadow submission failed open
Exact-stock shadow submission failed open
```cmd
jps -lv | findstr /I "RuoYiApplication FT546WMS"
```
出现单条告警不等于 Legacy 失败,但应记录时间和业务单号。测试前由现场负责人和 DBA 根据稳定时段基线写下响应延迟、SQL CPU/I/O、锁等待、连接数和 Shadow 告警频率阈值;未约定阈值时,只允许少量受控业务,不进入连续观察。满足任一条件立即停止影子测试并执行第 10 节回滚:
只能看到一个 FT546WMS JVM。
- Legacy 入库或出库结果、返回码、消息或设备动作与稳定版不同;
- 正常接口达到预先约定的延迟阈值,或同类 3 秒超时告警重复出现;
- SQL Server CPU、I/O、锁等待或连接数出现不可接受增长;
- `alg` 之外出现任何由本次测试新增的表、过程、触发器或数据修改;
- 同一 Legacy 存储过程疑似被重复调用;
- WMS、WCS、PDA 或现场操作出现异常。
### 第七步:做只读和受控业务检查
实际进入影子规划的请求每次都会按仓库全量刷新读模型。应用在单个 JVM 内将观察周期上限限制为 1、队列容量为 0,其他并发观察立即跳过;这能限制重叠刷新,但 `READ_UNCOMMITTED` 和单并发都无法消除全表扫描带来的 CPU 和 I/O,所以必须从少量受控业务开始,不能直接长时间全量开放。若部署多个影子 JVM,该上限分别生效,现场仍只允许启动一个 WMS 实例。
先完成登录、页面查询等只读检查,再由现场人员执行一笔受控入库、一笔自动出库和一笔手动出库。确认:
## 9. 数据采集与交付
- Legacy 返回码、消息、库位和设备动作与稳定流程一致;
- 没有相同存储过程重复执行;
- `alg.shadow_snapshot_state` 为仓库 `01` 的 `PUBLISHED`;
- `alg.shadow_instance_heartbeat` 只有当前实例;
- `alg.decision_log` 出现新的计划/比较记录;
- 应用日志中的影子 warning 不包含业务载荷或异常消息。
测试开始和结束时各执行一次:
## 5. 立即停止条件
```text
fortucky-algorithm/src/main/resources/db/sqlserver/diagnostics-shadow.sql
出现任一情况立即执行第 7 节回滚:
- Legacy 结果、响应码、消息、库位或设备动作改变;
- 同一个 Legacy 存储过程疑似执行两次;
- 出现第二个 FT546WMS JVM;
- `alg` 之外出现本次部署造成的数据写入或新对象;
- WMS、WCS、PDA 或现场作业异常;
- 正常接口延迟或数据库 CPU、I/O、锁等待超过现场阈值;
- 快照长时间不是 `PUBLISHED`,或 `ERROR_*` 指标持续增长。
单条 `shadow_failure` 表示该影子样本失败开放,不等于 Legacy 失败;但必须记录时间并纳入分析。
## 6. 连续观察和七天导出
至少连续观察 7 天,覆盖正常业务高峰、入库、自动出库和手动出库。期间不要重放业务来补影子样本。
观察结束后运行:
```cmd
cd /d C:\project\FT546WMS-SHANDOW
call scripts\shadow-v3-export.cmd C:\project\FT546WMS-SHANDOW "<SQL_SERVER>" "<DATABASE>" "<V3_START_UTC>" "C:\project\FT546WMS-shadow-v3-export" "<LOG_DIR>"
```
在 SSMS 中选择“结果输出到文件”,保留完整结果。该脚本只读,包含对象清单、读模型统计、Legacy 表行数/校验和、当前锁和决策日志。Legacy 表校验和会扫描数据,只在低业务量时执行,不要高频轮询。
成功时显示 `EXPORT_OK`。输出目录包含:
测试结束、卸载之前单独导出原始决策记录:
- `deployment.txt`:分支、提交、工作树;
- `runtime-processes.txt`:JVM 进程;
- `environment-variable-names.txt`:仅环境变量名,不含值;
- `sql-diagnostics.txt`:manifest、快照、心跳、输入覆盖、阻塞;
- `comparison-detail.txt`:比较汇总和完整决策行;
- `runtime-metrics.txt`:准入、跳过、错误和时延桶;
- `inventory-parity.txt`:Legacy 与已发布快照库存差异计数;
- `shadow-warnings.txt`:日志目录中的结构化影子 warning。
```sql
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
把整个输出目录压缩后交给分析,不要包含密码、令牌或与测试无关的个人信息。只有七天数据通过分析后,才讨论正式切换;本分支本身不执行 ACTIVE 切换。
SELECT decision_id, warehouse_id, decision_type, input_version,
result_code, reason, created_at
FROM alg.decision_log
WHERE created_at >= '<测试开始时间>'
AND created_at < '<测试结束时间>'
ORDER BY created_at, decision_id;
## 7. 回滚
首选回滚只关闭影子,不卸载数据库对象:
1. 在 IDEA 停止 v3,记录停止时间;
2. 设置 `FORTUCKY_SHADOW_ENABLED=false`;
3. 完整重启一次;
4. 检查只有一个 JVM;
5. 做登录、查询、受控入库和出库冒烟检查。
更彻底的应用回滚是停止 v3,切回现场原稳定源码/提交并用原 Run Configuration 启动。无论哪种方式,都先恢复业务服务,再处理数据库对象。
`alg.*` 可以保留供取证,稳定 Legacy 不依赖它。不要把卸载当作紧急回滚步骤。
## 8. 可选卸载
只有满足全部条件才卸载:影子实例已停止、稳定服务已恢复、七天证据已导出并备份、DBA 已确认维护窗口。
```cmd
call scripts\shadow-v3-uninstall.cmd "<SQL_SERVER>" "<DATABASE>" CONFIRM_UNINSTALL
```
出库对比记录的 `reason` 会带出 `detail`、`project`、`product`、`tray`、`stock`、`snapshotSync`、`legacyMatches` 和 `shadowMatches`。其中 `legacyMatches` 是按 Legacy 有效库存条件计算的实时数量,`shadowMatches` 是影子快照中按项目/产品条件计算的数量;两者不一致时先检查快照同步时间,再判断业务映射。
卸载器只接受精确口令 `CONFIRM_UNINSTALL`,并由 SQL 包再次校验 v3 manifest 和完整对象白名单。发现未知/缺失对象时会在删除前停止。不要修改 manifest 或脚本绕过保护。
交付分析的数据包至少包括:
## 9. 自动化验证与残余风险
- 决策日志导出文件,保持原始列名和时间字段;
- `diagnostics-shadow.sql` 开始和结束两份结果;
- 应用日志中测试时间段的 Shadow 告警及其前后异常栈;
- 测试开始/结束时间、时区、仓库号、入库次数、自动出库次数、手动出库次数;
- 现场人员确认的 Legacy 最终库位、返回码及异常说明;
- 当前分支提交号和构建 JAR 的 SHA-256。
不要提供数据库密码、访问令牌或与分析无关的个人信息。
## 10. 快速回滚
### 10.1 首选:切回远端稳定源码
1. 停止 `FT546WMS-SHADOW`,记录停止时间。
2. 确认进程退出和端口释放。
3. 在独立稳定工作区启动 `FT546WMS-STABLE-origin-main`。
4. 执行登录、查询、受控入库和受控出库冒烟检查。
稳定版不引用 `alg.*`,因此应用回滚时无需立即卸载数据库对象。先恢复生产服务,再在维护窗口导出数据并卸载。
### 10.2 备用:仅关闭影子开关
如果稳定工作区暂时无法启动,可在影子 Run Configuration 中设置:
```text
FORTUCKY_SHADOW_ENABLED=false
```
然后完整重启应用。该方式保留影子分支代码,但所有影子入口会直接返回空观察结果。它不替代稳定版回滚,只用于临时恢复。
## 11. 完整卸载
仅在影子应用已停止、`alg.decision_log` 已导出且稳定版已恢复后执行。
使用 SSMS 打开并执行:
```text
fortucky-algorithm/src/main/resources/db/sqlserver/uninstall-shadow.sql
```
卸载脚本先校验包标记必须精确等于 `FT546WMS_SHADOW_ONLY` / `2026-08-12-1`,再校验 `alg` 顶层对象的名称和类型必须与本包白名单完全一致。发现未知对象、缺失对象、类型不符或标记不符时会在第一个 `DROP` 前拒绝执行,不删除任何对象。校验通过后才在事务内删除本分支拥有的 `alg` 过程、视图、表和 schema;失败会回滚,不修改 Legacy 业务行。执行后验证:
```sql
SELECT SCHEMA_ID(N'alg') AS alg_schema_id;
```
预期结果为 `NULL`。再次查询全库 DML 触发器集合,结果应与安装前保存的基线一致。
不要在影子应用运行时卸载。如果脚本报错 51011-51014,保存错误和对象清单,停止手工删除,由 DBA 判断恢复或清理方案。不要修改 manifest 来绕过保护。卸载后如需再次测试,必须重新执行完整安装和检查流程。
## 12. 已知残余风险
- 当前自动化验证是 Java 单元测试和 SQL 静态审计,不能替代真实 SQL Server 2016 副本演练。
- `READ_UNCOMMITTED` 可能读到业务事务的中间状态;该结果只用于影子比较,不参与 Legacy 决策。
- 零等待异步提交不保证严格的 Legacy 前置快照;影子读取可能与 Legacy 写入重叠或发生在其后。
- 3 秒事务超时会触发 fail-open,但 JDBC 取消和 SQL Server 回滚完成时间不保证严格等于 3 秒。
- 每次影子规划前的全量刷新可能增加数据库 CPU 和 I/O;现场必须监控并设置短测试窗口。
- JVM 内单线程零队列执行器只避免同一实例的重叠刷新,不限制其他进程或数据库会话;禁止同时运行稳定版和影子版,也禁止运行多个影子实例。
- 应用级 fail-open 能保护 Legacy 控制流,但不能消除数据库、网络或主机资源争用。
这些残余风险是采用“零 Legacy 触发器、每次规划前全量刷新”的代价,也是现场必须先小流量验证、随时可切回稳定源码的原因。
- 本地单元/静态测试不能替代 SQL Server 2016 备份副本演练。
- `READ UNCOMMITTED` 只用于观察,可能看到业务事务中间状态。
- 单线程容量一队列限制影子后台并发,但不能消除数据库资源竞争。
- 3 秒 worker 等待超时不等于 JDBC/SQL Server 一定在 3 秒内完成取消或回滚。
- 影子调用线程不等待后台,但主机和数据库资源竞争仍可能间接影响 Legacy,需要现场监控。

View File

@@ -0,0 +1,60 @@
# 给服务器 AI 的 FT546WMS 影子 v3 导出指令
把下面整段交给服务器上的 AI。先替换尖括号内容,不要把密码放进提示词。
```text
你在 Windows CMD 环境中操作 FT546WMS 影子 v3。你的任务只导出证据,不修改数据库、不切换分支、不重启服务、不卸载任何对象。
固定信息:
- 仓库目录:C:\project\FT546WMS-SHANDOW
- SQL Server:<SQL_SERVER>
- 数据库:<DATABASE>
- v3 测试开始 UTC:<V3_START_UTC,例如 2026-09-03T08:00:00>
- 应用日志目录:<LOG_DIR>
- 输出目录:C:\project\FT546WMS-shadow-v3-export
- 期望分支:test/ft546wms-shadow-v3-20260903
- 期望提交:<V3_COMMIT>
安全规则:
1. 只能使用 cmd.exe,不使用 PowerShell。
2. 数据库只能使用 Windows 集成认证,不询问、保存或输出密码。
3. 不执行 INSERT、UPDATE、DELETE、MERGE、TRUNCATE、DROP、ALTER、CREATE、EXEC。
4. 不运行 install、upgrade、uninstall,不停止或启动 IDEA/Java。
5. 任一步失败就停止,保留错误原文,不猜测、不绕过保护。
6. 不修改仓库文件,不执行 git checkout/switch/reset/clean/pull。
先在 CMD 执行只读核对:
cd /d C:\project\FT546WMS-SHANDOW
git branch --show-current
git rev-parse HEAD
git status --porcelain
jps -lv | findstr /I "RuoYiApplication FT546WMS"
必须满足:分支等于期望分支,HEAD 等于期望提交,git status 没有输出,相关 JVM 最多一个。否则停止并报告。
然后执行仓库自带的只读导出器:
call scripts\shadow-v3-export.cmd C:\project\FT546WMS-SHANDOW "<SQL_SERVER>" "<DATABASE>" "<V3_START_UTC>" "C:\project\FT546WMS-shadow-v3-export" "<LOG_DIR>"
必须看到 EXPORT_OK。随后只检查输出文件是否存在,不打开或改写内容:
dir /b C:\project\FT546WMS-shadow-v3-export
期望至少包含:
deployment.txt
runtime-processes.txt
environment-variable-names.txt
sql-diagnostics.txt
comparison-detail.txt
runtime-metrics.txt
inventory-parity.txt
shadow-warnings.txt
最后报告:
- 实际分支和提交号;
- JVM 数量;
- EXPORT_OK 是否出现;
- 输出目录;
- 文件名和大小;
- 任何错误。
不要在回复中粘贴环境变量值、数据库凭据或完整业务数据。不要压缩以外的改写;由现场人员把整个输出目录压缩后交给分析。
```