SQL Server DB在一夜之间变得无法使用


9

昨天,我的SQL Server数据库很好。如今,它几乎无法使用-减慢了5到20倍,具体取决于我何时按下它。

在通宵的加载过程中,一些数据已添加到服务器,但没有什么比对数据库有很大影响的卷更是如此。大约50,000条纯文本记录(没有XML或其他轻率的记录)。

该服务器已在今天早晨修补后重新启动。但是,我们所有其他也已打补丁的数据库服务器的行为都不相同。

资源监视器似乎暗示其磁盘IO有故障。即使在数据库中没有实际发生任何事情时,它始终在.mdf文件上以接近100%的容量运行。对Templog.ldf的访问也非常高。

这里没有人是专家DBA(我们都是拥有不同SQL技能的开发人员),我们都对发生的事情感到困惑。我们尝试运行sp_updatestats并将一些大索引移到不同的光盘上,但无济于事。

我认为这一定与补丁有关-似乎太多的巧合。一位同事确信,由于数据负载导致mdf的大小增加到导致执行计划变得效率低下的程度。

到底是什么原因造成的?我们如何找出答案,我们该如何解决?

编辑:

使用sp_WhoIsActive不会显示任何异常。它记录了我自己对sproc的使用以及来自当前正在尝试移动另一个索引的同事的一些命令。那可能现在正在支撑数据库,但是它之前运行得很差。

它是SQL Server 2008 R2的标准版本。SELECT @@VERSION给出:

Microsoft SQL Server 2008 R2(SP2)-10.50.4033.0(X64)
2014年7月9日
版权所有(c)Windows NT 6.1(Build 7601:Service Pack 1)上的Microsoft Corporation标准版(64位)(Hypervisor )

该服务器具有72GB的RAM和三个四核2GHz处理器。

该修补程序仅适用于Windows。除补丁外,没有其他更改。

所选设置:

_id     name                        value   minimum     maximum     value_in_use    description                                 is_dynamic  is_advanced
1540    min memory per query (KB)   1024    512         2147483647  1024            minimum memory per query (kBytes)           1           1
1541    query wait (s)              -1      -1          2147483647  -1              maximum time to wait for query memory (s)   1           1
1543    min server memory (MB)      0       0           2147483647  16              Minimum size of server memory (MB)          1           1
1544    max server memory (MB)      65536   16          2147483647  65536           Maximum size of server memory (MB)          1           1

更新:将索引和表转移到不同的磁盘分区似乎正在改善情况。我仍然对如何达到临界点感到困惑,所以突然有了如此惊人的结果。


您可以将sp_whoisactive运行5分钟并将输出捕获到表中吗?您可以从此处下载它,这将显示如何将输出捕获到表中
Kin Shah 2015年

好吧,如果重新启动服务器,则意味着所有缓存数据都已从缓冲池中转储,并且所有缓存执行计划也已转储。这意味着SQL Server将必须同时提高两者-每个执行计划都必须重新编译,并且如果统计数据陈旧,则可能无法获得最有效的计划。这也意味着必须将数据从磁盘读取到内存中,而在重新启动之前,它可能与内存中的数据一起嗡嗡作响。这应该是短暂的。
亚伦·伯特兰

@AaronBertrand像这样已经八个小时了。我们会定期重新启动服务器以进行修补,以前从未发现过类似的情况。
Bob Tway

1
不要使用UI来检查配置设置。SELECT * FROM sys.configurations;-您想要value, value_in_use类似的东西max server memory (MB)。此外,内部版本号SELECT @@VERSION;以及该版本是否在虚拟机管理程序中以及自昨天(或自上次SQL Server上次重新启动以来)以来主机上是否发生任何更改都将很有用。
亚伦·伯特兰

2
您正在使用哪种类型的IO子系统?SAN,本地磁盘等?您是否偶然有驱动器损坏?另外,您的任何数据库是否与任何OS文件存储在同一位置?还有最后一个问题。在进行操作系统升级之前,我们过程的一部分是预先制作VM快照。不幸的是,负责人忘记了提交。整个系统很快变得越来越慢。这有什么可能发生在你身上吗?
肯尼斯·费舍尔

Answers:


3

可能会发生少量数据达到SQL Server中的某个限制以强制执行其他计划或类似情况的情况。这并非不可能。但是,您的光盘似乎负担很重,这一事实使我得出另一个结论。

您放慢速度的可能有两个基本原因。

  1. 您已升级系统并重新启动
  2. 您在其中加载了一堆数据

让我们看一下第一部分

您的SQL Server配置可能已损坏。这可能会导致有关服务器速度和光盘使用情况的严重问题。

请首先检查您的基本服务器设置。这些基本设置是max server memoryaffinity I/O maskaffinity maskmax degree of parallelism。您可能需要使用启用高级选项show advanced options

这是一个完整的脚本:

-- enable advanced options
EXEC sp_configure 'show advanced options',1
-- apply configuration
RECONFIGURE
-- how much memory can the sql server allocate?
EXEC sp_configure 'max server memory'
-- which cpu is used to run I/O operations
EXEC sp_configure 'affinity I/O mask'
-- which cpus can run processes?
EXEC sp_configure 'affinity mask'
-- how many threads can work on one query part?
EXEC sp_configure 'max degree of parallelism'

将结果与您在安装步骤中记录的值进行比较。他们还是一样吗?

