协议实体字段定时变更追踪:寻求Event Sourcing之外的简化方案
替代Event Sourcing的简便方案
1. 版本化实体表+生效时间字段
直接在实体表给每一次字段变更存一条版本记录,每条记录带这些信息:
- 实体ID(关联对应的协议)
- 所有字段的当前值(存全量比只存变更字段更方便后续查询)
- 生效起始时间(
effective_start) - 生效结束时间(
effective_end,初始设成9999-12-31这种无限远的时间)
当更新字段并指定生效时间时:
- 先找到当前正在生效的版本(就是
effective_end等于9999-12-31的那条),把它的effective_end改成新版本effective_start的前一天(如果是精确到时分秒就改成前一秒) - 插入一条新的版本记录,把指定的生效时间设成
effective_start,effective_end还是设成无限远,字段值填更新后的内容
查询的时候:
- 要拿当前日期的正确值?就筛选
effective_start <= 当前日期 AND effective_end >= 当前日期的记录就行 - 要查某个时间区间的历史值?筛选
effective_start <= 区间结束日期 AND effective_end >= 区间开始日期的记录,按需展示所有版本或者去重
这种方案直接用SQL就能搞定,不需要额外搞事件存储和快照重建,开发维护成本低,适合中小规模的业务场景。
2. 变更日志表+当前状态表
拆成两张表来做:
- 当前状态表:专门存协议实体的最新生效状态(或者当前日期对应的生效状态),方便快速查当前值
- 变更日志表:记录每一次字段变更的细节,包括:
- 实体ID
- 变更的字段名
- 变更前的值
- 变更后的值
- 指定的生效时间
- 变更操作的时间(可选)
更新字段的时候:
- 先往变更日志表里插一条记录
- 如果生效时间是当前或者过去,直接更新当前状态表的对应字段;如果是未来时间,可以整个定时任务到点再更新,或者查询的时候动态计算当前应该用哪个值
查历史值的时候:
- 按时间区间筛选变更日志表的记录,结合当前状态表回溯出指定时间点的字段值;也可以在变更日志表里维护版本链,方便快速回溯
这种方案兼顾了当前查询的速度和历史追踪的需求,比Event Sourcing轻量很多,适合需要快速拿到当前状态的场景。
3. 用支持时态特性的数据库
如果用的数据库支持时态功能(比如PostgreSQL的时态扩展、SQL Server的系统版本时态表),直接靠数据库原生功能就能实现字段的时间追踪:
- 创建系统版本时态表,数据库会自动帮你维护每条记录的生效时间区间
- 更新字段时,数据库自动把旧版本标记成历史记录,保留好生效时间
- 查询的时候直接用时态查询语法,就能拿到指定时间点或者区间的历史值
这种方案几乎不用写额外的业务代码,全靠数据库搞定,是最省事的方案之一,但前提是数据库支持时态特性,要是换数据库的话成本可能有点高。
比起Event Sourcing,这些方案都不用维护事件流和快照重建的逻辑,开发复杂度低很多,查询也更直接,适合那些不需要复杂事件溯源的业务需求。
内容的提问来源于stack exchange,提问作者Andrius
相关产品推荐
相关产品推荐

