数据库审计字段应该如何设计?created_by、updated_by、deleted_at 有什么用?
简化版
审计字段用于回答“谁在什么时候创建、修改、删除了数据”。常见字段包括 created_at、created_by、updated_at、updated_by、deleted_at、deleted_by。普通表可放基础审计字段,关键业务还要配操作日志或变更历史表。
详细版
审计字段不是摆设,它服务于排障、追责、合规和数据恢复。基础设计:
created_at、created_by:创建时间和创建人。updated_at、updated_by:最后更新时间和修改人。deleted_at、deleted_by:软删除时间和删除人。version:并发控制或变更版本。- 关键变更写审计日志表,记录变更前后内容。
要注意系统任务、第三方回调、管理员操作都要有操作者语义,不能只有用户 ID。
完整版教学
一、审计字段回答的是可追溯问题
数据库不是只负责存当前值。很多线上问题都要回到几个问题:这条数据是谁创建的、什么时候改的、为什么被删、哪个系统任务触发了变更。
如果没有审计字段,排查只能翻应用日志。但日志可能过期、分散、不易关联。把基础审计信息放在数据表中,可以让最常见的追溯问题直接从数据库回答。
记忆钩子:审计字段的价值不是展示,而是出问题时能还原现场。
二、基础审计字段要统一命名
常见基础字段包括创建、更新和删除三组。命名应全库统一,不要一张表叫 create_time,另一张表叫 gmt_create,第三张表叫 createdAt。
created_at timestamp not null,
created_by bigint null,
updated_at timestamp not null,
updated_by bigint null,
deleted_at timestamp null,
deleted_by bigint null
统一命名方便 ORM 自动填充、后台通用组件展示、数据同步和治理。字段语义统一,比字段名个人偏好更重要。
三、created_by 和 updated_by 不一定都是用户
很多系统默认操作者是用户 ID,但真实变更来源可能是管理员、系统任务、外部回调、数据修复脚本。只放一个 user_id 可能表达不全。
可以引入操作者类型:
operator_type: user / admin / system / callback
operator_id: 具体 ID
operator_name: 快照名称
简单系统可以只用 created_by、updated_by,复杂系统则在操作日志里记录更完整的操作者上下文,包括 IP、User-Agent、请求 ID。
四、updated_at 只能表示最后一次变化
updated_at 很有用,但它只能保存最后一次更新时间。它无法告诉你字段变更历史,也无法回答“状态从 A 变成 B 的时间线”。
比如商品价格从 99 改到 129,再改到 109,主表只剩 109 和最后更新时间。想知道历史价格,就需要变更日志或历史表。
主表:保存当前状态
审计日志:保存每次操作
历史表:保存关键版本快照
所以审计字段和审计日志不是替代关系,而是粗粒度与细粒度的关系。
五、软删除字段要和查询约束配合
deleted_at 和 deleted_by 常用于软删除。软删除后数据仍在表里,便于恢复和审计,但所有普通查询都要默认过滤删除数据。
where deleted_at is null
软删除还会影响唯一约束。比如用户名删除后是否允许复用,要在唯一索引设计里考虑。否则会出现“页面看不到这个名字,但创建时提示已存在”的体验问题。
六、关键业务要有审计日志表
对于金额、权限、配置、审批这类关键业务,只靠 updated_at 和 updated_by 不够。应该记录操作日志或变更明细。
| 字段 | 含义 |
|---|---|
biz_type | 业务类型 |
biz_id | 业务 ID |
action | 操作类型 |
before_value | 变更前 |
after_value | 变更后 |
operator | 操作者 |
request_id | 请求链路 ID |
审计日志可以较大,通常按时间分区、归档或进入日志平台。它的目标不是高频业务查询,而是追溯和合规。
七、常见误区与追问
- 误区:有 created_at 和 updated_at 就算完整审计。 它们只提供基础时间,关键业务还需要操作者和变更明细。
- 误区:updated_by 一定是用户 ID。 系统任务、外部回调、管理员脚本也会改数据,需要操作者类型。
- 误区:软删除只加 deleted 字段即可。 还要处理默认过滤、唯一约束、恢复和归档。
- 追问:审计日志会不会太大? 会,所以通常按业务重要性记录,配合分区、归档和冷热存储。
- 追问:before/after 存 JSON 可以吗? 可以用于审计,但核心查询字段仍应结构化,JSON 主要用于追溯。
- 追问:created_at 用应用时间还是数据库时间? 要全系统统一;很多团队用数据库默认时间或服务端统一时间,关键是避免混用。
八、面试中可以这样落地
普通业务表统一加基础审计字段,ORM 或数据访问层自动填充。关键表再加操作日志,记录变更前后内容和请求链路。
create table audit_log (
id bigint primary key,
biz_type varchar(64) not null,
biz_id bigint not null,
action varchar(64) not null,
before_value json null,
after_value json null,
operator_type varchar(32) not null,
operator_id varchar(64) null,
created_at timestamp not null
);
如果是权限、金额、审批配置,强调审计日志不可随意删除,并要有查询和归档策略。
九、加强记忆
审计字段记住“谁、何时、做了什么、能否恢复”。基础字段解决当前记录追溯,操作日志解决历史变更追溯,软删除解决误删恢复和合规保留。面试时把系统任务、外部回调这类非用户操作者补上,答案会更完整。