2. 核心概念:数据库 Schema、API 契约、版本号语义化(SemVer)、向前兼容与向后兼容
在构建数据库迁移与 API 版本对齐的体系时,必须首先统一四个核心概念的语言。它们是整个蓝图的地基:数据库 Schema 定义了数据的静态结构;API 契约 约定了服务间的交互边界;语义化版本号 提供了可计算的演进规则;兼容性方向 决定了迁移是否安全。下面逐一拆解。
2.1 数据库 Schema:数据的静态骨架
数据库 Schema 是对数据库结构的形式化描述,包括表、列、数据类型、约束、索引、视图、存储过程等。在迁移语境中,Schema 是“源”与“目标”之间的差异度量单位。
| Schema 元素 | 示例 | 变更影响 |
|---|---|---|
| 表结构 | CREATE TABLE users (id INT, name VARCHAR) |
增删列、修改类型、调整约束 |
| 索引 | CREATE INDEX idx_email ON users(email) |
查询性能变化,不改变数据语义 |
| 约束 | FOREIGN KEY (dept_id) REFERENCES dept(id) |
引用完整性规则变化 |
| 视图/存储过程 | CREATE VIEW active_users AS ... |
逻辑层抽象变化,可能影响上游查询 |
实践要点: 每次迁移都应生成一份 Schema 差异清单(diff),作为版本号变更的输入依据。只改索引不增删列,通常只需补丁版本;增删列则至少需要次版本。
2.2 API 契约:服务间的正式约定
API 契约是服务提供方与消费方之间的双边协议,通常以 OpenAPI(Swagger)、gRPC Proto、GraphQL Schema 或 JSON Schema 等形式定义。契约包含:端点路径、请求参数、响应结构、错误码、认证方式。
在数据库迁移场景中,API 契约是“保护层”——它决定了数据库 Schema 的变化能否被安全地暴露给客户端。如果契约不变,数据库 Schema 的变更必须被封装在服务内部;如果契约必须变,则版本号必须升级。
关键原则: 数据库 Schema 是内部实现,API 契约是外部承诺。两者可以不同步,但每次 API 版本变更都必须有对应的数据库 Schema 版本作为支撑。
2.3 版本号语义化(SemVer):可计算的演进规则
语义化版本号(SemVer)采用 MAJOR.MINOR.PATCH 格式,为每个版本赋予明确的兼容性含义。在数据库迁移与 API 对齐的上下文中,SemVer 的语义需要映射到 Schema 和契约的变化类型。
| SemVer 段 | 数据库 Schema 变化 | API 契约变化 | 升级动作 |
|---|---|---|---|
| MAJOR | 删除列、修改列类型、破坏性约束变更 | 删除端点、修改请求/响应结构(不兼容) | 必须同步升级,客户端需改造 |
| MINOR | 新增列(可空或有默认值)、新增索引 | 新增端点、新增可选字段 | 向后兼容,客户端可逐步升级 |
| PATCH | 修改注释、调整索引类型、性能优化 | 修复文档、调整错误消息 | 完全透明,无需客户端配合 |
常见陷阱: 只改数据库不改 API 版本号,或只改 API 版本号不改数据库版本号,都会导致版本信息失真。建议采用双版本号追踪:数据库 Schema 版本 + API 契约版本,两者独立演进但通过迁移脚本关联。
2.4 向前兼容与向后兼容:两个方向的安全网
兼容性方向是迁移决策的核心判断依据。两个方向的定义常被混淆,这里给出精确区分:
- 向后兼容(Backward Compatible): 新版本的消费者可以正确处理旧版本提供者返回的数据。即:新客户端 → 旧服务 能正常工作。
- 向前兼容(Forward Compatible): 旧版本的消费者可以正确处理新版本提供者返回的数据。即:旧客户端 → 新服务 能正常工作。
在数据库迁移中,向后兼容通常更容易实现(只加不减、只扩不缩);向前兼容则要求服务端在返回新字段时,旧客户端能忽略未知字段(如 JSON 的 additionalProperties 或 Protobuf 的字段编号预留)。
2.5 四个概念的关系矩阵
将上述四个概念整合到一个关系矩阵中,可以快速判断一次迁移的风险等级:
| 场景 | Schema 变化 | 契约变化 | SemVer 建议 | 兼容性 | 风险 |
|---|---|---|---|---|---|
| 新增可空列 | MINOR | 无变化 | MINOR / PATCH | 向后兼容 | 低 |
| 新增必填列 | MINOR | MINOR(新增字段) | MINOR | 向后兼容 | 中 |
| 删除列 | MAJOR | MAJOR(删除字段) | MAJOR | 破坏性 | 高 |
| 修改列类型(如 INT→BIGINT) | MAJOR | MAJOR(类型变更) | MAJOR | 破坏性 | 高 |
| 新增索引 | PATCH | 无变化 | PATCH | 完全透明 | 极低 |
核心结论: 数据库 Schema 的每一次变更,都应该映射到 API 契约的版本号上。使用 SemVer 作为共同语言,用向后兼容和向前兼容作为安全边界,才能构建可审计、可回滚的迁移体系。