我的家庭实验室设置包括四台服务器,这些服务器在两台物理主机上运行在 HyperV 中。SQL Server 实例是 SQLAG101、SQLAG102、SQLAG201 和 SQLAG202。
SQLAG101 和 SQLAG102 是 SQLAG100 可用性组的成员,并且位于 192.168.0.0/24 网络上。
SQLAG201 和 SQLAG202 是 SQLAG200 可用性组的成员,并且位于 192.168.2.0/24 网络上。
流量在两个子网之间路由,这两个子网都在我的实验室本地(即涉及的延迟非常少)。
SQLDAG 是一个分布式可用性组,跨越 SQLAG100 和 SQLAG200。这已经运行了大约 6 个月,AG 成员服务器之间的自动故障转移和两个 AG 之间的手动故障转移都正常工作,并且没有数据丢失。
在我的测试服务器上,我在我的 Distributed AG Forwarder 上看到以下错误FILESTREAM
:
操作系统在“F:\SQLServer\HV2019\FILESTREAM\dag_test_db\dag_test_db_fg_fs_f01\3e6a0757-7405-4ee2-b8a8-df878b8cd7ce\a10e3ae8”上尝试“CreateFileW”时返回错误“2(系统找不到指定的文件。)” -922c-4821-904e-7555c031630d\0000008f-000292b0-0006' 在 'fsdohdlr.cpp' (2474)。
数据库“dag_test_db”的 Always On 可用性组数据移动已暂停,原因如下:“系统”(源 ID 3;源字符串:“SUSPEND_FROM_CAPTURE”)。要恢复数据库上的数据移动,您需要手动恢复数据库。有关如何恢复可用性数据库的信息,请参阅 SQL Server 联机丛书。
(喜欢 Books Online 参考,顺便说一句)
为了排除故障,我已经完全dag_test_db
从转发器和次要转发器中删除了。dag_test_db
然后,我从主数据库中获取了完整备份,并将其恢复到转发器,并在将备份添加回转发器可用性组之前根据需要通过恢复日志备份进行前滚ALTER DATABASE [dag_test_db] SET HADR AVAILABILITY GROUP = SQLAG200;
最初,转发器 AG (SQLAG200) 的可用性组仪表板显示数据库正在同步,但大约一个小时后显示同步状态NOT SYNCHRONIZING
并且同步健康原因描述显示SUSPEND_FROM_CAPTURE
。
chkdsk /f
在 F: 驱动器上运行不会报告任何错误。
dbcc checkdb (dag_test_db)
从主要返回没有错误。
我写了一个查询来从文件流中读取所有数据;也许这会显示一些有趣的东西。获得该测试的结果后,我将更新问题。查询使用ApplicationIntent=ReadOnly
通过 sqlcmd.exe 连接到转发器实例。这是查询,对于那些感兴趣的人:
USE [dag_test_db];
GO
DECLARE @d varbinary(max);
DECLARE @f nvarchar(260);
DECLARE cur CURSOR LOCAL FORWARD_ONLY READ_ONLY
FOR
SELECT
[f].[file_data]
, [f].[original_file_name]
FROM [dbo].[files] [f];
OPEN cur;
FETCH NEXT FROM cur INTO @d, @f;
WHILE @@FETCH_STATUS = 0
BEGIN
PRINT @f + N': ' + CONVERT(nvarchar(11), LEN(@d), 0);
FETCH NEXT FROM cur INTO @d, @f;
END
CLOSE cur;
DEALLOCATE cur;
也许一些勇敢的年轻 Microsoft 工程师可以帮助我理解是什么导致了错误fsdohdlr.cpp at 2474
?
DBCC CHECKDB ([dag_test_db]) WITH NO_INFOMSGS;
在全球主要显示没有腐败。
将报错信息中的文件名转换为十进制的LSN,fn_dblog
在global primary上使用显示日志内容显示:
当前LSN | 手术 | 语境 | 交易编号 | 日志块生成 | 标记位 | 日志记录固定长度 | 日志记录长度 | 以前的LSN | 标志位 | 原木储备 | AllocUnitId | 分配单位名称 | 页面编号 | 插槽编号 | 上一页LSN | 分区ID | 行标志 | Num Elements | Offset in Row | Modify Size | Checkpoint Begin | CHKPT Begin DB Version | Max XDESID | Num Transactions | Checkpoint End | CHKPT End DB Version | Minimum LSN | Dirty Pages | Oldest Replicated Begin LSN | Next Replicated End LSN | Last Distributed Backup End LSN | Last Distributed End LSN | Repl Min Hold LSN | Server UID | SPID | Beginlog Status | Xact Type | Begin Time | Transaction Name | Transaction SID | Parent Transaction ID | Oldest Active Transaction ID | Xact ID | Xact Node ID | Xact Node Local ID | End AGE | End Time | Transaction Begin | Replicated Records | Oldest Active LSN | Server Name | Database Name | Mark Name | Master XDESID | Master DBID | Preplog Begin LSN | Prepare Time | Virtual Clock | Previous Savepoint | Savepoint Name | Rowbits First Bit | Rowbits Bit Count | Rowbits Bit Value | Number of Locks | Lock Information | LSN before writes | Pages Written | Command Type | Publication ID | Article ID | Partial Status | Command | Byte Offset | New Value | Old Value | New Split Page | 行已删除 | 字节释放 | CI 表 ID | CI 索引 ID | NewAllocUnitId | 文件组编号 | 元状态 | 文件状态 | 文件编号 | 物理名称 | 逻辑名称 | 格式化LSN | 行集ID | 文本指针 | 列偏移 | 旗帜 | 字体大小 | 抵消 | 旧尺寸 | 新尺寸 | 描述 | 批量分配的盘区数 | 批量 RowsetId | 批量 AllocUnitId | 批量分配第一个 IAM 页面 ID | 批量分配的区段 ID | 添加了 VLF | 无效缓存 ID | 使缓存键无效 | CopyVerionInfo 源页面 ID | CopyVerionInfo 源页面 LSN | CopyVerionInfo 源插槽 ID | CopyVerionInfo 源插槽计数 | 行日志内容 0 | RowLog 内容 1 | RowLog 内容 2 | RowLog 内容 3 | RowLog 内容 4 | RowLog 内容 5 | 压缩日志类型 | 压缩信息 | 页面格式页面类型 | PageFormat PageFlags | 页面格式页面级别 | PageFormat PageStat | PageFormat 格式选项 | 日志记录 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0000008F:000292B0:0006 | LOP_FS_DOWNLEVEL_OP | LCX_NULL | 0000:0022f09f | 0 | 0x0000 | 24 | 360 | 0000008F:000292B0:0005 | 0x0002 | 366 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | 无效的 | Operation CREATE;File Id 65537;Name 3e6a0757-7405-4ee2-b8a8-df878b8cd7ce\a10e3ae8-922c-4821-904e-7555c031630d\0000008f-000292b0-0006 | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | NULL | 0x000018008F000000B0920200050002009FF022000000910001004A01010000007000C00001000000010001000000000000000000000046003A005C00530051004C005300650072007600650072005C004D005300530051004C00310035002E004800560032003000310039005C004D005300530051004C005C0044004100540041005C006400610067005F0074006500730074005F00640062005F00660067005F0066007300330065003600610030003700350037002D0037003400300035002D0034006500650032002D0062003800610038002D006400660038003700380062003800630064003700630065005C00610031003000650033006100650038002D0039003200320063002D0034003800320031002D0039003000340065002D003700350035003500630030003300310036003300300064005C00300030003000300030003000380066002D00300030003000320038006600360038002D0030003000310030000001 |
错误消息中引用的文件确实存在于转发器的文件系统中:
C:\Users\Hannah>目录 F:\SQLServer\HV2019\FILESTREAM\dag_test_db\dag_test_db_fg_fs_f01\3e6a0757-7405-4ee2-b8a8-df878b8cd7ce\a10e3ae8-922c-4821-904e-7555c0316 30d\0000008f-000292b0-0006 驱动器 F 中的卷没有标签。 卷序列号是 90BA-CEC3 F:\SQLServer\HV2019\FILESTREAM\dag_test_db\dag_test_db_fg_fs_f01\3e6a0757-7405-4ee2-b8a8-df878b8cd7ce\a10e3ae8-922c-4821-904e-7555c031630d目录 2023 年 4 月 28 日晚上 10:27 797,346 0000008f-000292b0-0006 1 文件 797,346 字节 0 目录 123,663,937,536 字节空闲
icacls
对于转发器上的相关路径显示:
icacls F:\SQLServer\HV2019\FILESTREAM\dag_test_db\dag_test_db_fg_fs_f01\3e6a0757-7405-4ee2-b8a8-df878b8cd7ce\a10e3ae8-922c-4821-904e-7555c031630d F:\SQLServer\HV2019\FILESTREAM\dag_test_db\dag_test_db_fg_fs_f01\3e6a0757-7405-4ee2-b8a8-df878b8cd7ce\a10e3ae8-922c-4821-904e-7555c031630d NT SERVICE\MSSQL$ HV2019:(I)(OI)(CI)(F ) 所有者权利:(I)(OI)(CI)(F) 内置\管理员:(I)(OI)(CI)(F) 成功处理1个文件;处理 0 个文件失败
从我所看到的来看,权限看起来不错——SQL Server 服务作为对文件的完全控制,实际上整个文件夹结构来自F:\SQLServer\HV2019
.
我无法最终确定根本原因是什么
SUSPEND_FROM_CAPTURE
。显然,此状态表明转发器(或辅助设备)无法再以允许辅助设备跟上主设备的方式从主设备读取日志流。为了在转发器上解决这个问题,我从 SQLAG200 可用性组主数据库(即转发器)中删除了数据库,然后将其从 SQLAG200 可用性组的辅助数据库中删除。然后,我从 SQLAG200 辅助数据库和 SQLAG200 主数据库上的备份恢复数据库,确保恢复适用的事务日志备份,以使数据库的每个副本尽可能接近 SQLAG100 数据库的全局主副本中的状态。恢复完成后,我可以通过以下方式让转发器赶上全局主节点:
这将新恢复的数据库关联到转发器可用性组,并通过分布式可用性组扩展到全局主要可用性组。
货运代理上船后,我在二级货运代理上执行了以下操作:
最后,它看起来很稳定。我从这一切中得到的收获是,数据库的主副本在任何时候都不会脱机,或者对我的 C# Filestream 测试客户端不可用。它只是继续将文件写入
dag_test_db
文件流文件组。这可能需要一段时间,但只要主服务器在线,业务就不会太糟糕。我很高兴有这样的家庭实验室设置,我可以在这些问题影响实际生产数据库之前练习如何处理这些问题。
Microsoft CSS 有一个未记录的跟踪标志,可在 SQL Server 启动时使用它来禁用多个日志流,这是 SQL Server 2022 中的一项新功能。在我的例子中,启用该跟踪标志解决了问题;删除跟踪标志导致问题几乎立即重现。