简介:本资源是一份面向SQL Server数据库管理员、运维工程师及初中级DBA的实战型技术文档,系统讲解数据库备份、还原与损坏修复三大核心场景的完整操作方案。内容覆盖手动单次备份、维护计划自动化备份、还原前准备与执行流程,以及PhotoRec数据恢复、Data Numen SQL Recovery MDF文件修复等应急手段,兼顾原理说明与工具实操,适用于生产环境故障应对与日常容灾能力建设。资源为1个660KB的Word文档(.docx),结构清晰,含步骤截图指引、参数配置要点及注意事项提示,便于快速查阅与落地执行。目前已有717人学习下载,读者可直接获取标准化操作路径、常见报错应对思路及专业修复工具选型建议,显著降低数据库异常导致的业务中断风险。
1. SQL Server 备份还原修复:不是点几下“确定”就完事的三件套,而是数据生命线的日常巡检与应急手术
很多人第一次接触 SQL Server 的「备份还原修复」,是在凌晨两点收到告警邮件:主库连接超时、查询卡死、某个关键表突然返回空结果。这时候打开 SSMS,手抖点开“任务 → 备份”,再点“还原”,最后在“修复数据库”里勾上“检查分配一致性”——以为做完这三步就万事大吉。结果第二天发现,还原后的库能连上,但财务报表金额对不上;修复后表能查了,但触发器全丢了;备份文件看着有 23GB,restore 时却报错“介质集不完整”。这不是操作失误,而是把三个逻辑层级完全不同的动作混为一谈:备份是快照,还原是重建,修复是外科清创。它不面向 DBA 考试,而面向真实业务连续性——你得知道什么时候该用BACKUP DATABASE ... WITH COPY_ONLY避免打断日志链,什么时候必须停应用做RESTORE DATABASE ... WITH RECOVERY,又什么时候DBCC CHECKDB (..., REPAIR_ALLOW_DATA_LOSS)是最后一剂后悔药,而不是默认选项。本文写给每天要守着 50+ 实例、既要防误删又要扛勒索病毒、还得在领导问“数据还能不能救”时给出 3 分钟内可验证结论的一线运维和开发同学。
2. 备份不止是“右键导出”:从 FULL / DIFF / LOG 三类备份的本质讲起
SQL Server 的备份不是把 MDF 文件拷走那么简单。它的核心是基于事务日志(Transaction Log)的前滚(Redo)与回滚(Undo)机制,所有备份类型都服务于一个目标:在任意时间点,用最少的 I/O 和最短的 RPO/RTO 恢复到一致状态。理解 FULL、DIFF、LOG 三者的关系,是避免“备份做了但还原不了”的第一道防线。
2.1 FULL 备份:基线锚点,不是全量拷贝
FULL 备份捕获的是数据库在备份开始时刻的数据页一致性快照,但它不包含自上次 FULL 以来的所有日志,也不保证备份期间新事务被截断。关键点在于:
- 它会重置日志截断点(Log Truncation Point),但仅当数据库处于
FULL或BULK_LOGGED恢复模式下,且后续有日志备份配合; - 它本身不阻塞用户操作(默认
WITH NOFORMAT, NOINIT, NAME...),但大库 FULL 备份期间会产生大量 I/O 压力,建议避开业务高峰; - 致命误区:认为 FULL 备份 = “把整个库复制一份”。错。它只备份已分配的数据页,跳过空闲空间;若表中有大量 LOB 数据(如
VARCHAR(MAX)、VARBINARY),实际备份体积可能远小于磁盘占用。
-- 推荐的生产级 FULL 备份命令(带校验 + 压缩 + 过期清理) BACKUP DATABASE [MyAppDB] TO DISK = N'D:\Backup\MyAppDB_FULL_20240615.bak' WITH FORMAT, -- 覆盖同名文件,避免追加导致介质集混乱 INIT, -- 同上,显式声明更安全 COMPRESSION, -- 必开!SQL Server 2008 R2+ 原生支持,压缩率通常 60%~70% CHECKSUM, -- 校验备份块完整性,防止磁盘静默错误 STATS = 10, -- 每 10% 进度输出一行,便于监控耗时 RETAINDAYS = 7; -- 自动标记过期,配合后续脚本清理参数说明:
COMPRESSION在企业版中免费,标准版需确认版本是否支持(SQL Server 2014 SP2+ 标准版也支持);CHECKSUM不是可选装饰,而是检测备份文件是否在写入过程中损坏的唯一可靠手段;RETAINDAYS不会自动删除文件,只是设置备份集元数据,需配合sp_delete_backuphistory或 PowerShell 清理。
2.2 DIFF 备份:只存“变化差”,依赖 FULL 锚点
DIFF 备份记录的是自上次 FULL 备份以来所有被修改过的数据页。它体积小、速度快,但有一个硬约束:必须存在一个有效的、未被覆盖的 FULL 备份作为基准。没有这个基准,DIFF 文件就是一张废纸。
- DIFF 不依赖日志备份链,但它必须在 FULL 之后、下一个 FULL 之前执行;
- 连续做 10 次 DIFF,还原时只需最新一个 DIFF + 对应的 FULL,无需中间所有 DIFF;
- 血泪经验:某次模拟演练中,运维同学误删了上周五的 FULL 备份,只留了本周一到周四的 DIFF。还原时
RESTORE DATABASE ... WITH NORECOVERY成功,但RESTORE LOG报错“找不到基础备份”。原因?DIFF 的 LSN(日志序列号)链断裂,SQL Server 无法定位其父级 FULL。
-- DIFF 备份命令(注意:目标路径与 FULL 分开,避免混淆) BACKUP DATABASE [MyAppDB] TO DISK = N'D:\Backup\MyAppDB_DIFF_20240616.bak' WITH DIFFERENTIAL, -- 关键标识!缺此不可 COMPRESSION, CHECKSUM, STATS = 5;逻辑说明:
DIFFERENTIAL参数告诉 SQL Server 只扫描msdb.dbo.backupset中最近一次type = 'D'(FULL)的备份记录,并比对当前数据页的differential_base_lsn。若该 LSN 在backupset表中不存在或已被清除,命令直接失败。
2.3 LOG 备份:日志链的“毛细血管”,RPO 的命脉
LOG 备份捕获的是自上次 LOG 备份(或 FULL/DIFF)以来所有已提交事务的日志记录。它是实现秒级 RPO(恢复点目标)的唯一途径,也是还原到指定时间点(PITR)的基础。
- LOG 备份必须在
FULL或BULK_LOGGED恢复模式下才能生效;SIMPLE模式下日志会被自动截断,无法做 LOG 备份; - 它不释放日志空间,只是将已备份的日志标记为“可截断”(Truncatable),真正释放需等待检查点(Checkpoint)或手动
CHECKPOINT; - 玄学现象:某次 LOG 备份耗时突增 300%,
sys.dm_db_log_stats显示log_truncation_holdup_reason = 'ACTIVE_BACKUP_OR_RESTORE'。排查发现是另一个实例正在做长时间 FULL 备份,占用了共享存储 I/O,导致本库日志写入延迟,堆积未备份日志。
-- 生产环境 LOG 备份脚本(每 15 分钟一次,带失败告警) DECLARE @backupPath NVARCHAR(500) = N'D:\Backup\MyAppDB_LOG_' + FORMAT(GETDATE(), 'yyyyMMdd_HHmm') + '.trn'; BACKUP LOG [MyAppDB] TO DISK = @backupPath WITH NOFORMAT, NOINIT, COMPRESSION, CHECKSUM, STATS = 1;参数说明:
NOINIT允许在同一文件中追加多个 LOG 备份(形成介质集),但必须确保还原时按 LSN 顺序依次应用;若用INIT,每次都会覆盖,丢失历史 LOG,无法 PITR。
3. 还原不是“导入”,而是状态机重建:NORECOVERY、RECOVERY、STANDBY 的取舍逻辑
还原(Restore)是备份的逆过程,但绝非简单“把 bak 文件拖进去”。它本质是将备份中的数据页和日志记录,按事务一致性规则,重新加载到目标数据库文件中,并控制其可用状态。WITH RECOVERY、WITH NORECOVERY、WITH STANDBY这三个开关,决定了数据库是立刻上线、继续接收日志、还是变成只读快照。
3.1WITH NORECOVERY:还原流水线的“暂停键”
当你需要还原多个备份(如 FULL + DIFF + 多个 LOG)时,除最后一个还原操作外,其余全部必须用NORECOVERY。它让数据库停留在“正在还原中(Restoring…)”状态,保持日志链开放,允许后续RESTORE LOG继续前滚。
- 若在还原 DIFF 时误用了
RECOVERY,则后续 LOG 备份无法应用,因为数据库已退出还原模式; NORECOVERY下数据库不可读写,但可通过SELECT * FROM sys.databases WHERE state_desc = 'RESTORING'确认状态;- 翻车现场:某次灾备切换,DBA 手动执行
RESTORE DATABASE ... WITH NORECOVERY后忘记后续步骤,监控系统持续报警“数据库不可用”。其实此时库已还原完毕,只需一条RESTORE DATABASE ... WITH RECOVERY即可激活。
-- 还原 FULL 备份(不恢复,为后续留门) RESTORE DATABASE [MyAppDB_RestoreTest] FROM DISK = N'D:\Backup\MyAppDB_FULL_20240615.bak' WITH MOVE 'MyAppDB_Data' TO 'D:\Data\MyAppDB_RestoreTest.mdf', MOVE 'MyAppDB_Log' TO 'D:\Log\MyAppDB_RestoreTest.ldf', REPLACE, -- 强制覆盖同名数据库 NORECOVERY, -- 关键!保持还原状态 STATS = 10; -- 还原 DIFF 备份(同样不恢复) RESTORE DATABASE [MyAppDB_RestoreTest] FROM DISK = N'D:\Backup\MyAppDB_DIFF_20240616.bak' WITH NORECOVERY, STATS = 5;MOVE 说明:
MyAppDB_Data是逻辑文件名(查sys.master_files),不是物理文件名;REPLACE防止因目标库已存在而报错,但务必确认目标路径磁盘空间充足。
3.2WITH RECOVERY:最终“开机键”,不可逆
RECOVERY是还原流程的终点。它触发 SQL Server 执行两个动作:
① 回滚(Undo)所有未提交事务(基于日志中的LOP_ABORT_XACT记录);
② 前滚(Redo)所有已提交但未写入数据页的事务(基于LOP_COMMIT_XACT)。
完成后,数据库进入ONLINE状态,用户可正常访问。
- 重要边界:一旦执行
WITH RECOVERY,就无法再应用任何后续日志备份。想还原到更晚时间点?只能重来。 - 若还原后发现数据不对,唯一补救是:从更早的备份点重做还原流程(比如跳过 DIFF,直接用 FULL + 更早的 LOG)。
-- 最后一步:应用最后一个 LOG 并恢复(假设还原到 2024-06-16 14:30) RESTORE LOG [MyAppDB_RestoreTest] FROM DISK = N'D:\Backup\MyAppDB_LOG_20240616_1430.trn' WITH RECOVERY, -- 此处必须用 RECOVERY STOPAT = '2024-06-16T14:30:00'; -- 精确到秒的时间点恢复STOPAT 说明:
STOPAT必须配合NORECOVERY使用(除最后一次),否则报错。它不是“停在那个时间点”,而是“停在该时间点之前最后一个已提交事务”。
3.3WITH STANDBY:只读备库的“活快照”
STANDBY是NORECOVERY的增强版:它在还原后生成一个xxx.undo文件,保存回滚未提交事务所需的信息,使数据库进入STANDBY状态——可读,不可写,且支持后续RESTORE LOG继续前滚。
- 典型场景:报表服务器、BI 查询库、开发测试库,需要接近实时数据但不接受写入;
xxx.undo文件会随每次RESTORE LOG增大,需定期清理或监控空间;- 避坑提示:若在
STANDBY状态下有长事务(如未关闭的 SSMS 查询窗口),RESTORE LOG会因锁等待超时失败,报错1437。
-- 创建只读备库(首次还原) RESTORE DATABASE [MyAppDB_ReadOnly] FROM DISK = N'D:\Backup\MyAppDB_FULL_20240615.bak' WITH MOVE 'MyAppDB_Data' TO 'D:\Data\MyAppDB_ReadOnly.mdf', MOVE 'MyAppDB_Log' TO 'D:\Log\MyAppDB_ReadOnly.ldf', STANDBY = N'D:\Backup\MyAppDB_ReadOnly.undo', -- 指定 undo 文件路径 REPLACE, STATS = 10; -- 后续每日追加 LOG(保持只读状态) RESTORE LOG [MyAppDB_ReadOnly] FROM DISK = N'D:\Backup\MyAppDB_LOG_20240616.trn' WITH STANDBY = N'D:\Backup\MyAppDB_ReadOnly.undo';undo 文件说明:该文件本质是“回滚段快照”,SQL Server 用它在下次
RESTORE LOG前快速撤销上次还原时可能产生的未提交事务。若磁盘满,RESTORE直接失败。
4. 修复不是“一键重生”,而是数据外科手术:DBCC CHECKDB 的三层诊断与风险权衡
当备份还原都失败,或怀疑数据库文件物理损坏(如磁盘坏道、存储控制器异常)时,“修复”成为最后手段。但 SQL Server 的修复不是格式化重装,而是通过DBCC CHECKDB这个黑匣子,对数据库进行三级诊断(PHYSICAL_ONLY→EXTENDED_LOGICAL_CHECKS→REPAIR),每一层都意味着更深入的介入和更高的数据丢失风险。
4.1 诊断先行:用PHYSICAL_ONLY快速筛硬件问题
PHYSICAL_ONLY是最快、最轻量的检查模式,它只校验页头、页尾校验和、页链接、对象分配映射(IAM)等物理结构,跳过所有逻辑一致性检查(如索引键重复、外键引用缺失)。耗时通常是全量检查的 1/10,适合日常巡检或怀疑存储层故障时快速定位。
- 若
PHYSICAL_ONLY报错(如Error 824: The operating system returned error 21),基本可判定是磁盘、RAID 卡或 SAN 存储问题,应立即停写并联系基础设施团队; - 它不检查数据逻辑,所以即使通过,也不能保证业务数据正确(例如,一个被误删的订单记录,物理页完好,但逻辑上已消失)。
-- 快速物理层扫描(生产库建议在低峰期执行) DBCC CHECKDB ('MyAppDB') WITH PHYSICAL_ONLY, NO_INFOMSGS, -- 屏蔽 INFO 级别消息,聚焦错误 ALL_ERRORMSGS; -- 输出所有错误详情,不截断输出解读:关注
Msg 89xx开头的错误。823/824/825是 I/O 层错误,指向硬件;8909/8928是页结构损坏,可能需修复;8966是文本/图像页损坏,影响TEXT/NTEXT/IMAGE类型(已弃用,但老库仍有)。
4.2 逻辑深挖:EXTENDED_LOGICAL_CHECKS揭露隐性腐烂
开启EXTENDED_LOGICAL_CHECKS后,CHECKDB会遍历所有索引、约束、统计信息、Service Broker 队列等,验证其逻辑一致性。它会:
- 检查聚集索引键是否唯一、非空;
- 验证非聚集索引行是否能在聚集索引中找到对应记录(即“索引指针悬空”);
- 核对
sysindexes.rowcnt与实际行数是否一致; - 代价巨大:对大表会触发全表扫描,可能引发严重阻塞,建议在维护窗口执行。
-- 全面逻辑检查(务必提前评估影响) DBCC CHECKDB ('MyAppDB') WITH EXTENDED_LOGICAL_CHECKS, DATA_PURITY, -- 检查列值是否符合数据类型定义(如 DATETIME 超出范围) NO_INFOMSGS, ALL_ERRORMSGS;DATA_PURITY 说明:SQL Server 2005+ 默认启用,但旧库升级后需手动运行一次以填充
sys.databases.is_data_purity_clean标志。它能发现DATETIME存储了1900-01-01以外的非法值(如9999-99-99),这类数据在后续版本中可能被拒绝读取。
4.3 修复决策树:REPAIR_FAST、REPAIR_REBUILD、REPAIR_ALLOW_DATA_LOSS的生死线
DBCC CHECKDB本身只诊断,不修复。修复需单独执行DBCC CHECKDB ... WITH REPAIR_xxx,且必须满足:数据库处于单用户模式(SINGLE_USER)、无活动连接、且备份已确认有效(修复前务必再做一次 FULL 备份!)。
| 修复级别 | 作用范围 | 是否丢失数据 | 典型场景 |
|---|---|---|---|
REPAIR_FAST | 仅修复PHYSICAL_ONLY发现的页头/页尾校验和错误 | 否 | 存储层瞬时错误,页内容未损 |
REPAIR_REBUILD | 重建索引、分配单元、统计信息 | 否 | 索引碎片、IAM 链断裂、统计信息损坏 |
REPAIR_ALLOW_DATA_LOSS | 删除损坏页、截断日志、重置分配位图 | 是 | 页数据损坏、LOB 页丢失、关键系统表损坏 |
-- 修复前必做:切单用户 + 强制断开所有连接 ALTER DATABASE [MyAppDB] SET SINGLE_USER WITH ROLLBACK IMMEDIATE; -- 尝试最小侵入修复(仅重建索引) DBCC CHECKDB ('MyAppDB') WITH REPAIR_REBUILD; -- 若失败,再考虑终极方案(警告:可能丢数据!) DBCC CHECKDB ('MyAppDB') WITH REPAIR_ALLOW_DATA_LOSS;REPAIR_ALLOW_DATA_LOSS 警告:它可能删除整页数据(如一个损坏的
PAGE_ID=12345),导致该页上所有行丢失;可能重置IDENTITY列种子;可能破坏FILESTREAM文件关联。执行后必须立即DBCC CHECKDB验证,并对比业务关键表行数、校验和。
5. 备份还原修复的五大避坑指南:那些没写在手册里的血泪现场
备份还原修复看似是标准化操作,但一线工程师踩过的坑,往往藏在文档字缝里。以下是五个高频、高损、教科书不提的真实问题,按“现象 → 原因 → 解决”结构列出,每一条都来自某次深夜救火。
5.1 现象:RESTORE VERIFYONLY通过,但RESTORE DATABASE报错 “The media set has 2 media families but only 1 are provided”
原因:备份时使用了MIRROR TO或多设备备份(如TO DISK='a.bak', DISK='b.bak'),但还原时只指定了其中一个文件。SQL Server 要求所有镜像/分卷文件必须同时提供,缺一不可。
解决:还原命令中必须列出所有备份文件路径,顺序无关,但数量必须严格匹配:
RESTORE DATABASE [MyAppDB] FROM DISK = N'D:\Backup\MyAppDB_FULL_1.bak', DISK = N'D:\Backup\MyAppDB_FULL_2.bak' -- 必须两个都写 WITH REPLACE, NORECOVERY;5.2 现象:还原后数据库状态为RECOVERING,持续数小时不结束
原因:数据库过大(>1TB),且还原时未指定RECOVERY,SQL Server 在后台默默执行UNDO(回滚未提交事务)。若备份前有长事务(如未提交的大批量 DELETE),UNDO阶段会逐条重放日志,极其缓慢。
解决:
① 还原前用DBCC OPENTRAN检查是否有长事务;
② 还原时加STATS = 1观察进度;
③ 若确认可丢弃未提交事务,改用WITH RECOVERY强制跳过UNDO(但需承担数据不一致风险)。
5.3 现象:DBCC CHECKDB报错Error 7909: Database is not accessible,但数据库明明是ONLINE
原因:CHECKDB需要获取数据库的SCH_M(架构修改)锁,若此时有 DDL 操作(如ALTER TABLE、CREATE INDEX)正在执行,或 SSMS 中打开了“查看执行计划”的查询窗口(它会隐式请求架构锁),CHECKDB就会无限等待。
解决:
① 执行sp_who2或sys.dm_exec_requests查找阻塞会话;
② 杀掉阻塞会话(KILL <spid>);
③ 或改用WITH TABLOCK选项,强制CHECKDB获取表级锁而非数据库级锁(仅限PHYSICAL_ONLY)。
5.4 现象:LOG 备份文件越来越大,log_reuse_wait_desc显示LOG_BACKUP
原因:日志备份未成功执行(如备份路径磁盘满、网络存储不可达、权限不足),导致日志无法截断,VLF(虚拟日志文件)持续增长,最终撑爆磁盘。
解决:
① 立即检查msdb.dbo.backupset中最近 LOG 备份记录;
② 若无记录,手动执行一次 LOG 备份(哪怕备份到NUL设备:BACKUP LOG [db] TO DISK='NUL');
③ 长期方案:部署备份成功率监控(查backupset表 +backupmediafamily表)。
5.5 现象:RESTORE HEADERONLY显示Position = 1,但RESTORE DATABASE报错 “File 'xxx' cannot be restored to 'yyy' because it was originally formatted with sector size 4096”
原因:源库和目标库所在存储设备扇区大小不同(如源在 4K 扇区 SSD,目标在 512e 磁盘)。SQL Server 备份文件中硬编码了扇区大小,还原时校验失败。
解决:
① 源库执行SELECT value_in_use FROM sys.configurations WHERE name = 'max server memory (MB)'确认配置;
② 目标服务器 BIOS/RAID 卡中统一扇区大小(推荐全 4K);
③ 或在还原时加WITH CONTINUE_AFTER_ERROR(不推荐,仅应急)。
6. 一个值得坚持的日常习惯:用 T-SQL 脚本自动化验证备份有效性
我见过太多团队,备份策略写得天花乱坠,但从未验证过.bak文件能否真正还原。直到某次勒索病毒加密了所有备份文件,才发现RESTORE VERIFYONLY通过,但RESTORE DATABASE时因CHECKSUM校验失败而中断——因为备份时没开CHECKSUM,病毒加密后文件仍能通过无校验的VERIFYONLY。
现在,我在每个实例上部署一个每日任务:自动抽取一个最小业务表(如SysConfig),还原到临时库,执行SELECT COUNT(*)并比对源库数据量,最后自动清理。整个过程无人值守,失败立即邮件告警。脚本核心逻辑如下:
6.1 自动化验证脚本框架
-- Step 1: 从 msdb 获取最新 FULL 备份路径 DECLARE @backupPath NVARCHAR(500); SELECT TOP 1 @backupPath = mf.physical_device_name FROM msdb.dbo.backupset bs JOIN msdb.dbo.backupmediafamily mf ON bs.media_set_id = mf.media_set_id WHERE bs.database_name = 'MyAppDB' AND bs.type = 'D' -- FULL AND bs.backup_finish_date > DATEADD(day, -2, GETDATE()) ORDER BY bs.backup_finish_date DESC; -- Step 2: 构建还原命令(到临时库 MyAppDB_Verify) DECLARE @sql NVARCHAR(MAX) = N' RESTORE DATABASE [MyAppDB_Verify] FROM DISK = ''' + @backupPath + ''' WITH MOVE ''MyAppDB_Data'' TO ''D:\Data\MyAppDB_Verify.mdf'', MOVE ''MyAppDB_Log'' TO ''D:\Log\MyAppDB_Verify.ldf'', REPLACE, RECOVERY, STATS = 10;'; -- Step 3: 执行还原 EXEC sp_executesql @sql; -- Step 4: 验证关键表行数(假设 SysConfig 表应有 127 行) DECLARE @srcCount INT, @dstCount INT; SELECT @srcCount = COUNT(*) FROM MyAppDB.dbo.SysConfig; SELECT @dstCount = COUNT(*) FROM MyAppDB_Verify.dbo.SysConfig; IF @srcCount <> @dstCount BEGIN RAISERROR('验证失败:SysConfig 行数不一致 %d vs %d', 16, 1, @srcCount, @dstCount); -- 发送邮件告警逻辑... END ELSE BEGIN -- 清理临时库 DROP DATABASE [MyAppDB_Verify]; END为什么选
SysConfig:它通常是小表(<1KB),无外键依赖,无 LOB 字段,还原快、验证快、失败影响小。不验证全库,是因为成本太高;不跳过验证,是因为VERIFYONLY只校验文件头,不校验数据页内容。
6.2 验证脚本的三个硬性要求
| 要求 | 说明 | 不满足后果 |
|---|---|---|
| 必须在独立磁盘路径还原 | 临时库的.mdf/.ldf不能与生产库共用同一磁盘 | 若生产磁盘故障,验证脚本自身也会失败,失去预警能力 |
必须包含CHECKSUM校验 | 备份命令中WITH CHECKSUM是底线,验证脚本不负责备份,只负责还原验证 | 无CHECKSUM的备份,无法检测静默损坏(Silent Corruption) |
必须记录每次验证的backup_set_id | 将msdb.dbo.backupset.backup_set_id写入自定义日志表 | 当某次验证失败时,能精准定位是哪个备份文件损坏,而非笼统说“备份坏了” |
我坚持这个习惯三年,拦截了 7 次备份静默损坏(其中 3 次是存储固件 Bug 导致的页校验和错),2 次是备份路径权限变更,还有 1 次是 DBA 误删了备份保留策略。它不花一分钱,但每次成功预警,都让我少熬一次通宵。希望帮到你。
本文还有配套的精品资源,点击获取