81 lines
3.0 KiB
Markdown
81 lines
3.0 KiB
Markdown
# 12.4 数据删除规范
|
||
|
||
:::tip 概述
|
||
删除一律软删(del_flag=1,由全局钩子强制改写);物理删除只在定时清理任务中出现。删除守卫保护引用完整性。本节为强制规范与操作红线。
|
||
:::
|
||
|
||
## 强制规范
|
||
|
||
```text
|
||
1. 删除接口全部软删:deleteHook 把物理 DELETE 改写为 UPDATE del_flag=1
|
||
——业务代码无需(也不允许)自己写 del_flag 更新
|
||
|
||
2. 查询一律经 dao.Ctx(自动过滤 del_flag=0)
|
||
——禁止绕过 dao 直连 g.DB()(已删数据会"复活"可见)
|
||
|
||
3. 禁止手写 del_flag 条件(手写易漏:忘 filter 或写错值)
|
||
|
||
4. 物理删除仅允许出现在清理类定时任务(LogClean/CleanTemp)
|
||
——业务代码禁止 Data/Delete 真实物理删除
|
||
|
||
5. 删除前守卫:存在子级/引用时拒绝(1011/1014),先处理关联
|
||
|
||
6. 唯一索引含 del_flag(软删行不占唯一坑位——uk 设计规范)
|
||
```
|
||
|
||
## 守卫模式(真实模块)
|
||
|
||
```text
|
||
dept:存在子部门拒绝(1011);存在用户引用拒绝
|
||
menu:存在子菜单拒绝(1011)+ 同步清理 role_menu(防悬挂授权)
|
||
role:存在用户引用拒绝(1014/1011 语义)
|
||
user:删除守卫 + 清理 user_role 关联
|
||
category:存在子分类/文章引用检查
|
||
```
|
||
|
||
spec 钩子:`BeforeDelete`(守卫)→ 基座软删 → `AfterDelete`(关联清理/缓存清理)。
|
||
|
||
## 软删的工程含义
|
||
|
||
```text
|
||
可恢复:del_flag 改回 0 即恢复(无官方恢复接口时可 DB 操作/数据修复)
|
||
存储增长:软删行永久占用——靠唯一索引含 del_flag 设计兼容
|
||
唯一性:uk 含 del_flag → 同名删除后可再建(软删行不占坑)
|
||
审计:create_user/update_user 保留最后操作人;恢复时注意盖章语义
|
||
```
|
||
|
||
## 数据清理策略
|
||
|
||
```text
|
||
日志三表(operation_log/login_log/job_log):
|
||
LogClean 任务每日 02:30 物理删除超保留期记录
|
||
保留天数 job.logRetentionDays(默认 90),任务参数 retentionDays 可覆盖
|
||
单批 5000 行循环;单表单次上限 20 万行(防长事务)
|
||
|
||
业务表软删数据:
|
||
默认不清理(可恢复性优先)
|
||
如需归档清理:新建归档任务(参考 LogClean 模式),先归档再物理删
|
||
清理前备份
|
||
```
|
||
|
||
## Review 检查项
|
||
|
||
```text
|
||
□ 删除走 spec.Delete/手写 dao.Ctx 软删(无物理 DELETE)
|
||
□ BeforeDelete 守卫齐全(子级/引用)
|
||
□ AfterDelete 关联清理(user_role/role_menu 等)
|
||
□ 唯一索引含 del_flag(新建表时)
|
||
□ 无绕过 dao 的删除路径
|
||
□ 批量删除逐条守卫(非绕过逐条检查的批量 SQL)
|
||
```
|
||
|
||
## 反例(禁止)
|
||
|
||
```text
|
||
❌ dao.Xxx.Ctx(ctx).Where(...).Delete() 未确认 deleteHook 生效(绕过 dao 时物理删除!)
|
||
❌ UPDATE goframe_xxx SET del_flag=1 手写(应交给钩子)
|
||
❌ 清理任务直接 DELETE 大表无分批(长事务锁表)
|
||
❌ 唯一索引不含 del_flag(软删后无法再建同名)
|
||
❌ 删除后不清理关联(悬挂 role_menu/user_role)
|
||
```
|