我们有一个 SQL Server 2016 (v13 SP3) 企业版服务器托管在 Windows 故障转移群集/SQL 可用性组中,具有两个节点(主节点和辅助节点)。这两个节点在运行 Windows Server 2012 R2 64 位 (NT 6.3) 的 AWS EC2 实例内运行。
本周早些时候,服务器开始响应此错误:
Could not allocate space for object 'dbo.Batches'.'pk_Batches_BatchID' in database 'XXX' because the 'PRIMARY' filegroup is full. Create disk space by deleting unneeded files, dropping objects in the filegroup, adding additional files to the filegroup, or setting autogrowth on for existing files in the filegroup.
起初,这似乎非常简单:我们认为我们粗心并允许数据和/或日志文件变得太大。这些文件肯定已满,其中没有任何未分配的空间。我们认为我们只需要扩展 Windows (NTFS) 驱动器(由 AWS EBS 在后台支持)。“XXX”数据库有一个日志文件和两个数据文件 - 数据文件设置为无限增长(尽管一次只能增长 64MB),并且数据库只有默认的“PRIMARY”文件组,不涉及其他文件组。数据文件位于“D:”驱动器上。
但“D:”驱动器有超过 400 GB 的可用空间,那么为什么数据文件没有增长呢?
我们花了很多时间查看 Windows 集群和 SQL 可用性组,因为我们还看到大量有关 AG 状态进入“正在恢复”状态以及集群角色未正确应用/同步的错误。一些更改允许主节点恢复几分钟,但随后它会再次崩溃。(因此,我们检查“XXX”数据库本身的能力受到限制。)我们查看了 EBS 是否存在某种问题或中断,但没有发现任何错误。
我们意识到服务器已经过时且陈旧。我们意识到有些人会说使用/依赖自动增长是一种不好的做法。但这个问题与最佳实践无关——而是我们如何让这个当前关闭的生产服务器恢复正常运行?
解决方案是添加另一个数据文件!
由于节点的快速升降,我们不得不将其重新打开(Windows集群中的“启动角色”),然后急于执行这个命令:
ALTER DATABASE [XXX] ADD FILE ( NAME = N'XXX3', FILENAME = N'D:\DATA\XXX3.mdf' , SIZE = 1110884352KB, FILEGROWTH = 65536KB ) TO FILEGROUP [PRIMARY]
(通过 UI 执行此操作太慢。)
一旦我们这样做了,问题就消失了,服务器/集群保持正常运行!
(我们事先确实增加了驱动器/卷的大小。)
我无法充分解释为什么这有效。弄清楚这一点的人表示,微软曾经告诉他,这是由 NTFS 中的一个错误引起的,该错误不会让文件在某些条件下增长。我在任何地方都找不到任何相关信息,所以我不知道这是否属实。
这里似乎确实存在一个常见的误解(我也有)。显然,文件组中的文件会单独增长的想法是错误的。实际上,自动增长事件将同时扩展文件组中的每个文件。这是有道理的,但它似乎没有解释任何事情:这似乎只是意味着数据库引擎试图获取 128 MB 而不是 64 MB,而 64 MB 的空间已经足够了。
现在,两个数据文件的大小不同:第一个文件为 2,161,928MB (~2TB),第二个文件为 1,084,912MB (~1TB)。有关增长文件组的比例填充算法如何工作的信息表明,这可能导致引擎请求 192 MB,甚至 256 MB。但同样,两者都小于 400 GB。
文件组增长行为与跟踪标志 1117 和 1118之间存在关系。根据记录,这两个跟踪标志均未在此服务器上启用。(仅供参考,您可以使用 检查这一点
DBCC TRACESTATUS
。)我一直无法确定 SQL Server 服务是否是使用-E
(增加范围)选项启动的。无论如何,引擎似乎正在尝试分配比自动增长设置建议的多得多的文件空间。只有添加另一个数据文件并有效地避免自动增长,我们才能扩展数据库大小并使其恢复正常。
我一直在咒骂“不准确/误导性”错误消息,但它就在那里说:
Create disk space by ...
adding additional files to the filegroup
我们应该从一开始就这样做。