数据库无关联设计,删除数据

一、为什么不直接物理删除

即使业务上"不需要保留"订单数据,直接 DELETE 仍会带来问题:

场景:某电商决定只保留3个月订单,过期删除

直接 DELETE 的问题

问题 说明 实际影响
主从延迟 大删除产生大量 binlog 从库延迟几分钟到几十分钟
锁竞争 DELETE 期间锁住大量行 影响正常读写,可能超时
磁盘碎片 删除后空间不释放,只是标记可复用 表文件大小不变,浪费空间
无法恢复 误删后只能从备份恢复 恢复时间几小时到几天
事务日志膨胀 undo log 记录删除操作 可能撑爆磁盘
缓存穿透 大量删除导致 Buffer Pool 污染 影响后续查询性能

二、标准做法:多阶段生命周期

完整的数据流转路径

订单创建 → 热数据(3个月) → 温数据(1年) → 冷数据(3年) → 归档/删除
   ↓            ↓                ↓               ↓              ↓
在线库      在线库          历史库          冷存储        合规销毁
可读写      可读写          只读查询        离线查询       物理删除

实际表设计:状态字段

# orders 表增加状态字段
orders 表字段:
- id
- user_id
- user_name
- total_amount
- status          # 业务状态:待支付/已完成/已取消
- data_status     # 数据生命周期状态:热/温/冷/已归档
- created_at
- archived_at     # 归档时间
- deleted_at      # 标记删除时间

数据状态流转示例

订单ID 创建时间 data_status deleted_at 说明
1001 2024-11-01 NULL 3个月内,在线库可读写
1002 2024-08-15 NULL 3-12个月,在线库只读
1003 2023-06-01 NULL 1-3年,已迁移到历史库
1004 2022-01-01 已归档 2025-01-01 超过3年,已归档并标记删除

三、不同场景的处理策略

场景1:订单数据完全不需保留(如测试数据、临时购物车)

策略:定时任务批量删除 + 软标记

# 每天凌晨执行
def cleanup_temp_carts():
    # 步骤1:标记(软删除)
    db.execute("""
        UPDATE shopping_carts 
        SET status = '已删除', 
            deleted_at = NOW()
        WHERE status = '临时' 
        AND created_at < DATE_SUB(NOW(), INTERVAL 7 DAY)
        LIMIT 10000
    """)
    
    # 步骤2:延迟物理删除(可选,7天后真正删除)
    db.execute("""
        DELETE FROM shopping_carts 
        WHERE status = '已删除' 
        AND deleted_at < DATE_SUB(NOW(), INTERVAL 7 DAY)
        LIMIT 5000
    """)

数据状态

id user_id status created_at deleted_at
1 100 正常 2024-02-10 NULL
2 101 已删除 2024-02-01 2024-02-05
3 102 已删除 2024-01-20 2024-01-25

场景2:订单数据需要保留但不可见(用户注销场景)

策略:更新状态 + 数据脱敏

# 用户注销时
def anonymize_user_orders(user_id):
    # 不删除,只脱敏和标记
    db.execute("""
        UPDATE orders 
        SET user_name = '[已注销]',
            user_phone = NULL,
            user_address = NULL,
            is_visible = 0,        # 前端不可见
            data_status = '已脱敏'
        WHERE user_id = ?
    """, user_id)

订单数据变化

id user_id user_name total_amount is_visible data_status
1001 3 王五 1299.00 1 正常
1002 3 [已注销] 599.00 0 已脱敏

效果

  • 后台对账、财务审计仍能看到完整数据
  • 前端不展示给用户
  • 满足合规要求(如 GDPR 的"被遗忘权")

场景3:订单数据需要归档清理(节省在线库空间)

策略:分区表 + 在线 DDL 删除分区

MySQL 分区表示例:

-- 按月分区
CREATE TABLE orders (
    id BIGINT,
    created_at DATETIME,
    ...
) PARTITION BY RANGE (YEAR(created_at) * 100 + MONTH(created_at)) (
    PARTITION p202401 VALUES LESS THAN (202402),
    PARTITION p202402 VALUES LESS THAN (202403),
    PARTITION p202403 VALUES LESS THAN (202404),
    ...
);

