Scert/doc/构建版本与数据库支持矩阵.md

302 lines
26 KiB
Markdown
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.

# 构建版本与数据库支持矩阵
核查日期:2026 年 9 月 27 日。本文区分代码支持、隔离测试和正式生产准入,不把驱动存在视为兼容性验收。
## 一、工具链与依赖
| 项目 | 当前固定来源 | 当前核查值 | 发布要求 |
|---|---|---|---|
| Go | `backend/go.mod`、`backend/go.sum` | 模块内 `go1.26.6 windows/amd64` | 在模块内记录实际版本,不使用仓库根目录的版本推断 |
| 工具链选择 | `go env GOTOOLCHAIN` | `auto` | 自动选择仍必须与模块要求一致,不得降低版本绕过失败 |
| Node.js | `frontend/package.json` 的 `engines`、`devEngines`,锁文件 | `v24.19.0` | 精确匹配,升级需同步声明并重跑测试和构建 |
| npm | 同上,另有 `packageManager` | `11.17.0` | 精确匹配,使用锁文件安装;Windows 使用 `npm.cmd` |
| Vue | `frontend/package.json`、`frontend/package-lock.json` | `3.5.41` | 直接依赖固定精确版本,声明及锁文件必须一致 |
| Vite | 同上 | `6.4.3` | 同上 |
| Vue 构建插件 | 同上 | `5.2.4` | 同上 |
| SQLite Go 驱动 | `backend/go.mod` | `modernc.org/sqlite v1.37.0` | 驱动版本不等于数据库引擎版本 |
| MySQL Go 驱动 | 同上 | `github.com/go-sql-driver/mysql v1.9.3` | 不代表 MySQL 所有服务端版本均通过验收 |
| PostgreSQL Go 驱动 | 同上 | `github.com/jackc/pgx/v5 v5.9.2` | 同上 |
| 编译目标 | `build/build-release.ps1` | `windows/amd64`、`linux/amd64` | 核心二进制 `CGO_ENABLED=0`、`-trimpath` |
核查命令:
```powershell
cd backend
go version
go env GOVERSION GOTOOLCHAIN GOOS GOARCH
go mod verify
go test -p 1 -count=1 -timeout=3m ./...
go vet -p=1 ./...
cd ../frontend
node --version
npm.cmd --version
npm.cmd ci
npm.cmd test
npm.cmd run build
```
历史基线只验证过现有依赖;随后 P0-03 已在 `fab98d1` 独立克隆重新执行 `npm ci`、150 项前端测试和双平台候选构建。该次安装仍有脚本批准策略警告,不能证明安装脚本被禁止。P0-04 改为明确禁用依赖安装脚本,执行证据持续记录在《Scert整改任务执行清单.md》,不能将旧安装结果当作新策略验证。
### 构建机与安装策略
| 项目 | 固定基线或约束 | 验收边界 |
|---|---|---|
| 当前 Windows 构建机 | Windows 11 Home China,系统 `10.0.26200`,amd64;Windows PowerShell 5.1 | 记录实际值,不把系统显示名称误写成内核版本;系统更新后需重新验收 |
| Linux 原生构建机 | 脚本允许 Linux amd64,但尚无本批指定发行版、内核、PowerShell 版本的原生构建证据 | 不宣称 Linux 原生可重复构建已通过;Linux 候选包由 Windows 交叉编译 |
| 目标平台 | `windows/amd64`、`linux/amd64`,`CGO_ENABLED=0`、`-trimpath`、`-mod=readonly` | 构建机版本与生产运行系统分别记录 |
| 安装脚本 | `.npmrc` 固定 `ignore-scripts=true`,正式入口再显式传参 | npm 未审查警告不是安全保证,禁止白名单和全量放行 |
| 可选平台包 | `npm ci` 显式包含开发和可选依赖 | esbuild 不执行安装脚本,使用锁文件中的平台包;外部二进制覆盖被拒绝 |
| 发布追溯 | `manifest.json` 的 `build_environment` | 包含实际工具链、系统、直接前端依赖、安装策略和五份输入文件 SHA256;Go 驱动及依赖由模块文件哈希追溯 |
| 源码换行 | `.gitattributes` 固定文本 LF,二进制自动识别并保留 | 覆盖用户 `core.autocrlf` 差异;原目录不强制重写,正式验证使用干净克隆 |
正式发布入口自动校验工具链、核验 Go 模块缓存、按锁文件干净安装,并在构建结束后复核输入文件。环境不符时尽早失败;构建中版本文件漂移则不生成发布清单。`toolchain.mjs` 和配套测试属于正式构建代码,不作为替代真实部署的辅助验收脚本。具体流程见 `build/README.md`。
## 二、数据库支持矩阵
| 数据库 | 预期定位 | 代码现状 | 本轮验证 | 尚未满足的正式验收 |
|---|---|---|---|---|
| SQLite | 单机、开发、轻量部署 | 驱动、初始化、迁移 1~9、CLI 备份恢复 | 临时独立库从版本 0~9 升级、重复迁移、非法历史和新版数据库拒绝 | 并发读写/锁、服务重启、完整业务数据升级恢复 |
| MySQL 5.7.44 | 历史兼容目标,仍保留实现 | 独立方言、迁移、连接恢复、InnoDB 快照、生成列备份及官方存储对象 SQL 恢复 | `e6e6719`:85 个叶子用例通过,含既有回归、特殊列双向互操作和存储对象恢复;详见第九、十节 | 自有导出的对象完整性、更多 SQL 模式、独立发行命令、Linux 实库、Web 初始化及生产系统验证 |
| MySQL 8.0.45 | 正式生产支持目标 | 同上,额外处理不可见列实际数据 | 同候选独立实库 87 个叶子用例通过,未复用 5.7 的结果 | 同上;不代表 8.0 全部补丁版本已经验证 |
| PostgreSQL | 正式生产支持目标,实际服务端版本待本轮复核 | 独立方言、迁移 1~9、严格 TLS 和官方备份恢复工具接入 | 文件/嵌入/登记一致性、凭据/TLS 单元测试 | 当前版本真实集群、初始化、升级、失败回滚、备份恢复和业务回归 |
正式支持目标不等于已经生产放行。旧文档中的 PostgreSQL 实机记录仅作为线索,不替代当前候选版本复测。本批 MySQL 测试自行初始化 loopback 独立实例,不连接本机已有服务或生产数据库;PostgreSQL 当前候选实库测试未执行。
## 三、迁移与降级边界
1. 三种数据库必须提供相同编号和名称的迁移,SQL 内容允许因方言不同而不同。
2. `migration_catalog_test.go` 检查源码目录、嵌入资源和 `latestMigrationVersion`;新增文件忘记登记或嵌入时必须失败。
3. `Migrate` 在执行后续迁移前读取完整有序版本历史;版本高于程序支持范围或历史不连续时拒绝启动,不自动删除或修补版本记录。
4. MySQL 的 DDL 重入和 PostgreSQL 的事务回滚必须用对应引擎验证,不能通过文件数量一致推断行为一致。
5. 当前不存在通用向下迁移承诺。降级须使用兼容程序及对应已验证备份,在隔离环境验证后再操作,禁止通过删除 `schema_migrations` 绕过拒绝。
## 四、真实实例验收步骤
每个数据库和声明支持的服务端版本独立执行以下步骤,保存版本、候选提交、命令退出码和脱敏证据:
1. 建立明确归属的隔离空库和最小权限账户,验证 TLS 与主机身份;不使用现有业务库。
2. 按正式初始化入口完成配置;创建用户、域名、DNS 账户、服务器和任务,验证权限隔离。
3. 从支持的旧版本数据库升级,检查数据、索引、默认值、归属和任务状态;重复执行不产生额外变更。
4. 注入迁移中断,在恢复后确认重入/回滚;新版数据库被旧程序拒绝且原数据保持不变。
5. 按该数据库的 CLI 备份恢复流程在另一隔离空库恢复;验证敏感配置和证书关联,篡改备份必须拒绝。
6. 重启服务验证持久化,完成前后端业务回归;记录未执行、跳过和失败项,不汇总为通过。
MySQL/PostgreSQL 没有当前实机证据的格子保持待验收。本矩阵不授权清理共享数据库或同机其他服务。
## 五、MySQL 隔离迁移正式回归
测试入口为 `backend/internal/database/mysql_integration_test.go`;同目录的 `mysql_integration_helpers_test.go` 适配共享夹具 `backend/internal/testsupport/mysqltest/server.go`,供数据库和 CLI 正式 Go 测试复用,不需要辅助脚本,也不进入生产程序依赖。未显式提供程序目录时显示跳过,不得把常规 `go test ./...` 的结果当作实库通过。
本批 Windows 实际命令如下,两个版本分别执行;产物根可复用,但测试每次创建全新数据目录,不复用业务库:
```powershell
Set-Location D:\Desktop\Scert\backend
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\mysql-matrix-20260927'
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\5.7\bin'
go test -count=1 -v -timeout=8m -run '^TestMySQLRealMigrations$' ./internal/database
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\8.0\bin'
go test -count=1 -v -timeout=8m -run '^TestMySQLRealMigrations$' ./internal/database
```
安全和覆盖边界:
1. 只接受绝对程序及产物目录,不接受外部 DSN;使用 `--no-defaults`,不会读取既有实例配置。数据库管理命令只作用于本次创建的随机端口与数据目录。
2. 初始化不开放监听;首次启动在接收连接前设置随机密码。运行时仅绑定 loopback,强制 TLS,验证 CA 和 IP 身份;8.0 的额外 X 协议关闭。
3. 迁移使用库级业务账户,不用管理账户替代最低权限检查;测试保留管理账户仅用于创建隔离库和正常关闭自己的进程。
4. 每个历史起点及每个 DDL 中间状态升级后,比较表引擎、字段类型、默认值、字符集及全部索引。此比较证明升级结构与全新迁移一致,不单独证明业务设计本身完全正确。
5. 冷重启用例关闭应用连接池、停止数据库、重启后重新打开连接。保留旧池的独立在线恢复测试见第六节,不能用冷重启结果代替。
6. 测试正常结束会停止自己的进程,清空初始口令文件,保留日志和数据目录;产物已被 Git 忽略。非正常终止后应先核对具体进程归属,禁止批量停止所有 MySQL。
7. 本批不是发布包部署、Web 初始化、备份恢复、Windows Service 或 Linux 运行验收;PostgreSQL 和 SQLite 剩余矩阵不得据此标记通过。
## 六、MySQL 在线连接池恢复
正式入口:`backend/internal/database/mysql_recovery_integration_test.go`;复用第五节隔离夹具。两个版本分别设置程序目录后运行:
```powershell
go test -count=1 -v -timeout=8m -run '^TestMySQLReal(Migrations|PoolRecovery)$' ./internal/database
```
实现和行为边界:
1. 锁定的 MySQL 驱动在 Windows 上没有有效的空闲套接字检查。复用连接之前通过驱动的 `SessionResetter` 增加一次有界 `COM_PING`;Linux 保留驱动原有检查,不增加这次往返。
2. 单次探测最多 2 秒;调用者更短的截止时间或取消优先。探测失败关闭连接并返回 `driver.ErrBadConn`,让连接池在发送业务语句之前更换连接。
3. 完整保留驱动的查询、写入、预编译、事务、参数转换和连接校验接口。不包装业务执行及提交错误,不新增 SQL 或事务重放逻辑。
4. `checkConnLiveness` 默认开启;显式关闭时不启用上述额外检查,不保证失效空闲连接上的首次请求成功。连接仍可能在探测成功后断开,应用必须处理执行错误及提交结果不确定性。
5. 成本是 Windows 每次复用池连接时增加一次协议往返;同一已取得的事务连接内部不重复探测。当前没有远距离网络性能基准,不以 loopback 测试推断生产延迟。
新增 7 个实库场景每个使用单独业务库:保留旧池并重启数据库后的首次写入、空闲断线后的预编译语句、首次查询及迁移、无符号整数参数及正常提交、只读事务与正常回滚、活动事务连接中断、数据库不可用时有界失败并恢复。每次故障后的数据值均验证,避免把重复写入或未提交数据当作恢复成功。
`mysql_pool_test.go` 另行验证健康探测、驱动拒绝、探测失败、截止时间、取消、写入前更换连接,以及查询、写入和提交响应不确定时保留原错误且不重放。响应丢失场景是驱动接口层故障注入,不声称已完成真实网络丢弃提交确认包的演练。
候选 `9cf3a3b` 在 Windows 的 MySQL 5.7.44、8.0.45 均为 55 项子测试通过,0 失败、0 跳过。产物位于 `artifacts/mysql-matrix-20260927/mysql57-9cf3a3b.log` 和 `mysql80-9cf3a3b.log`,不纳入源码。Linux 数据库测试包交叉编译通过,但没有执行 Linux 实库恢复;其门禁仍然保留。
## 七、MySQL 基本备份恢复与指定失败回滚
候选 `7bfd400`;正式入口为 `backend/internal/cli/mysql_integration_test.go` 和 `mysql_commands_integration_test.go`,复用严格 TLS、随机账户、全新实例的共享夹具。
修复前在 5.7.44 的真实数据库上复现两类错误:禁用空闲连接后,会话变量跨 SQL 语句丢失;DECIMAL 文本字节被作为十六进制数值恢复,出现数值越界。修复固定恢复连接,并依据字段类型导出精确文本;旧 DECIMAL 备份没有自动转换,应重新生成并验证备份。
新增测试覆盖:
1. `MaxIdleConns=0` 时,记录并比较同一恢复脚本中的真实连接编号。
2. 两种空闲连接配置下,恢复子表在前、父表在后的关联数据,核对中文、特殊字符、二进制、DECIMAL、NULL、微秒时间和自增;恢复后外键仍生效。
3. 无效 SQL 前的写入保留,失败后的写入不执行;提前取消不修改当前数据库。底层导入函数不承诺事务原子性,整库回滚由正式恢复命令负责。
4. 同进程调用正式备份和恢复命令,先执行完整 MySQL 迁移,再验证成功恢复、SQL 导入失败后的回滚、证书恢复失败后的回滚;检查业务行、审计行、配置文件、加密凭据、证书文件和恢复前快照。
重跑原有 55 项及新增 10 项的命令如下。两个版本分别设置程序目录,产物根每次生成独立数据目录:
```powershell
Set-Location D:\Desktop\Scert\backend
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\mysql-restore-session-20260927'
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\5.7\bin'
go test -json -p 1 -count=1 -timeout=8m -run '^TestMySQLReal' ./internal/database ./internal/cli
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\8.0\bin'
go test -json -p 1 -count=1 -timeout=8m -run '^TestMySQLReal' ./internal/database ./internal/cli
```
JSON 日志保存为 `artifacts/mysql-restore-session-20260927/mysql57-7bfd400.jsonl`、`mysql80-7bfd400.jsonl`,不纳入源码。
候选最终复测结果如下,均为 0 失败、0 跳过;子测试计数包含两种连接池场景及其嵌套用例:
| 实际版本 | 数据库包 | CLI 包 | 通过子测试 |
|---|---:|---:|---:|
| MySQL 5.7.44 | 43.949 秒 | 11.350 秒 | 65 |
| MySQL 8.0.45 | 51.125 秒 | 16.803 秒 | 65 |
最终 8 个隔离测试实例均已退出,对应端口无监听;原有 MySQL 进程保持不变,全部初始化口令文件为空。保留目录中的测试数据、随机测试密钥和日志仅作为本地忽略产物,不提交或分发。
本批边界与剩余门禁:
- TLS 注册名只存在于测试进程,正式命令测试是同进程调用,不是独立发行二进制验收。Linux CLI 测试包仅交叉编译,未在 Linux 运行。
- 本节候选尚无跨表统一一致性快照;后续 InnoDB 数据快照见第八节,并发 DDL 一致性仍不承诺。
- 视图、触发器、生成列、更多 SQL 模式与对象清单完整性仍须验证,不能把已测试表类型扩展为任意 MySQL 对象支持。
- 当前仍使用自有 SQL 导出;官方工具互操作、独立 CLI、完整生产业务及服务重启验收必须补齐。PostgreSQL、SQLite 和其他 44 项整改不因本批局部通过而缩减。
## 八、MySQL 跨表快照与备份失败边界
跨表快照候选为 `8d742fe`;取消锁等待与失败边界候选为 `73df576`。正式测试入口是 `mysql_snapshot_integration_test.go`、`mysql_backup_failure_integration_test.go`,均位于 `backend/internal/cli/`,复用第五节的隔离夹具;没有新增辅助验收脚本。
### 实现与复现
1. 备份枚举表、读取表结构和数据使用同一只读可重复读事务。数据快照在首次一致性读取时建立,不声称事务开始瞬间已建立快照;外部并发 DDL 仍须禁止。
2. 跨表测试锁住第二张表,等首表已导出后依次更新两张表,再解锁并恢复到另一个空库。数据库状态依次为 `(0,0)`、`(1,0)`、`(1,1)`;原实现恢复为从未出现的 `(0,1)`,现实现两种连接池配置均恢复为 `(0,0)`。
3. 取消测试也使用同一真实锁边界。修复前客户端已经返回取消,但首表的后续 DDL 在 5 秒内不能取得锁。备份现在仅对自己的会话执行 `SET SESSION lock_wait_timeout = 5`;双版本实测取消后约 5 秒释放本场景阻塞,未修改全局值。
4. 该限制针对单次元数据锁获取,不是整个备份的 5 秒执行期限,不为任意查询、多个锁等待或任意网络故障承诺统一取消完成时间。备份遇到锁超时直接失败,不重放事务;维护期间需要排除外部 DDL。
5. 当前只允许 InnoDB 基础表;MyISAM 和视图明确失败,避免静默声称一致性备份。拒绝只是当前安全边界,不能将对象完整性任务标记完成。
6. 成功发布前结束事务、同步并关闭临时文件、检查取消再重命名。失败只清理本次独占创建的临时文件;原有目标文件、其他操作占用的临时文件和目录内容不被修改。
### 新增正式回归
| 场景 | 子测试数 | 关键断言 |
|---|---:|---|
| 跨表并发写入快照 | 2 | 两种空闲连接配置;真实导出并恢复后两表均为原快照 |
| MyISAM、视图 | 2 | 明确拒绝;不替换原有备份,不遗留本次临时文件 |
| 首表导出后取消 | 2 | 保留取消错误;分别验证无目标文件和已有目标文件;首表 DDL 恢复可执行 |
| 首表导出后 SQL 中断 | 2 | 管理连接仅中断已确认的本次备份语句;保留错误 1317,文件与锁收尾正确 |
| 元数据锁等待超时 | 2 | 自然触发错误 1205;不靠测试解锁促成返回,文件与锁收尾正确 |
| 临时文件冲突 | 1 | 保留已有目标及其他操作的临时文件 |
| 重命名发布失败 | 1 | 非空目录占用目标时返回发布错误,目录内容保留,本次临时文件清理 |
其中跨表快照为上一批新增 2 项,本批失败边界新增 10 项;加此前 65 项,最终每版 77 项。统计口径仍包含既有嵌套子测试,不将父级包成功再加一次。
### 最终候选证据
在 `backend/` 执行,两个版本各运行一次,明确提供程序目录,不接受跳过结果:
```powershell
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\mysql-backup-boundaries-20260927'
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\5.7\bin'
go test -json -p 1 -count=1 -timeout=8m -run '^TestMySQLReal' ./internal/database ./internal/cli |
Tee-Object -FilePath '../artifacts/mysql-backup-boundaries-20260927/mysql57-73df576.jsonl'
# 换为 E:\DB\8.0\bin,输出文件换为 mysql80-73df576.jsonl,再执行相同测试。
```
| 实际版本 | 数据库包 | CLI 包 | 通过子测试 | 失败 / 跳过 |
|---|---:|---:|---:|---:|
| MySQL 5.7.44 | 44.591 秒 | 41.001 秒 | 77 | 0 / 0 |
| MySQL 8.0.45 | 53.844 秒 | 51.178 秒 | 77 | 0 / 0 |
常规 `go test -count=1 ./...`、`go vet ./...`、`go mod verify` 通过。Linux CLI 测试包仅交叉编译成功,未作实库运行。最终复测创建 12 个隔离实例,连同复现和定向测试,本批目录共 18 个实例;全部正常退出,已记录端口无监听,初始化口令文件为空,共享 MySQL 进程不变。数据目录、随机测试密钥、日志和二进制均被忽略,不提交或分发。
剩余验收明确保留:触发器、生成列、例程、事件和视图等对象的完整性;官方工具互操作与独立发行 CLI;磁盘写满、同步失败和掉电等更广泛文件系统故障;Linux 实库、完整 Web 业务和服务部署;PostgreSQL、SQLite 剩余矩阵。本批不得替代这些证据,也不得据此关闭 P0-05 或全部 44 项目标。
## 九、生成列、不可见列与官方工具双向互操作
代码候选 `f260b22`,修改前检查点 `e9bc156`。正式测试为 `TestMySQLRealOfficialInteroperability`,共享调用代码位于 `backend/internal/testsupport/mysqltest/tools.go`,没有使用临时辅助验收脚本。
- 修复生成列被显式写入恢复语句,以及 `SELECT *` 遗漏不可见列的问题;只读取可写列,并保留只有生成列的表的实际行数。
- 修复仅有生成列时扫描指针长度错误导致的越界。
- 源数据、恢复数据以及表、列、索引的实际元数据分别核对;不以 `SHOW CREATE TABLE` 中等价的显式字符集写法差异误判结构变化。
- 5.7.44 验证基础值、混合生成列和仅生成列表的双向互操作;8.0.45 额外验证不可见列的非默认实际值。
- 官方工具从当前测试服务端的程序目录读取,检查版本系列;使用 `VERIFY_IDENTITY`,随机密码仅通过子进程环境传递。继承的 `MYSQL*` 环境和用户登录文件均隔离,未改写官方导出内容。
- 本机两个版本的默认扩展插入导出,在仅生成列表上实证出现无效 SQL;正式测试明确使用 `--skip-extended-insert`,该选项下双向恢复通过,不把默认选项记为通过。
最终专项证据:
| 实际版本 | 数据库包 | CLI 包 | 通过测试记录(含父项) | 叶子用例 | 失败 / 跳过 |
|---|---:|---:|---:|---:|---:|
| MySQL 5.7.44 | 47.670 秒 | 45.554 秒 | 90 | 81 | 0 / 0 |
| MySQL 8.0.45 | 54.469 秒 | 57.907 秒 | 92 | 83 | 0 / 0 |
文件:`artifacts/mysql-pending-review-20260927/review-mysql57.jsonl`、`review-mysql80.jsonl`。这里明确区分父子测试记录总数与叶子用例,不把嵌套父项重复算成独立场景。后端常规测试、静态检查、模块校验通过;本批没有执行 Linux 实库或生产部署。
这只完成已列出的表和列类型的双向互操作,不能据此宣布视图、触发器、例程、事件、任意 SQL 模式及完整对象清单均受支持。P0-05 继续为 `[~]`。
## 十、官方存储对象 SQL 的分隔符恢复
修改前检查点 `6707059`,代码候选 `e6e6719`。本批处理的是官方导出文件到 Scert 恢复的方向,**没有把 Scert 自有导出改为完整存储对象备份**。
### 故障与修复
- 在隔离 MySQL 5.7.44 中实证:有效官方导出文件遇到 `DELIMITER` 时,旧恢复实现返回 1064。该指令用于客户端拆句,不应发送给数据库。
- 解析器现在识别独立行上的分隔符切换,支持本批验证的 `;;`、`$$`、`//`;保留复合语句内部的分号、带引号的内容和可执行版本注释。
- 支持 UTF-8 BOM、CRLF、大小写与前导空白。无效分隔符、未闭合引号或块注释返回错误,并且不返回可执行的部分语句。
- 恢复仍使用单一数据库连接;数据库错误立即返回,不跳过错误、不提升权限、不切换连接重放。词法预检不等于完整 SQL 语义验证,也不宣称全部 DDL 可事务回滚。
### 正式测试范围
`TestMySQLRealOfficialStoredPrograms` 使用同版本的官方 `mysqldump --routines --events` 生成文件,文件未经改写,分别交给官方 `mysql` 和 Scert 恢复到全新隔离库。
1. 验证两个同表触发器的定义与执行顺序,插入新行后核对 `(4 + 2) * 3 = 18` 和中文标签。
2. 验证存储过程、函数的定义、参数、返回类型、字符集、排序规则、定义者、SQL 模式和安全上下文;实际调用并核对结果。
3. 验证禁用事件的定义、计划、时区及保留策略;仅在本测试实例中启用事件调度,并在目标库显式修改为两秒后的单次计划,检查实际执行且源库未变化。不是对生产数据库或机器共享实例开启调度。
4. 使用没有对象管理权限的独立账户恢复同一文件,检查 1142、1227 或 1419 权限错误返回,且不继续恢复后面的例程。
5. 无效分隔符出现在建表语句之后时,检查恢复拒绝整个词法输入,目标库仍无任何表。
每个版本运行 4 个新增叶子场景;常规单元测试另外覆盖分隔符、注释、转义、换行和无效输入。
### 权限和 SQL 模式边界
- 不改写 `DEFINER`,本批源库和两个恢复库使用同一隔离账户。跨账户、跨服务器定义者及跨库引用的迁移仍未验收。
- 5.7 工具读取例程需要相应系统元数据权限,本夹具只在独立实例给测试账户授予 `mysql.proc` 读取权限。
- 8.0 实例启用二进制日志时,函数创建实证返回 1419;本夹具只给该实例的专用测试账户授予所需 `SUPER`,没有启用 `log_bin_trust_function_creators`,也没有给实际业务账户扩权。
- 本机 5.7 官方导出会移除对象 SQL 模式中的 `NO_AUTO_CREATE_USER`,官方恢复对照也出现同样变化。本批正式用例明确创建于 `STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION`,源、官方恢复及 Scert 恢复的元数据严格相等;不把默认模式或任意 SQL 模式记为通过。
- `NO_BACKSLASH_ESCAPES` 等其他词法模式、恢复已启用事件时的调度隔离和对象安全语义,仍需独立验证。
### 复测结果与证据
在 `backend` 目录执行:
```powershell
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\mysql-stored-programs-20260927'
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\5.7\bin'
go test -json -p 1 -count=1 -timeout=8m -run '^TestMySQLReal' ./internal/database ./internal/cli |
Tee-Object -FilePath '../artifacts/mysql-stored-programs-20260927/mysql57-review.jsonl'
# 将程序目录换为 E:\DB\8.0\bin,输出文件换为 mysql80-review.jsonl,再执行相同测试。
```
| 实际版本 | 数据库包 | CLI 包 | 通过测试记录(含父项) | 叶子用例 | 失败 / 跳过 |
|---|---:|---:|---:|---:|---:|
| MySQL 5.7.44 | 45.980 秒 | 59.816 秒 | 95 | 85 | 0 / 0 |
| MySQL 8.0.45 | 60.495 秒 | 72.856 秒 | 97 | 87 | 0 / 0 |
PowerShell 5.1 的 `Tee-Object` 文件使用 UTF-16,复核时用 `Get-Content -Encoding Unicode`。后端全量 `go test -count=1 ./...`、`go vet ./...`、`go mod verify` 通过;Linux CLI 测试包交叉编译通过但未运行,前端未修改、未重测。
本批复现、定向和全量测试共创建 22 个隔离实例,均已退出;全量测试记录的端口无监听,22 份初始化口令文件均为空,机器原有三个共享 MySQL 进程保持不变。数据、随机测试密钥、日志和编译文件仅留在忽略目录,没有提交。
### 尚未完成
Scert 自有导出仍需补齐触发器、例程、事件及视图,验证可见权限与完整对象清单,防止对象遗漏;本批导入能力不能证明导出完整。独立发行 CLI、Linux 实库、完整 Web 业务、服务重启和正式生产部署仍未验收。PostgreSQL、SQLite 和全部 44 项整改范围不变,P0-05 保持 `[~]`。