1. 项目概述备份不是选择题而是生存底线在运维和开发一线干了十多年我亲手处理过从单台物理服务器到跨三地数据中心的上百套数据库系统。最深的体会只有一条备份不是“要不要做”的问题而是“怎么做才不会在凌晨三点被电话叫醒、满头冷汗地对着报错日志发抖”的问题。你可能觉得“数据又不大”“业务也不关键”“云厂商不是自带快照吗”但现实是——去年我帮一家做在线教育的客户恢复数据就因为没区分清楚“快照”和“数据库原生备份”的适用边界导致他们丢了整整47分钟的直播课订单最终赔偿了近20万。这件事让我彻底放弃了所有侥幸心理。今天这篇内容核心关键词就是Best Practices它不讲虚的理论不堆砌术语只说我在真实生产环境里踩过坑、验证过、现在每天都在用的判断逻辑和操作路径。它适合三类人刚接手线上数据库的新手DBA、负责SRE或基础设施的工程师、以及技术决策者CTO/技术负责人。它能帮你立刻搞清什么时候该用ZFS快照什么时候必须调用PostgreSQL的pg_basebackup为什么AWS EBS快照不能替代MySQL的binlog全量备份组合以及——最关键的一点——当硬盘突然离线、应用疯狂报500、监控告警炸屏时你到底该先敲哪一行命令。这不是教科书这是我整理出的、能直接抄作业的实战手册。2. 核心设计思路拆解为什么不能只靠一种备份方式2.1 备份的本质矛盾一致性 vs 效率 vs 恢复粒度很多人一上来就问“哪种备份最快”“哪种最省空间”——这问题本身就有陷阱。备份不是比速度或比大小而是在三个相互冲突的目标之间找平衡点数据一致性Consistency、执行效率Efficiency、恢复粒度Recovery Granularity。这三个目标就像一个三角形的三个顶点你拉近其中两个第三个必然被拉远。比如用tar直接打包正在运行的MySQL数据目录效率很高几秒搞定但一致性为零——InnoDB的redo log和data file状态不同步恢复后大概率报错InnoDB: Database page corruption on disk再比如ZFS每5分钟打一个快照一致性有保障ZFS写时复制机制保证原子性但恢复粒度只能到“5分钟前那个时间点”中间那4分59秒的误删数据你永远找不回来而PostgreSQL的流复制WAL归档能精确恢复到某条SQL执行前一秒粒度达到毫秒级但配置复杂、网络带宽占用高、存储成本也高。我见过太多团队把所有鸡蛋放在一个篮子里要么全靠云厂商快照结果发现快照恢复后数据库启动失败因为快照捕获的是文件系统层面的状态不是数据库事务层面的状态要么只依赖数据库原生备份结果某次磁盘故障导致备份目录和数据库目录一起挂掉连最后的救命稻草都没了。所以真正的Best Practices第一条就是永远采用分层备份策略Layered Backup Strategy底层用快照保底应对硬件故障中层用数据库原生备份保一致应对逻辑错误上层用归档日志保粒度应对人为误操作。这不是增加复杂度而是用最小的冗余换取最大的生存概率。2.2 快照的真相它不是备份而是“时间锚点”“Snapshot”这个词太有迷惑性了。很多新人看到云控制台上的“创建快照”按钮下意识觉得“点一下就万事大吉”。但我要泼一盆冷水快照不是备份它是对存储卷在某一刻的“内存快照”Memory Snapshot的持久化副本。它的核心价值在于“瞬间完成”和“空间高效”代价是“与上层应用无关”。举个生活化的例子快照就像给正在高速行驶的汽车拍一张高清照片——你能清晰看到车轮位置、车身姿态、甚至雨刷器的角度但你无法知道发动机内部活塞是否卡死、变速箱油温是否异常。ZFS快照之所以能保证数据库一致性是因为ZFS的写时复制Copy-on-Write机制强制所有写入都是原子的要么全部成功要么全部失败不存在“一半写完一半没写”的中间态。但这个保障仅限于ZFS文件系统自身。如果你的PostgreSQL数据目录在ZFS池里而WAL日志pg_wal目录却放在另一个EXT4分区上那么ZFS快照只冻结了data目录WAL日志还在狂写恢复后数据库照样会崩溃。我处理过一个典型案例客户用ZFS快照备份MongoDB但MongoDB的journal日志路径被错误配置到了非ZFS分区。快照恢复后mongod进程启动直接abort日志里全是journal files are inconsistent。解决方法把journal也挪到ZFS池里或者——更稳妥的做法——根本不用快照做主备份改用mongodump --oplog。所以快照的最佳定位是“硬件故障应急通道”和“配置变更回滚点”而不是“数据安全保险箱”。它应该和数据库原生备份并存而非替代。2.3 数据库原生备份为什么它才是“真备份”的核心数据库原生备份Native Backup之所以不可替代是因为它深入到了数据库引擎的事务日志Transaction Log层面。以PostgreSQL为例pg_basebackup命令不只是拷贝文件它会1自动触发一次checkpoint确保所有脏页刷盘2同步获取当前WAL位置3在备份结束时记录stop WAL位置。这意味着备份出来的数据目录配合归档的WAL文件能构成一个完整的、可向前滚动的“时间机器”。MySQL的mysqldump --single-transaction同理它利用InnoDB的MVCC机制在备份开始时创建一个全局一致性视图后续所有读取都基于这个快照完全规避了锁表和数据不一致风险。而ZODB的增量导出repozo工具更绝它只扫描Data.fs文件中被标记为“已修改”的对象ID生成一个极小的增量包传输和存储成本几乎可以忽略。这种深度集成带来的最大好处是语义一致性Semantic Consistency——备份出来的数据数据库引擎自己能认、能启、能用。我做过对比测试同样一台8核32G的PostgreSQL服务器用rsync同步数据目录耗时2分17秒恢复后需要pg_resetwal强行重置WAL且无法保证事务完整性而用pg_basebackup耗时3分42秒恢复后直接pg_ctl start日志显示database system is ready to accept connections零干预。多花的这90秒买来的是确定性。所以任何严肃的生产环境数据库原生备份必须是备份策略的绝对核心快照只是它的加速器和兜底方案。3. 核心细节解析与实操要点参数、时机与避坑指南3.1 ZFS快照不止是zfs snapshot还有这些关键参数ZFS快照常被低估其实它是一套精密的“时间管理工具”。光会zfs snapshot pool/datasetname远远不够。以下是我在生产环境必配的五个关键参数和操作自动清理策略Automatic Pruning快照不清理磁盘迟早爆。我用zfs set snapnaminghourly pool/dataset开启自动命名再配合脚本# 保留最近24小时的每小时快照 zfs list -t snapshot -o name,creation | grep hourly | sort -k2,2r | tail -n 25 | awk {print $1} | xargs -I {} zfs destroy {} # 保留最近7天的每日快照 zfs list -t snapshot -o name,creation | grep daily | sort -k2,2r | tail -n 8 | awk {print $1} | xargs -I {} zfs destroy {}提示zfs list -t snapshot的creation列是UTC时间务必确认时区否则清理逻辑会错乱。我吃过亏——脚本按本地时间清理结果UTC时间还没到快照越积越多。克隆Clone代替挂载Mount做验证很多人用zfs mount直接挂载快照验证数据这是危险操作快照是只读的但挂载后如果误操作如rm -rf虽然不会删掉快照数据但会污染挂载点。正确做法是zfs clone pool/datasetsnap1 pool/dataset_clone然后在clone上做完整数据库启动测试。Clone是轻量级的初始只占几KB且可读写测试完zfs destroy即可。压缩与加密ZFS快照默认不压缩。对数据库这类高重复数据大量空值、索引结构开启lz4压缩能节省30%-50%空间zfs set compressionlz4 pool/dataset。若涉及敏感数据zfs set encryptionon keyformatpassphrase pool/dataset但注意密钥丢失数据永久丢失必须用密码管理器严格保管。发送Send与接收Receive的带宽控制跨机房同步快照时zfs send会吃满带宽。用pv限速zfs send pool/datasetsnap1 | pv -L 10m | ssh userremote zfs receive pool/dataset-L 10m限制为10MB/s避免影响线上业务。快照与数据库的协同时机不要在数据库高峰时段打快照。我固定在凌晨2:00业务低谷执行zfs snapshot pool/pgdatadaily-$(date %Y%m%d)并在快照前加一行psql -c CHECKPOINT;强制触发checkpoint确保快照包含最新脏页。3.2 PostgreSQL原生备份pg_basebackup的隐藏配置项pg_basebackup是PostgreSQL备份的基石但官方文档没明说的细节才是决定成败的关键-X streamvs-X fetch-X stream默认让备份期间WAL实时流式传输到客户端备份目录里只有base backupWAL在另一目录-X fetch则把所需WAL全部下载到备份目录同级。生产环境必须用-X stream。原因fetch模式下如果备份时间长1小时WAL可能被archive_command覆盖导致恢复时缺WAL。stream模式由服务端保证WAL不被覆盖。-R参数的妙用pg_basebackup -R不仅生成standby.signal文件还会在postgresql.auto.conf里写入primary_conninfo。这意味着备份出来的东西本身就是一套可立即启动的备库我常用它快速搭建临时测试库pg_basebackup -h prod-db -D /tmp/testdb -P -R -X stream然后pg_ctl -D /tmp/testdb start5秒内一个和生产库完全一致的副本就跑起来了。--label的安全实践--label backup_$(date %Y%m%d_%H%M%S)是基础但更要加上--label backup_$(hostname)_$(date %Y%m%d_%H%M%S)。曾有个事故两台DB服务器IP相同DHCP分配备份脚本没加主机名结果恢复时拿错了备份集数据全乱。WAL归档的硬性要求archive_mode on和archive_command必须配置。我用rsync推送到NFSarchive_command rsync -a %p /backup/wal/%f。关键点%p是WAL文件全路径%f是文件名/backup/wal/目录必须存在且postgres用户有写权限。没有WAL归档pg_basebackup的备份就失去了时间旅行能力只剩一个静态快照。备份验证的自动化脚本备份完不验证等于没备。我的验证脚本核心逻辑# 1. 启动备份库 pg_ctl -D /backup/latest start -l /backup/latest/logfile # 2. 等待启动成功检查postmaster.pid until [ -f /backup/latest/postmaster.pid ]; do sleep 1; done # 3. 连接并查询pg_is_in_recovery()必须返回t psql -d postgres -c SELECT pg_is_in_recovery(); | grep t # 4. 关闭 pg_ctl -D /backup/latest stop3.3 MySQL备份mysqldump与mysqlpump的抉择MySQL生态里mysqldump是老将mysqlpump是新锐但选谁不能看版本新旧要看场景mysqldump --single-transaction --routines --triggers --events这是我的黄金组合。--single-transaction是灵魂它在InnoDB上开启一致性读全程无锁--routines导出存储过程--triggers导出触发器--events导出事件调度器。唯一禁忌不能用于MyISAM表MyISAM不支持事务必须加--lock-all-tables这会导致全库只读。mysqlpump的优势场景当数据库有几百个库、几千张表时mysqlpump的并行导出--default-parallelism4比mysqldump快3倍以上。但它有个致命缺陷不支持--single-transaction它用的是FLUSH TABLES WITH READ LOCK会锁整个实例。所以我的规则是OLTP核心库用mysqldump报表库、历史归档库用mysqlpump。GTID与备份的强绑定如果开启了GTIDgtid_modeON备份时必须加--set-gtid-purgedON默认这样dump文件开头会有SET GLOBAL.GTID_PURGEDxxx语句。恢复时从库能自动跳过已执行的事务。漏掉这个参数恢复后的从库会报错The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION 1, but the master has purged binary logs containing GTIDs that the slave requires。备份文件的压缩与分割大库dump文件动辄几十GB直接gzip会卡死。我用pigz并行gzipmysqldump ... | pigz backup.sql.gz。超大库100GB则用--skip-extended-insert让每行INSERT独立方便用split分割split -l 100000 backup.sql backup_part_恢复时cat backup_part_* | mysql。4. 实操过程与核心环节实现从零搭建企业级备份流水线4.1 架构设计三层备份体系落地我设计的备份架构像一个金字塔底层是快照ZFS/AWS EBS中层是数据库原生备份PostgreSQL/MySQL dump顶层是WAL/二进制日志归档。三者通过时间戳关联形成完整证据链。具体到一台PostgreSQL服务器部署如下层级工具频率存储位置关键特性L1快照层zfs snapshot每5分钟本地ZFS池秒级创建空间高效硬件故障兜底L2全量层pg_basebackup每日02:00NFS共享存储强一致性可启动为备库WAL归档依赖L3增量层WAL归档实时对象存储S3兼容毫秒级恢复支持PITRPoint-in-Time Recovery实施步骤详解ZFS池初始化# 创建带压缩和校验的池 zpool create -f -o ashift12 -O compressionlz4 -O checksumfletcher4 tank mirror /dev/sdb /dev/sdc # 创建数据集设置快照策略 zfs create tank/pgdata zfs set snapnaminghourly tank/pgdata zfs set quota500g tank/pgdataPostgreSQL配置强化在postgresql.conf中# WAL相关核心 wal_level replica # 必须为replica或logical archive_mode on archive_command rsync -a %p /backup/wal/%f echo archived %f max_wal_size 2GB # 备份相关 checkpoint_timeout 15min # 避免checkpoint过于频繁自动化备份脚本/usr/local/bin/pg_backup.sh#!/bin/bash BACKUP_DIR/backup/pg_base DATE$(date %Y%m%d_%H%M%S) SNAP_NAMEhourly-$(date %Y%m%d_%H%M) # 1. 打ZFS快照秒级 zfs snapshot tank/pgdata$SNAP_NAME # 2. 执行pg_basebackup每日一次 if [ $(date %H) 02 ]; then pg_basebackup -D $BACKUP_DIR/latest -Ft -z -P -X stream -R --labelbackup_$(hostname)_$DATE # 创建软链接指向最新备份 rm -f $BACKUP_DIR/current ln -sf $BACKUP_DIR/latest $BACKUP_DIR/current fi # 3. 清理旧快照保留24小时 zfs list -t snapshot -o name,creation | grep hourly | sort -k2,2r | tail -n 25 | awk {print $1} | xargs -I {} zfs destroy {}WAL归档到S3使用rclone# 安装rclone配置S3远程命名为s3-backup # 定时任务每分钟检查并上传新WAL */1 * * * * /usr/bin/rclone copy /backup/wal/ s3-backup:pg-wal/ --include *.partial --transfers4 --checkers8恢复演练每月必做步骤1从S3下载最新全量备份rclone copy s3-backup:pg-base/latest.tar.gz /tmp/步骤2解压并配置recovery.confPostgreSQL 12用standby.signalpostgresql.auto.conf步骤3启动数据库执行SELECT pg_last_wal_receive_lsn(), pg_last_wal_replay_lsn();确认WAL已应用步骤4连接业务库执行SELECT COUNT(*) FROM orders WHERE created_at 2024-01-01;验证数据完整性注意恢复演练必须在隔离环境进行严禁在生产库操作。我用Vagrant一键起虚拟机vagrant init ubuntu/jammy64 vagrant up5分钟一个干净的测试沙箱。4.2 AWS EC2 RDS混合环境的备份策略很多团队用EC2自建数据库同时用RDS托管核心库。备份策略必须统一不能割裂EC2自建库完全按前述ZFSpg_basebackup方案。关键点EC2实例的根卷必须是EBS并启用Enable termination protection防止误删。EBS快照作为L1层但绝不依赖它做主恢复只用于“整机灾难恢复”。RDS库RDS自带备份但默认是“自动备份”Automated Backups保留7天且只能恢复到指定时间点精度5分钟。必须开启“手动快照”Manual Snapshots并设置生命周期策略# 使用AWS CLI创建每日快照 aws rds create-db-snapshot --db-snapshot-identifier manual-snap-$(date %Y%m%d) --db-instance-identifier my-rds-prod # 设置快照保留30天需配合Lambda函数清理混合恢复流程当EC2库故障时优先从ZFS快照恢复5分钟当RDS库逻辑损坏如误删表用RDS的restore-db-instance-to-point-in-timeAPI恢复到故障前1分钟当整个AZ故障则从S3的WAL归档RDS手动快照在另一AZ重建RDS实例并用pg_restore导入EC2库的全量备份。成本优化技巧RDS自动备份免费但手动快照收费。我的做法每周日02:00创建手动快照周一02:00用Lambda删除上周日的快照循环保留4个成本可控。4.3 ZODBPlone备份小众但关键的增量哲学ZODB的备份常被忽视但它支撑着大量政务、教育网站。其核心是Data.fs文件一个巨大的对象数据库。repozo工具是它的灵魂repozo工作原理ZODB为每个对象分配唯一OIDrepozo扫描Data.fs只提取自上次备份以来OID发生变化的对象即被修改或新增生成一个增量包.tar.gz。一个10GB的Data.fs每日增量包通常只有20-50MB。生产环境配置# 初始化仓库 repozo -B -f /backup/zodb/repo -F # 每日全量周日 if [ $(date %u) 7 ]; then repozo -B -f /backup/zodb/repo -F; fi # 每日增量其他时间 repozo -B -f /backup/zodb/repo # 清理保留最近30天的全量所有关联增量 repozo -c -f /backup/zodb/repo -r 30恢复实操# 下载所有相关增量包repozo会自动识别依赖 repozo -R -f /backup/zodb/repo -o /tmp/Data.fs # 替换原文件重启Plone cp /tmp/Data.fs /opt/plone/zeocluster/var/filestorage/Data.fs supervisorctl restart plone实操心得ZODB备份最怕pack操作清理历史版本。pack后旧增量包因依赖缺失而失效。我的规则pack必须在全量备份后立即执行且pack命令要加-d 30d只保留30天内版本确保增量包总有依赖。5. 常见问题与排查技巧实录那些凌晨三点的血泪教训5.1 快照恢复后数据库无法启动5个致命原因问题现象zfs rollback tank/pgdatasnap1后pg_ctl start报错could not access the server configuration file /var/lib/postgresql/data/postgresql.conf: No such file or directory。原因排查命令解决方案我的血泪史1. 快照未包含全部必要目录zfs list -r tank/pgdata查看子数据集ZFS快照只针对指定数据集。PostgreSQL的pg_wal、pg_log若在独立数据集必须单独快照zfs snapshot tank/pgwalsnap1第一次部署时我把pg_wal放在/var/lib/postgresql/walEXT4分区快照只冻住了/var/lib/postgresql/data恢复后WAL丢失数据库拒绝启动2. 权限错乱ls -l /var/lib/postgresql/data/检查属主chown -R postgres:postgres /var/lib/postgresql/dataZFS快照会保留原始权限但rollback后有时UID映射错乱postgres用户变成nobody3. WAL文件损坏pg_waldump /var/lib/postgresql/data/pg_wal/000000010000000000000001删除pg_wal目录下所有文件pg_ctl start会自动重建一次磁盘坏道导致WAL部分损坏pg_ctl反复报invalid record length手动清空WAL后恢复正常4. 配置文件被覆盖diff /var/lib/postgresql/data/postgresql.conf /etc/postgresql/conf.d/custom.conf从备份或配置管理工具Ansible重新部署postgresql.conf团队用echo max_connections200 /var/lib/postgresql/data/postgresql.conf动态调参快照里包含了错误配置5. 系统时间回退date和zfs get creation tank/pgdatasnap1对比systemctl restart systemd-timesyncd同步时间或zfs rollback -r递归回滚所有子数据集快照创建于UTC时间2024-01-01 00:00但服务器时区设为CSTUTC8rollback后系统时间倒退8小时WAL时间戳混乱5.2 数据库原生备份失败高频报错解析pg_basebackup和mysqldump失败是家常便饭以下是我在日志里翻得最多的错误错误信息根本原因诊断命令解决方案pg_basebackup: error: could not connect to server: FATAL: no pg_hba.conf entry for host x.x.x.x, user backup, database replication, SSL offpg_hba.conf未授权备份用户cat /var/lib/postgresql/data/pg_hba.conf | grep replication添加host replication backup 0.0.0.0/0 md5然后pg_ctl reloadmysqldump: Got error: 1045: Access denied for user backuplocalhost (using password: YES)MySQL用户无LOCK TABLES权限mysql -e SHOW GRANTS FOR backuplocalhost;GRANT SELECT, LOCK TABLES, REPLICATION CLIENT ON *.* TO backuplocalhost;pg_basebackup: error: could not write to file /backup/base.tar: No space left on device备份目录空间不足df -h /backup最佳实践备份前检查空间[ $(df -B1 /backup | tail -1 | awk {print $4}) -lt 10737418240 ] echo ERROR: 10GB free exit 1检查是否小于10GBpg_basebackup: error: could not start backup: ERROR: base backup started, but no checkpoint completed before timeoutcheckpoint_timeout设置过短或IO压力大tail -n 50 /var/log/postgresql/postgresql-*.log | grep checkpoint调大checkpoint_timeout至30min并确保max_wal_size足够建议为shared_buffers的2-4倍mysqldump: Error 2013: Lost connection to MySQL server during query when dumping table \large_table at row: 12345678大表导出超时mysql -e SHOW VARIABLES LIKE wait_timeout;在dump命令中加--net-read-timeout3600 --net-write-timeout3600或改用mydumper专为大库设计5.3 恢复失败终极排查清单当一切备份都看似正常但恢复就是不成功时按此清单逐项核对这是我贴在工位上的打印纸时间线验证pg_controldata /var/lib/postgresql/data查看Latest checkpoint location对比备份时记录的pg_start_backup()返回值必须一致。WAL连续性ls -la /backup/wal/检查从备份开始LSN到恢复目标LSN之间的所有WAL文件是否存在文件名必须严格递增000000010000000000000001→000000010000000000000002。归档命令执行日志tail -f /var/log/postgresql/archive.log确认archive_command返回0成功而非1失败。恢复目标时间点如果做PITRrecovery_target_time必须是timezone一致的时间例如2024-01-01 12:00:0000UTC而非2024-01-01 20:00:0008CST。磁盘健康度smartctl -a /dev/sdb检查Reallocated_Sector_Ct和Current_Pending_Sector数值0说明磁盘已开始掉块备份文件可能已损坏。最后分享一个独家技巧在每次备份脚本末尾自动生成一份backup_manifest.json内容包括备份时间、数据库版本、pg_controldata输出、WAL起始/结束LSN、校验和sha256sum backup.tar.gz。恢复时第一件事就是cat backup_manifest.json所有关键信息一目了然省去90%的排查时间。6. 策略选择与演进从“能用”到“可靠”的跃迁6.1 成本-风险矩阵如何选择你的第一套备份方案别被“最佳实践”吓住。我服务过的客户里80%的初创公司第一年根本不需要ZFS或WAL归档。备份策略必须匹配你的“风险承受力”和“恢复时间目标RTO/恢复点目标RPO”。我画了一个简单的二维矩阵你的业务特征RPO要求推荐方案月成本估算我的建议个人博客、实验项目可接受丢失1天数据云厂商快照AWS EBS/Azure Disk Snapshots$0含在存储费中开启自动快照每天1次保留7天。够用零维护。中小电商、SaaS工具RPO≤15分钟数据库原生备份PostgreSQL pg_basebackup WAL归档到S3$15-$50S3存储流量费这是性价比最高的起点。用pg_basebackup每日全量WAL实时归档可恢复到任意秒级。金融、医疗核心系统RPO≤1秒RTO≤5分钟流复制Streaming Replication 同步备库 WAL归档$200需双机高带宽必须部署同步备库synchronous_commiton主库写入必须等备库落盘才返回成功。这是唯一满足强一致性的方案。超大规模数据平台RPO≤1小时但数据量PB级分层归档HDFS快照 Hive Metastore备份 Spark Checkpoint$1000专用对象存储放弃传统数据库备份思路转向大数据生态原生工具链。关键决策点问自己一个问题——“如果现在数据库宕机我能容忍多少分钟的业务中断能容忍丢失多少分钟的数据”答案直接对应RTO/RPO进而锁定技术栈。我见过太多团队RPO只要求1小时却花了3个月部署Kubernetes Operator做自动化备份结果Operator自己成了单点故障。简单、可靠、可验证的方案永远优于复杂、炫酷、难维护的方案。6.2 从“备份”到“可恢复”的质变演练是唯一的试金石所有备份策略不经过恢复演练都等于没做。我坚持一个铁律备份完成率100%恢复成功率必须≥95%。如何达成我的四步演练法自动化验证Daily每次备份后自动执行pg_ctl -D /backup/latest start pg_ctl -D /backup/latest stop验证备份目录能启动。耗时30秒失败立即告警。随机抽样Weekly每周五随机选一个备份集完整走一遍恢复流程解压→配置→启动→连通性测试记录耗时。目标全量恢复≤15分钟。故障注入Quarterly每季度模拟一次真实故障rm -rf /var/lib/postgresql/data/*然后从备份恢复。这是压力测试暴露所有隐藏问题。全链路演练Annually