跳转到内容

数据备份与清理规范

备份策略、数据清理与归档


【Requirement】所有生产数据库必须配置全量备份 + 增量备份,备份保留周期 ≥ 30 天;核心库备份需异地存储。

方式工具频率恢复粒度说明
全量备份mysqldump / XtraBackup每日 1 次整库凌晨低峰执行
增量备份XtraBackup / binlog每小时 / 实时任意时间点binlog 实时归档
逻辑备份mysqldump每周 1 次单表/单库便于单表恢复
物理备份XtraBackup每日整实例恢复快,适合大库
数据级别全量备份binlog保留周期异地备份
核心库(订单/支付/用户)每日实时90 天必须
重要库(商品/库存)每日实时60 天必须
一般库(日志/统计)每周每小时30 天建议
临时库按需按需7 天否
# mysqldump 全量逻辑备份
mysqldump -h localhost -u root -p \
  --single-transaction --routines --triggers --events \
  --master-data=2 \
  --all-databases | gzip > /backup/full_$(date +%Y%m%d).sql.gz
 
# XtraBackup 物理备份
xtrabackup --backup --target-dir=/backup/full_$(date +%Y%m%d) \
  --user=root --password=secret
 
# binlog 归档
mysqlbinlog --read-from-remote-server --host=localhost \
  --user=root --password=secret --raw \
  --result-file=/backup/binlog/ mysql-bin.000001

【Standard】备份文件必须定期验证可恢复性,每月至少执行 1 次恢复演练。

  • 备份完成后校验文件大小与 checksum
  • 每周抽样恢复到测试库验证
  • 每月执行 1 次完整恢复演练,记录 RTO/RPO

【Requirement】每季度执行 1 次完整恢复演练,验证 RTO < 4 小时、RPO < 1 小时(核心库)。

指标核心库重要库一般库
RTO(恢复时间目标)≤ 4 小时≤ 8 小时≤ 24 小时
RPO(数据丢失目标)≤ 1 小时≤ 4 小时≤ 24 小时
# 1. 准备新实例
systemctl start mysql
 
# 2. 恢复全量备份(XtraBackup)
xtrabackup --prepare --target-dir=/backup/full_20240601
xtrabackup --copy-back --target-dir=/backup/full_20240601
chown -R mysql:mysql /var/lib/mysql
systemctl restart mysql
 
# 3. 应用 binlog 到指定时间点
mysqlbinlog --stop-datetime="2024-06-01 12:00:00" \
  /backup/binlog/mysql-bin.000001 | mysql -u root -p

每次演练必须记录:

项内容
演练时间2024-06-01 02:00
备份来源full_20240531 + binlog
恢复耗时2 小时 15 分
数据一致性校验通过
问题与改进binlog 归档延迟 5 分钟,需优化

【Standard】数据清理必须基于业务保留策略,采用逻辑删除 + 物理归档两步走;禁止直接 DELETE 生产数据。

数据类型在线保留归档保留说明
订单数据18 个月5 年超过 18 个月归档
支付流水24 个月永久财务合规要求
操作日志6 个月3 年审计需求
登录日志3 个月1 年安全审计
临时数据7 天不保留过期自动清理

【Requirement】业务删除必须使用逻辑删除(is_deleted 字段),禁止物理 DELETE。

-- 正确:逻辑删除
UPDATE order_order SET is_deleted = 1 WHERE id = ?;
 
-- 错误:物理删除
DELETE FROM order_order WHERE id = ?;

需要物理清理(归档后删除)时:

  1. 【Caution】必须在业务低峰期执行
  2. 【Requirement】清理前必须备份
  3. 【Standard】分批删除,每批 ≤ 1000 条,避免大事务锁表
-- 分批清理 3 个月前的已删除数据
DELETE FROM order_order
WHERE is_deleted = 1 AND update_time < '2024-03-01'
LIMIT 1000;
-- 重复执行直到影响行数为 0
import pymysql
import time
 
def clean_expired(table, condition, batch_size=1000, sleep=0.5):
    conn = pymysql.connect(...)
    cursor = conn.cursor()
    while True:
        sql = f"DELETE FROM {table} WHERE {condition} LIMIT {batch_size}"
        affected = cursor.execute(sql)
        conn.commit()
        print(f"Deleted {affected} rows")
        if affected < batch_size:
            break
        time.sleep(sleep)
    cursor.close()
    conn.close()

【Standard】超过在线保留期的数据归档至冷存储(HDFS / OSS / 归档库),归档后从在线库物理删除。

方式存储介质适用场景
归档库独立 MySQL 实例需要查询的历史数据
对象存储OSS / S3极少查询的数据
Hive / 数仓HDFS用于统计分析
1. 筛选:按时间范围筛选需归档的数据
2. 导出:导出为 SQL/CSV 或直接 INSERT 到归档表
3. 校验:校验归档数据与源数据一致(行数、checksum)
4. 备份:归档文件备份到异地
5. 删除:从在线库物理删除已归档数据
6. 记录:记录归档批次、时间、数据量、操作人

归档表与原表结构一致,可按时间分区:

CREATE TABLE order_order_archive (
  -- 与 order_order 结构一致
  ...
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单归档表'
PARTITION BY RANGE (TO_DAYS(create_time)) (
  PARTITION p202301 VALUES LESS THAN (TO_DAYS('2023-02-01')),
  PARTITION p202302 VALUES LESS THAN (TO_DAYS('2023-03-01')),
  ...
);

归档数据查询需走归档库或归档表,禁止直接查询在线库的历史分区:

-- 查询归档数据
SELECT * FROM order_order_archive 
WHERE create_time >= '2023-01-01' AND create_time < '2023-02-01'
AND user_id = ?;

【Requirement】数据处理必须符合《数据安全法》《个人信息保护法》及行业监管要求,敏感数据脱敏后存储与传输。

数据类型敏感等级处理要求
身份证号高加密存储,脱敏展示
手机号中高加密或哈希,脱敏展示
银行卡号高加密存储,脱敏展示
密码极高单向哈希(bcrypt),不可逆
住址中脱敏展示
生物特征极高加密存储,不可逆
  • 存储脱敏:敏感字段加密存储(AES-256)
  • 展示脱敏:前端展示时脱敏,如手机号 138****1234
  • 日志脱敏:日志中禁止打印明文敏感信息
  • 备份脱敏:非生产环境的备份数据必须脱敏
-- 手机号脱敏展示
SELECT CONCAT(LEFT(phone, 3), '****', RIGHT(phone, 4)) AS phone FROM sys_user;
  • 生产数据访问需审批,最小权限原则
  • 禁止将生产数据导出到本地或非授权环境
  • 数据导出需脱敏处理,记录操作日志
  • 数据保留期限到期后必须删除,不得超期留存
  • 个人信息出境需进行安全评估
  • 数据共享需签订数据处理协议,明确责任
  • 第三方数据接入需进行安全评估