← 返回题目列表

历史表和审计日志表应该怎么设计?

高频 中等 第 6 / 33 题 更新于 2026/07/28
数据库设计历史表审计日志数据追踪

简化版

历史表记录业务对象随时间变化的版本,审计日志记录谁在什么时候做了什么操作。历史表偏业务状态追溯,审计表偏操作追责和安全合规;设计时要记录主键、版本、变更前后值、操作人、操作时间、来源和请求 ID。

详细版

历史表常见字段:

id
biz_id
version
valid_from
valid_to
snapshot_json
created_at

审计日志常见字段:

id
actor_id
action
resource_type
resource_id
before_data
after_data
request_id
ip
created_at

设计要点:

  • 历史表要能还原某个时间点的数据状态;
  • 审计表要能回答谁、何时、从哪里、对什么做了什么;
  • 日志表通常只追加不更新;
  • 大量日志要分区、归档或进入日志系统;
  • 敏感字段要脱敏或加密。

完整版教学

一、历史表和审计表目标不同

历史表回答的是:这个业务对象过去是什么状态?

审计表回答的是:谁对这个对象做了什么操作?

比如商品价格从 100 改到 80,历史表关心价格版本;审计表关心哪个管理员、通过哪个后台页面、在什么时间做了修改。

二、历史表要能还原状态

历史表常见两种方式:

  • 快照式:每次变更保存整份对象快照;
  • 差异式:只保存变更字段和前后值。

快照式恢复简单,但占空间;差异式节省空间,但恢复某个时间点状态需要从多个变更合并。

业务重要、字段不太大的对象,快照式更稳;变更频繁且对象很大时,可以考虑差异式或混合方式。

三、版本和有效期很关键

历史表最好有版本号或有效期:

version
valid_from
valid_to

这样可以回答“2026 年 7 月 1 日这份合同条款是什么”。如果只有一堆更新时间,没有有效期模型,回溯查询会很痛苦。

四、审计日志要保留操作上下文

审计日志不只是保存变更内容,还要保存上下文:

  • 操作人;
  • 操作类型;
  • 资源类型和资源 ID;
  • 请求 ID;
  • IP 和设备信息;
  • 操作入口;
  • 变更前后值;
  • 操作时间。

请求 ID 特别有用,它能把应用日志、网关日志、数据库审计串起来。

五、审计日志通常只追加

审计日志的可信度来自不可随意修改。通常设计成只追加,不更新,不物理删除,或者删除也要有更高权限和留痕。

如果审计日志也能被普通业务随便改,那它就失去了追责价值。

六、数据量和敏感信息要提前考虑

审计和历史数据增长很快。设计时要考虑:

  • 按时间分区或分表;
  • 定期归档;
  • 冷热存储;
  • 查询索引;
  • 敏感字段脱敏;
  • 合规保留期限。

比如 before_dataafter_data 里不能随便明文存身份证、银行卡、密码哈希等敏感信息。

还有一个容易被忽略的点是索引数量。审计表常见查询是按 resource_type + resource_id 查某个对象的操作轨迹,或按 actor_id + created_at 查某个人的操作记录;不要给 JSON 大字段随意建索引。数据量达到千万级后,过多索引会让追加写入、归档和分区维护都变重。

七、常见误区与追问

设计目标历史表审计日志表
核心问题某个时间点对象是什么状态谁在什么时候做了什么
常见粒度业务对象版本一次操作或一次请求
查询方式biz_id + version/valid_time 回溯按操作人、资源、请求 ID 追踪

易错点:历史表和审计表可以同时存在。历史表偏“状态复原”,审计表偏“行为追责”,不要用一张流水表硬扛所有问题。

举个数字例子:一个商品每天改价 3 次,保存 365 天历史,快照式历史表大约是 3 * 365 = 1095 条版本记录;如果每份快照 2KB,大约 2MB 多,换来任意时间点恢复很划算。但如果对象快照是 200KB 且每分钟变更,差异式或字段级变更日志就更合适。

  • 误区:有了审计日志就不需要历史表。 审计日志能说明操作过程,但未必方便恢复某个时间点的完整业务状态。
  • 误区:历史表只存变更后的值就够了。 只存后值会让对比、回滚和责任判断变困难,关键字段通常要能看到前后变化。
  • 误区:审计日志可以随业务记录一起更新。 审计日志的可信度来自追加和留痕,随意更新会削弱追责价值。
  • 追问:快照式和差异式怎么选? 字段少、恢复要求高选快照式;对象大、变更频繁选差异式或混合式。
  • 追问:为什么要存 request_id? 它能把审计表、应用日志、网关日志、链路追踪串起来,定位一次操作的完整上下文。
  • 追问:敏感字段如何处理? 密码、证件号、银行卡等不要明文进审计日志,通常要脱敏、加密、哈希或只记录字段发生过变化。

八、加强记忆

历史表管“状态怎么变”,审计表管“谁做了什么”。历史表要有版本和有效期,审计表要有操作人、资源、前后值、请求 ID 和时间。两者通常只追加,并且要考虑归档、分区和敏感字段保护。