← 返回题目列表

软删除和硬删除怎么选?软删除表应该如何设计?

高频 中等 第 8 / 33 题 更新于 2026/07/28
数据库设计软删除硬删除数据生命周期

简化版

硬删除是直接删除物理记录,简单但不可恢复;软删除是用 deleted_atis_deleted 标记记录已删除,便于恢复、审计和保留历史。软删除要处理唯一约束、查询默认过滤、数据膨胀、归档清理和误把删除数据查出来的问题。

详细版

软删除适合:

  • 用户可恢复的数据;
  • 有审计、合规、追踪要求;
  • 其他表仍需要引用历史记录;
  • 删除只是业务状态变化。

硬删除适合:

  • 临时数据、缓存数据、中间表;
  • 法规要求必须彻底删除;
  • 数据没有历史价值;
  • 已经归档且确认不再使用。

软删除字段常见设计:

deleted_at datetime null
deleted_by bigint null
delete_reason varchar(...)

相比 is_deleteddeleted_at 同时表达“是否删除”和“何时删除”,信息量更高。

完整版教学

一、删除不是一个纯技术动作

业务里的删除可能代表很多含义:

  • 用户点了删除,但希望能恢复;
  • 管理员下架内容;
  • 数据过期进入归档;
  • 法规要求用户注销后清除个人信息;
  • 临时任务执行完可以清理。

这些语义不同,设计也不同。不要一上来就统一规定“都软删除”或“都硬删除”。

二、软删除的优点

软删除最大的好处是安全和可追溯:

  • 误删可以恢复;
  • 可以保留历史审计;
  • 关联表仍能找到历史记录;
  • 统计和追责更方便;
  • 删除动作可以参与业务流程。

比如订单、合同、支付记录通常不应该随便硬删除。即使用户端看不到,后台审计和财务仍可能需要。

三、软删除的坑

软删除不是加个字段就完事。常见坑包括:

  • 查询忘加 deleted_at is null,把已删除数据展示出来;
  • 唯一约束冲突,比如删除用户后无法重新注册同手机号;
  • 表越来越大,影响索引和查询性能;
  • 删除数据仍被统计进去;
  • 关联关系复杂,父记录软删后子记录状态不清楚。

所以软删除要配套查询规范、索引设计和归档策略。

四、唯一约束怎么处理

假设用户表有唯一手机号。如果软删除后还希望手机号可重新注册,就不能只建:

unique(phone)

因为被软删除的记录仍在表里。不同数据库支持能力不同,可以考虑:

  • 使用部分唯一索引,只约束未删除记录;
  • 唯一键包含删除标记或删除时间;
  • 删除时改写唯一字段,比如追加删除后缀;
  • 业务上规定删除后手机号仍不可复用。

具体方案要结合数据库能力和业务规则,不能硬套。

五、什么时候要硬删除或归档

长期软删除会让主表膨胀。很多系统会采用两阶段:

  1. 先软删除,保留一段可恢复窗口;
  2. 到期后归档到历史表或做硬删除。

对于合规删除,比如用户要求删除个人信息,还可能需要脱敏、匿名化或物理删除。此时“为了方便恢复而一直软删除”可能不合规。

六、查询层要统一处理

软删除最好在数据访问层统一加条件,避免每个业务开发手写过滤。比如 ORM 全局条件、Repository 基类、SQL 模板规范。

但也要提供后台审计查询入口,让有权限的人能查已删除数据。软删除不是数据消失,而是普通业务视图不可见。

软删除还要区分“可恢复删除”和“合规删除”。前者强调误删恢复和审计,后者可能要求清除或匿名化个人信息。比如用户注销后订单可以保留财务记录,但收货人手机号可能需要脱敏,不能简单用 deleted_at 把明文数据永久留在主表。

七、常见误区与追问

删除策略适合数据注意事项
软删除订单、合同、内容、可恢复数据默认过滤、归档、唯一约束
硬删除临时表、缓存表、无价值中间数据删除前确认无审计和恢复需求
脱敏/匿名化个人信息、合规删除保留业务统计但移除身份识别

记忆钩子:软删除不是“数据删了”,而是“普通业务视图不可见”。只要记录还在库里,就要继续承担索引、权限、合规和清理成本。

唯一约束是软删除最常见的坑。假设用户 A 用手机号 13800000000 注册后软删除,如果表上仍是全局唯一:

unique(phone)

用户 B 或用户 A 重新注册同一手机号会失败。此时要明确业务规则:手机号删除后是否允许复用;允许复用时可用部分唯一索引、(phone, deleted_at) 组合策略或删除时改写唯一字段,不允许复用时则保留全局唯一。

  • 误区:软删除就是加一个 is_deleted 字段。 还要处理默认查询过滤、唯一约束、索引膨胀、归档、权限和审计。
  • 误区:软删除比硬删除永远安全。 如果法规要求删除个人信息,一直软删除明文数据可能不合规。
  • 误区:所有查询手写 deleted_at is null 就够了。 手写容易漏,最好在数据访问层、ORM 或 Repository 规范中统一处理。
  • 追问:为什么更推荐 deleted_at 而不是单纯 is_deleted deleted_at 同时表达是否删除和删除时间,便于恢复窗口、归档和审计。
  • 追问:父记录软删后子记录怎么办? 要明确子记录是否仍可见、是否级联软删、是否禁止父记录删除,以及恢复时如何恢复关系。
  • 追问:软删除数据越来越多怎么办? 设计两阶段生命周期:先软删除保留可恢复窗口,到期后归档、脱敏或硬删除。

八、加强记忆

硬删除简单彻底,软删除安全可恢复但会带来查询、唯一约束和数据膨胀问题。软删除建议用 deleted_at 表达删除时间,并配套默认过滤、唯一约束方案、归档清理和权限控制。