- 将主键从自增id改为GUID格式并添加格式校验 - 为service_mask添加表达式索引优化首位查询性能 - 更新相关文档说明改造方案与验证步骤 - 添加统计模块记录数据库写入与Kafka消费量 - 重构Redis心跳协议改用LIST类型存储项目状态 - 修复部署脚本中的服务名称不一致问题
3.1 KiB
3.1 KiB
DB 设计与 OpenSpec 符合性/偏差说明(v2)
本文件用于对照当前 OpenSpec 规范与本次 v2 数据库设计的符合性,并指出偏差与风险点。
1. 与 OpenSpec(当前主规格)的一致点
- 满足
openspec/specs/db/spec.md对“表结构初始化、批量写入、约束错误捕获、查询支持”等方向性要求。 - 本次变更已在提案增量规范中补充了“分区表/自动分区/高吞吐”相关要求:
openspec/changes/update-heartbeat-db-v2/specs/db/spec.mdopenspec/changes/update-heartbeat-db-v2/specs/kafka/spec.mdopenspec/changes/update-heartbeat-db-v2/specs/processor/spec.md
2. 偏差与风险(需要评估)
2.1 “主键仅 id” 与 PostgreSQL 分区约束冲突
- 需求写:主键为
id(GUID)。 - 现实现:
PRIMARY KEY (ts_ms, guid)(其中 guid 为 varchar(32))。
原因:PostgreSQL 分区表的主键/唯一约束通常需要包含分区键,否则无法在父表创建全局约束。
影响:
- 业务若强依赖“仅 guid 即主键”的语义,需要额外约定(例如只把 guid 当作全局唯一序列号使用,主键组合用于物理约束)。
2.2 “自动分区”实现方式
- 需求写:新分区可自动创建。
- 现实现:通过
heartbeat.ensure_partitions(start_day, end_day)预创建分区(安装时默认创建昨天~未来 7 天)。
原因:在单条 INSERT 语句执行过程中对分区父表执行 CREATE TABLE .. PARTITION OF 会触发 PostgreSQL 的“对象正在被当前查询使用”的限制(已在冒烟测试中复现)。
建议:
- 运维/服务启动时每天调用一次
heartbeat.ensure_partitions(current_date, current_date + N)预建未来分区。 - 如环境允许,可用
pg_cron等机制定时执行。
2.3 数据库“中文排序规则”约束的实现方式
- 需求写:数据库排序规则使用适合中文环境的配置。
- 现状:我们不新建数据库,而是在既有库(默认 log_platform)建表;该库的数据库级 collation 可能不是中文。
可行方案:
- 若仅少数字段需要中文排序(通常是 text/varchar):可创建 ICU collation 并在列级/查询级使用(不要求重建数据库)。
- 若要求“整个数据库默认 collation 为中文”:只能通过重建数据库实现(你明确不希望这么做,则建议采用 ICU/列级 collation 的折中方案)。
2.4 枚举 CHECK 约束偏保守
- 需求写:各 int 字段添加合理 CHECK,限制取值范围。
- 现实现:采用“非负 + 类型上界”的保守范围,避免未来枚举扩展导致写入失败。
建议:
- 在枚举标准明确后,将约束收紧为
IN (...)或更小区间。
3. 结论
- 结构、分区、索引均已按 v2 脚本落地并通过冒烟测试。
- 两个主要“需求严格字面”不完全满足点:
- 中文 collation(当前 DB 为 en_US.utf8)
- 主键仅 id(分区表限制导致采用 ts_ms + id)
若你希望我下一步把这些偏差也强制满足(例如重建 DB + 调整主键策略/使用其他分区方案),我可以继续改脚本并提供迁移/回滚方案。