一、当镜像变成"单相思"——事故现象诊断
某金融公司周五下午3点,主数据库突然报错:"无法与镜像服务器建立连接"。DBA小张发现两地机房间的网络设备出现闪断,此时:
- 主体数据库显示状态为"已断开"
- 镜像数据库处于"正在恢复"状态
- 事务日志堆积量达到15GB
- 应用程序开始向日志写入大量超时错误
-- 查看镜像状态查询(需在主库执行)
SELECT
database_id,
mirroring_state_desc,
mirroring_safety_level_desc,
mirroring_partner_instance
FROM sys.database_mirroring
WHERE database_id = DB_ID('FinanceDB');
/* 返回结果示例:
database_id | mirroring_state_desc | mirroring_safety_level_desc | mirroring_partner_instance
-----------------------------------------------------------------------------------------
5 | DISCONNECTED | FULL | TCP://mirror01:5022
*/
此时最危险的情况是:当网络恢复后,如果处理不当可能导致数据丢失或日志损坏。去年某电商就曾因此丢失2小时交易数据,教训深刻。
二、断网恢复四步急救法(基于SQL Server 2019)
2.1 第一步:网络层体检
# 测试双向网络连通性(需在主体服务器执行)
Test-NetConnection -ComputerName mirror01 -Port 5022
# 检查防火墙规则
Get-NetFirewallRule -DisplayName "SQL Mirroring*" | Format-Table Name,Enabled
# 示例输出:
# Name Enabled
# ---- -------
# SQL_Mirror_Port True
特别注意:跨机房的网络抖动往往伴随MTU设置问题,可通过以下命令检测:
ping -f -l 1472 mirror01
2.2 第二步:安全模式下的紧急同步
当使用高安全模式(High Safety)时,需特别注意事务日志的保留策略:
-- 强制切换安全模式(仅在紧急情况下使用)
ALTER DATABASE FinanceDB SET PARTNER SAFETY OFF;
-- 检查日志复用情况
DBCC SQLPERF(LOGSPACE);
-- 示例结果:
-- Database Name Log Size (MB) Log Space Used (%)
-- FinanceDB 20480 98.76
此时如果日志即将填满,必须立即执行日志备份:
BACKUP LOG FinanceDB TO DISK = 'E:\Backup\FinanceDB_emergency.trn'
WITH COMPRESSION, FORMAT;
2.3 第三步:镜像重连的生死时速
重连操作就像给病人做心脏复苏,必须严格按照顺序:
-- 在主体服务器执行
ALTER DATABASE FinanceDB SET PARTNER RESUME;
-- 在镜像服务器执行
ALTER DATABASE FinanceDB SET PARTNER RESUME;
-- 验证恢复进度
SELECT
database_name = DB_NAME(database_id),
redo_rate_KB_per_sec =
(redo_queue_size * 8) / NULLIF(DATEDIFF(second, last_redo_time, GETDATE()),0),
mirroring_state_desc
FROM sys.dm_db_mirroring;
注意!如果遇到错误1412(超时),可尝试重置端点:
-- 重建端点(需在双方执行)
CREATE ENDPOINT Mirroring
STATE = STARTED
AS TCP (LISTENER_PORT = 5022)
FOR DATABASE_MIRRORING (ROLE = PARTNER);
2.4 第四步:数据一致性验证
使用DBCC校验数据完整性:
DBCC CHECKDB('FinanceDB') WITH
ALL_ERRORMSGS,
NO_INFOMSGS,
DATA_PURITY;
当发现页级损坏时,可通过镜像数据库进行页面还原:
-- 从镜像恢复单个页面
RESTORE DATABASE FinanceDB
PAGE = '1:154'
FROM MIRROR PARTNER;
三、实战中的魔鬼细节
3.1 自动故障转移的陷阱
某次网络中断后自动切换成功,但实际存在数据差异:
-- 检测未提交事务
SELECT
transaction_id,
database_transaction_log_bytes_used
FROM sys.dm_tran_database_transactions
WHERE database_id = DB_ID('FinanceDB');
此时必须使用日志传送进行数据补偿:
-- 应用增量日志
RESTORE LOG FinanceDB
FROM DISK = 'E:\Backup\FinanceDB_log_001.trn'
WITH NORECOVERY;
3.2 性能优化急救包
网络恢复初期容易遇到IO瓶颈:
-- 调整异步提交模式的批量大小
ALTER DATABASE FinanceDB SET PARTNER TIMEOUT 15;
监控关键性能计数器:
Get-Counter -Counter "\SQLServer:Database Mirroring(*)\*" -SampleInterval 2
四、技术选型中的生存智慧
4.1 何时选择数据库镜像?
- 跨地域的DR解决方案(100公里内)
- 需要秒级故障转移的OLTP系统
- 预算有限的HA方案(相比AlwaysOn节省30%成本)
4.2 镜像技术的阿喀琉斯之踵
某物流公司曾因以下配置错误导致数据丢失:
-- 错误示例:错误的安全模式切换
ALTER DATABASE OrderDB SET PARTNER SAFETY FULL; -- 应在两端执行
正确做法应通过配置管理器修改,并验证伙伴优先级:
SELECT
role_desc,
partner_server,
partner_priority
FROM sys.database_mirroring_endpoints;
五、灾备体系的最后防线
建议每季度执行断网演练:
- 随机断开镜像网络接口
- 制造10%数据写入负载
- 30分钟后恢复网络
- 测量RTO(恢复时间目标)和RPO(恢复点目标)
某银行通过该方法将RPO从15分钟缩短到47秒。
六、写给架构师的备忘录
- 网络延迟超过5ms时考虑异步模式
- 日志磁盘应保证至少20%的剩余空间
- 定期清理镜像监控历史表:
DELETE FROM msdb.dbo.mirroring_history
WHERE backup_finish_date < DATEADD(month, -3, GETDATE());
总结:与不确定性的持久战
通过某证券公司的真实案例:他们在2022年经历7次网络中断,但通过完善的恢复策略实现零数据丢失。关键要素包括:
- 实时网络质量监控(延迟>2ms自动告警)
- 双活日志传送通道(主备各保留3份日志)
- DBA团队的"肌肉记忆"训练(每月实战演练)
记住:数据库镜像不是银弹,而是需要配合网络层HA、存储层快照的复合型方案。当遇到持续断网超过TTL(生存时间)时,必须启动应急决策流程——这可能是DBA职业生涯中最艰难但最重要的判断时刻。