删除过期数据

-- 直接删除整个分区(毫秒级完成,不产生大量 binlog)
ALTER TABLE orders DROP PARTITION p202301;
ALTER TABLE orders DROP PARTITION p202302;
ALTER TABLE orders DROP PARTITION p202303;

数据流转

  1. 热数据:最近3个月分区,在线库可读写
  2. 温数据:3-12个月分区,在线库只读查询
  3. 冷数据:1年前分区,迁移到历史库后删除原分区

场景4:订单数据需要彻底物理删除(合规要求)

策略:专用清理任务 + DBA 审批

# 合规删除流程
def compliant_delete():
    # 1. 标记待删除
    db.execute("""
        UPDATE orders 
        SET delete_flag = 1,
            delete_request_time = NOW(),
            delete_reason = '用户主动删除'
        WHERE user_id = ? 
        AND status = '已完成'
        AND created_at < DATE_SUB(NOW(), INTERVAL 3 YEAR)
    """)
    
    # 2. 进入审批队列(等待 DBA 审核)
    create_approval_task(user_id, "合规删除申请")
    
    # 3. 审批通过后,执行物理删除(低峰期)
    # 先备份,再删除
    export_to_archive(user_id)  # 先归档到冷存储
    db.execute("DELETE FROM orders WHERE delete_flag = 1")

四、决策树:何时物理删除 vs 标记删除

是否需要物理删除?
    │
    ├─ 有合规要求(GDPR、金融法规)
    │   └─ 是 → 物理删除(但先归档备份)
    │
    ├─ 数据量极大,影响性能
    │   └─ 是 → 分区表,直接 DROP PARTITION
    │
    ├─ 数据可恢复要求高
    │   └─ 是 → 标记删除,永不物理删除
    │
    ├─ 成本考虑(存储费用高)
    │   └─ 是 → 迁移到廉价冷存储后物理删除
    │
    └─ 默认策略
        └─ 标记删除 + 延迟清理(7-30天后物理删除)

五、实际案例对比

案例A:淘宝订单

  • 策略:永不物理删除
  • 方式:状态字段 + 分区表
  • 原因:交易凭证,可能需要追溯10年
订单状态 数据状态 用户可见 后台可见
已完成 热数据
已删除(用户侧) 冷数据 是(运营可查)
已归档 归档库 是(需申请)

案例B:临时购物车

  • 策略:7天后物理删除
  • 方式:定时任务批量删除
  • 原因:无保留价值,节省空间
创建时间 操作 数据状态
0-7天 正常使用 在线库
7-14天 标记"已过期" 在线库(不可见)
14天后 物理删除 已删除

案例C:用户聊天记录

  • 策略:软删除 + 定期归档
  • 方式:状态字段 + 历史库
  • 原因:可能恢复,合规要求
时间 状态 存储位置
删除时 标记"已删除" 在线库
30天后 迁移 历史库
1年后 压缩归档 冷存储
3年后 物理删除

六、总结

数据重要性 推荐策略 方式
核心交易数据 永不删除 状态字段 + 分区 + 归档
用户主动删除 软删除 状态字段 + 脱敏
临时数据 延迟物理删除 定时任务 + 分批
日志/监控数据 定期清理 按时间分区删除
合规要求删除 物理删除 审批流程 + 备份先行

核心原则

  1. 默认软删除:用状态字段标记,保留恢复可能
  2. 物理删除是最后手段:只有明确合规要求或成本压力才执行
  3. 分批操作:任何删除都要限流、分批,避免影响业务
  4. 先备份后删除:物理删除前务必归档备份
  5. 分区表优先:按时间分区,删除分区比 DELETE 高效百倍

即使"不需要保留"的订单数据,大公司也会先标记删除,观察一段时间(如30天),确认无问题后再分批物理删除。这是对数据安全的敬畏。

posted @ 2026-04-06 16:33  爱晒太阳的懒猫。。  阅读(2)  评论(0)    收藏  举报