5

我们在生产系统中有一张表(出于遗留原因),它正在运行 SQL 2005 (9.0.5266) 并包含一个 TEXT 列(以及其他一些不同数据类型的列)。

突然之间(从一周前开始),我们注意到这张表的大小每天线性增加 10-15GB(而以前它一直保持不变的大小)。该表是消息传递系统的队列,因此其中的数据每隔几秒钟就会完全刷新一次。在任何时候都可能有 0 到大约 1000 行,但随着消息的插入和发送(此时它们被删除),它会迅速波动。

我们找不到在增长开始那天发生的任何变化——因此在这个阶段没有发现明显的潜在原因。

一个“明显”的罪魁祸首是 TEXT 列,因此我们检查了是否现在存储了任何大量值,但是(使用 DATALENGTH)我们发现没有超过约 32k 的单行。我们已经运行了 CHECKDB,更新了空间使用情况,重建了所有索引,等等——没有任何东西可以减少大小(CHECKDB 没有显示任何错误)。

我们查询了 sys.allocation_units 并且大小增加肯定是 LOB_DATA (显示 total_pages 和 used_pa​​ges 以恒定速率一起增加)。

为了减少昨晚的数据库大小,我们简单地在有问题的表旁边创建了一个新表(幸运的是,应用程序通过视图引用了该表),删除了旧表,并重命名了新表。我们昨晚离开了,因为我们已经缓解了空间问题而感到欣慰,并且我们今天有一张狡猾的桌子的备份可以进一步调查。然而,今天早上,表的大小已经达到 14GB(并且还在增长),而表中只有通常的 ~500 行,而 MAX(DATALENGTH(text_column)) 仅显示大约 35k。

关于什么可能导致这种“失控”增长的任何想法,或者我们可以尝试或查询的任何其他信息以获取有关究竟是什么在使用该空间的更多信息?

干杯,戴夫

4

2 回答 2

1

这是处理队列时的普遍问题。链接的文章讨论了 Service Broker 队列,但对于用作队列的普通表,问题是相同的。如果你有一个繁忙的系统,拥有大量资源(CPU、内存、磁盘 IO)并且你在这个系统上推送一个队列以达到高吞吐量,那么这些资源的很大一部分将用于处理这两个操作:入队(即 INSERT )和出队(即删除)。但是,记录的整个生命周期需要三个操作:INSERT、DELETE 和幽灵清除。它们在 CPU/内存/磁盘 IO 需求方面的成本大致相同,因此如果您将该队列用于 90% 的系统资源,那么您应该为每个队列分配 30% 的资源。但只有前两个在您的控制之下(即在用户会话中运行的显式语句)。第三个,ghost purge,是一个由 SQL Server 控制的后台进程,不可能允许 ghost 清理进程消耗 30% 的资源。这是一个基本问题,如果您将踏板踩到金属足够长的时间,您的 *就会撞到它。一旦幽灵记录累积并超过系统/工作负载特定阈值,性能将迅速下降,并且症状将螺旋式上升至糟糕的性能(形成负反馈循环)。

幸运的是,由于您不使用 Service Broker 队列,而是使用真实表作为队列,因此您可以使用一些更好的工具,例如ALTER TABLE REORGANIZEALTER TABLE REBUILD. 到目前为止,最好的解决方案是在线索引/表重建。SQL Server 2012 支持对包含 BLOB 的表进行在线操作,您可以利用它。当然,您必须摆脱已弃用的过时TEXT类型和 use VARCHAR(MAX),但这并没有说。

作为旁注:

如果您的页面上只有幽灵记录,那么您将不会再次阅读这些页面,并且它们不会被标记为清理

这是不正确的。只有重影的页面将被扫描检测并清除。正如我所说,问题不在于检测,而在于资源。如果您足够推动您的系统,您将领先于幽灵清理,而他将永远赶不上。

于 2012-08-17T12:04:34.890 回答
0

今天一大早,我用这个“问题队列表”重新启动了实例上的 SQL 服务。看来这已经解决了这个问题。重新启动后,我立即监控了 LOB_DATA 页面使用计数,它立即开始下降。它的清理速度很慢,所以可能需要大约一两个小时才能收回 60+GB 的空间(在确保一切正常后我就上床睡觉了)。

目前,就使用中的分配而言,该表已恢复正常(悬停在 <100 页左右),并且没有显示任何重新增长的迹象。

考虑到我们以同样的方式(即作为队列)使用这张桌子至少 10 年了,而且它比过去一两周更繁忙,我会感到惊讶如果是上面 Remus 描述的问题(尽管我理解这是怎么发生的;我猜这个特定的队列还不够忙,不足以淹没幽灵清理过程?)。很奇怪...

再次感谢各位的帮助!

于 2012-08-20T22:10:02.563 回答