推荐使用 deleted_at 时间戳字段实现软删除,NULL 表示未删除,非空表示已删除,支持审计、归档与索引优化,并需在 ORM 层统一过滤。
软删除字段通常用一个布尔型或时间戳字段来标记数据是否被“删除”,而不是真正从数据库中移除。设计时核心目标是:不影响原有查询逻辑、便于恢复、避免误删、兼顾性能和可读性。
比布尔字段(如 is_deleted)更灵活,能记录删除时间,支持按时间范围审计、自动归档或定时清理。值为 NULL 表示未删除,非空表示已软删除。
deleted_at DATETIME NULL DEFAULT NULL
WHERE deleted_at IS NULL
UPDATE users SET deleted_at = NOW() WHERE id = 123
UPDATE users SET deleted_at = NULL WHERE id = 123
大量数据下,WHERE deleted_at IS NULL 可能走全表扫描。建议为该字段建立单独索引,或与高频查询字段组合成联合索引。
INDEX idx_deleted_at (deleted_at)
INDEX idx_status_created (deleted_at, created_at)
IS NULL 可走索引,但部分旧版本对函数索引支持有限,避免写成 IFNULL(deleted_at, '1970-01-01') 这类表达式避免每个 SQL 都手动写 WHERE deleted_at IS NULL,应在 ORM 或 DAO 层做默认过滤。
SoftDeletes trait,自动追加全局作用域
findWithDeleted() 或传
includeDeleted: true
虽然简单,但存在语义歧义(比如初始值设 true 还是 false?逻辑反转易出错),且无法记录删除时间,后续扩展性差。
FALSE,并确保所有插入不显式赋值deleted_at 当作一等公民字段对待,从建表、索引、查询到业务逻辑层层对齐,才能真正落地可靠。