服务器行为如此奇怪可能有很多原因。我通常会打赌,你max server memory错了。这将导致您的SQL Server永久交换数据页。他无法将所有东西都保存在他的记忆中。这意味着他需要从光盘中读取页面,对其进行更新,然后立即将其写回。如果出现另一个更新,并且使用同一页面进行更新,则无法从内存中读取该更新。相反,服务器需要再次从光盘读取它。只是交换...

另一个问题可能是磁盘或进程之间的亲和力很高。如果您使用共享服务器(SQL Server以及其他服务)和专用于SQL Server的光盘(这种情况很少见,但是可能),这可能是您的问题。您的服务器通常以前有3个cpus用于进程,一个有I / O。其他12个cpus用于其他服务。在这种情况下,您的相似性掩码是错误的,例如使用自动配置。这意味着您的服务器动态地将所有16个内核用于进程和I / O。如果您正在运行大量进程,则它们可能会在光盘上造成巨大负担,而光盘可能无法处理。但实际上,我不认为这是您的情况。如果可以的话,它会更快(即使只是一点点),但是您的情况会变慢。

另一个问题可能是并行度太高。这意味着您在查询的一个部分上有太多线程空转。如果并行性无法按预期工作,这也可能导致极大的速度降低。但这并不能说明您的总体I / O高。

现在我们也来看看第二部分

您将一堆行加载到系统中。即使这是一项常规工作,也可能会限制查询计划的升级。甚至可能是您的插入与SQL Server组合产生此行为的情况。

悠悠提到您已经尝试将索引迁移到另一张光盘,这似乎有所帮助。这可能是由于您将负载分配到两个不同的光盘上而发生的。

可能是您的索引破裂,您的计划破裂或统计数据刚刚过时。

1.让我们检查统计信息的最新更新 您可以在界面上针对每个单个统计信息元素手动执行此操作。那样会很痛苦。或者您可以尝试以下代码:

SELECT name AS indexname,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes

这将为您提供有关每个索引(和堆)及其背后统计信息的完整信息。即使您运行sp_updatestats它也不意味着统计信息已更新。当您进行更新时,即使您运行sp_updatestatsauto update statistics启用该更新也非常棘手,该统计信息不会及时更新。当需要/生成更新时,这是一些要点:

  • 空表将获得一行或多行
  • 具有多于500行的表将更新20%+ 500多行,此后发生插入
  • 当在少于500行的表中更改500行时

这意味着,即使您运行更新,您的统计信息也可能已过时。

您可以看一下上面的查询。如果您在某些表中发现了一些非常旧的统计信息,则可能要为此表运行手动统计信息更新:

UPDATE STATISTICS dbo.YourBadTable WITH FULLSCAN

之后,您可能希望让服务器发挥作用,以丢弃所有旧计划。

DBCC FREEPROCCACHE 

如果您只想清除所有缓存,则可能要运行以下命令:

DBCC FREESYSTEMCACHE ('ALL')

这将清除所有缓存,而不仅仅是计划缓存。我通常会警告,在生产阶段在生产服务器上使用它。但是,由于您的服务器目前无法正常工作,因此不能对它们造成太大的损害。由于他需要重建所有缓存,因此它可能会减慢几秒钟,可能需要1-2分钟,但是在此之后,他应该按照正确的计划运行。

另一个原因可能是索引完全碎片化。可以使用以下语句在整个服务器上进行检查:

SELECT * 
FROM sys.dm_db_index_physical_stats (NULL, NULL, NULL, NULL, NULL)

如果碎片很大,则可能需要重新组织(碎片<20%)或完全重建(> 20%)。这可能会给光盘带来更大的压力并引起麻烦。另一方面,如果指数那么糟糕,那么最终可能会带来更大的帮助,而不是有害的。

除了这两个原因,仍然可能存在第三个问题

可能您的服务器已配置好,这一次您没有更改任何代码,仅添加了几行。所有统计信息均已更新,所有缓存均已重建。您所有的索引都按照您需要的方式进行了重组,但是仍然没有任何效果。可能只是您在进程中达到了可用内存的限制。也许您需要更多。您可以简单地检查是否有任何尝试获取比您更多的内存的进程。

您可以使用以下命令检查此内容:

SELECT * FROM sys.dm_exec_query_memory_grants

它将为您提供所有消耗内存的会话的列表。可能有一些查询仍在等待获取内存。这些查询可以轻松过滤。所有会话都在哪里granted_memory_kb IS NULL。这些是需要内存但没有获取内存的会话。另一件事可能是授权内存,该内存可能不足。您可以将列requested_memory_kb与进行比较granted_memory_kb。请求显示进程需要多少内存才能最佳运行,而被授予则显示为进程启用的内存。如果一个进程需要2GB才能运行,但仅需要2MB,则...您可以自己获取它。;-)

另一种方法是检查RESSOURCE_SEMAPHORE

SELECT * FROM sys.dm_exec_query_resource_semaphore

您可以看一下waiter_countgrantee_count。如果服务员的压力大于0,则您的内存压力很大,这可能会导致交换,并可能导致您在性能监视器中看到光盘压力。


0

除了可能的驱动器故障外,请检查RAID子系统的状态。我们看到了类似的情况,结果发现RAID控制器上的电池出现故障,因此没有可用的写缓存-所有写操作都必须直接进入磁盘。旁注-当RDC进入系统时,我们可能会感到系统暂停。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.