软删除是通过status字段标记删除状态而非物理删除数据,需建索引、orm全局拦截、关联查询同步过滤,并定期归档清理。

软删除不是真删数据,而是用字段标记“已删除”状态,让查询默认过滤掉这些记录。核心在于统一拦截、避免漏查、兼顾历史和性能。
用 status 字段实现基础软删除
在表中增加 status(tinyint)或 is_deleted(boolean)字段,约定 0/1 或 false/true 表示“未删除/已删除”。所有写操作(INSERT/UPDATE)不直接删行,而是 UPDATE status = 1;读操作默认加 WHERE status = 0 条件。
- 推荐用 status TINYINT DEFAULT 0 COMMENT '0-正常,1-已删除',比布尔类型更易扩展(比如后续加“审核中”“回收中”等状态)
- 必须为 status 字段建索引,尤其当表数据量大、删除比例高时,避免全表扫描
- 不要用 deleted_at IS NULL 这类方式替代 status,NULL 值在索引和 JOIN 中行为复杂,且无法表达“逻辑删除但时间未知”的语义
全局拦截:ORM 层统一处理
靠人工每次写 WHERE status = 0 容易遗漏,应在 ORM 框架层做默认过滤。例如:
- MyBatis-Plus:开启 logic-delete,配置 global-config 中的 dbConfig.logicDeleteField 和 logicDeleteValue
- Django:用 django-model-utils 的 SoftDeletableModel,或自定义 Manager,在 get_queryset() 中默认 filter(is_deleted=False)
- Laravel:使用 SoftDeletes trait,模型自动添加 whereNull('deleted_at'),并重载 delete() 方法
注意:需明确区分“管理后台查全部”和“用户端查有效数据”,可通过显式调用 withTrashed() 或 onlyTrashed() 绕过默认过滤。
在线证件照系统是一套完善的冲印行业解决方案,致力于解决用户线上拍摄证件照,拍摄最美最标准证件照的使命。证件照免费版功能:后台统计:当天制作、当天新增、支持规格、近7日统计规格列表:筛选查看、编辑用户列表:筛选查看常见问题:筛选查看、新增、编辑、删除小程序设置:应用设置、流量主设置小程序跳转:筛选查看、新增、编辑、删除关注公众号:引导设置系统要求:系统:Linux系统(centos x64)运行环境
关联查询与统计要同步过滤
软删除影响不止单表——JOIN、子查询、COUNT、聚合都可能出错。例如查“每个分类下的商品数”,若商品表有软删除但没在 COUNT 中过滤,结果会虚高。
- LEFT JOIN 关联时,在 ON 条件里补上 AND b.status = 0(b 是被关联的软删除表)
- COUNT(*) 改为 COUNT(CASE WHEN b.status = 0 THEN 1 END) 或直接 COUNT(b.id)(因 NULL 不计入 COUNT)
- 分页列表中带统计字段(如“该用户已删订单数”),应单独写子查询或用窗口函数,避免主查询 WHERE 干扰统计逻辑
清理与归档:别让垃圾数据越积越多
长期不清理已删除数据,会导致表膨胀、备份变慢、查询变卡。需制定归档策略:
- 定期(如每月)将 status = 1 且 deleted_at
- 归档后执行 DELETE FROM table WHERE status = 1 AND ... —— 这是物理删除,需在低峰期操作,并确认业务无回溯依赖
- 关键表(如订单、用户)建议保留软删除标记至少 1 年,满足审计与客诉追溯要求
不复杂但容易忽略。









