SQL Server 2008标准版中,主文件组因无明显原因而已满。

48

我们的数据库目前达到了64 GB,其中一个应用程序出现了以下错误:

System.Data.SqlClient.SqlException: Could not allocate space for object 'cnv.LoggedUnpreparedSpos'.'PK_LoggedUnpreparedSpos' in database 'travelgateway' 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.

我仔细检查了一切:单个文件组中的所有文件都允许自动增长,增量合理(数据文件为100 MB,日志文件为10%),数据库有超过100 GB的可用空间,tempdb也设置为自动增长,并且其驱动器上有足够的空闲硬盘空间。

为解决问题,我向文件组添加了第二个文件,错误已经消失。但整个情况让我感到不安。

各位大佬,这里有什么问题?


1
而且没有指定最大文件大小吗? - Damir Sudarevic
10个回答

28

好的,搞定了。原来问题出在NTFS卷上,那里存放了数据库文件,被严重碎片化了。停止SQL Server,对整个卷进行了碎片整理,从此一切都好了。


谢谢,今天醒来也要解决同样的问题,而对数据文件(.mdf)进行碎片整理修复了它。我使用Defraggler。 - dtbarne
我遇到了同样的问题,在运行磁盘碎片整理程序后,解决了数据文件存储的问题!谢谢。 - Erick Sasse

19

安东,

作为最佳实践,不应该在主文件组中创建用户对象。当你有空余时间时,请创建一个新的文件组并将用户对象移动到其中,保留系统对象在主文件组中。

下面的查询将帮助你识别每个文件中使用的空间以及具有最高行数和堆积表的顶级表格,这是一个好的起点来调查此问题。

SELECT  
ds.name as filegroupname
, df.name AS 'FileName' 
, physical_name AS 'PhysicalName'
, size/128 AS 'TotalSizeinMB'
, size/128.0 - CAST(FILEPROPERTY(df.name, 'SpaceUsed') AS int)/128.0 AS 'AvailableSpaceInMB' 
, CAST(FILEPROPERTY(df.name, 'SpaceUsed') AS int)/128.0 AS 'ActualSpaceUsedInMB'
, (CAST(FILEPROPERTY(df.name, 'SpaceUsed') AS int)/128.0)/(size/128)*100. as '%SpaceUsed'
FROM sys.database_files df LEFT OUTER JOIN sys.data_spaces ds  
    ON df.data_space_id = ds.data_space_id;

EXEC xp_fixeddrives
select  t.name as TableName,  
    i.name as IndexName, 
    p.rows as Rows
from sys.filegroups fg (nolock) join sys.database_files df (nolock)
    on fg.data_space_id = df.data_space_id join sys.indexes i (nolock) 
    on df.data_space_id = i.data_space_id join sys.tables t (nolock)
    on i.object_id = t.object_id join sys.partitions p (nolock)
on t.object_id = p.object_id and i.index_id = p.index_id  
where fg.name = 'PRIMARY' and t.type = 'U'  
order by rows desc
select  t.name as TableName,  
    i.name as IndexName, 
    p.rows as Rows
from sys.filegroups fg (nolock) join sys.database_files df (nolock)
    on fg.data_space_id = df.data_space_id join sys.indexes i (nolock) 
    on df.data_space_id = i.data_space_id join sys.tables t (nolock)
    on i.object_id = t.object_id join sys.partitions p (nolock)
on t.object_id = p.object_id and i.index_id = p.index_id  
where fg.name = 'PRIMARY' and t.type = 'U' and i.index_id = 0 
order by rows desc

很棒的脚本。我遇到的一个问题是“size/128”整数化了计算,导致除以零错误。将其更改为“size/128”。 - Dave
这个脚本对我不起作用。我得到了一些受影响的行,然后出现了一个错误 - Msg 8134,Level 16,State 1,Line 1 遇到除以零的错误。 - Steam

19
遇到了相同的问题,一开始碎片整理似乎起到了作用。但是只持续了很短的时间。原来客户使用的服务器正在运行 Express 版本,该版本有约 10GB 的许可限制。
所以即使大小设置为“无限制”,它也不是真正无限制的。

4

只需做一件事情,前往数据库属性,选择文件并增加数据库的初始大小,并将主文件组设置为自动增量。重新启动 SQL Server。

之后您就可以像之前一样使用该数据库了。


3
在我的情况下(可能比较罕见),我创建了一个新的TrueCrypt分区/文件,并选择存储大于4GB的文件,这可能使其使用了exfat文件系统。(请参阅以下详细信息(和其他尝试)。)

简述

我也遇到了同样的问题,初始数据库大小设置为4GB,自动增长设置为1MB。看起来,包含数据库的虚拟加密TrueCrypt驱动器有足够的空间。

我改变了一些(上面提到的)东西:

  • 我将Sql Server Express的Windows服务从自动更改为手动,这样只有“常规”Sql Server在运行。(尽管我正在运行应该允许10 GB的Sql Server 2008 R2。)
  • 我将自动增长从1 MB更改为10%
  • 我将自动增长增量大小从10%更改为1000 MB
  • 我对驱动器进行了碎片整理
  • 我收缩了数据库:
    • 手动 DBCC SHRINKDATABASE('...')
    • 右键单击数据库 | “属性”| “自动收缩”| “检查点时截断日志”)

所有这些都没有太大作用(我可以插入更多记录,但很快遇到了同样的问题)。Tobbi提到的页面文件使我尝试了一个更大的虚拟驱动器。(尽管我的驱动器不应该包含任何这样的系统文件,因为我经常在没有挂载的情况下运行。)

  • 我使用TrueCrypt创建了一个新的更大的虚拟驱动器
在制作过程中,我遇到了一个TrueCrypt问题,如果我要存储大于4GB的文件(如此SuperUser问题所示)。
  • 我告诉TrueCrypt我将存储大于4GB的文件
在这最后两个之后,我做得很好,我认为这最后一个就解决了问题。我认为TrueCrypt选择了一个exfat文件系统,限制了所有文件为4GB。(所以我可能根本不需要扩大驱动器,但我还是这样做了。)请参见veracrypt-file-system-option-for-larger-files,其中列出了一些具有优缺点的文件系统格式。
这可能是一个非常罕见的边界情况,但也许对某些人有帮助。

2
我发现这是由于以下原因所致:http://support.microsoft.com/kb/913399 SQL Server仅在以下条件满足时释放堆表使用的所有页面:在该表上进行了删除操作,正在持有表级锁。请注意,堆表是指未与聚集索引关联的任何表。
如果未将页面解除分配,则数据库中的其他对象无法重用这些页面。
但是,在SQL Server 2005数据库中启用基于行版本控制的隔离级别时,即使持有表级锁,也无法释放页面。
微软的解决方案:http://support.microsoft.com/kb/913399 要解决此问题,请使用以下方法之一: 1. 如果未启用基于行版本控制的隔离级别,请在DELETE语句中包含TABLOCK提示。例如,请使用类似以下语句的语句:
DELETE FROM TableName WITH (TABLOCK)
注:代表表名。如果要删除表中的所有记录,请使用TRUNCATE TABLE语句。例如,请使用类似以下语句的语句:
TRUNCATE TABLE TableName 2. 创建一个表列上的聚集索引。有关如何在表上创建聚集索引的更多信息,请参阅SQL中的“创建聚集索引”主题。
您会注意到,在链接底部没有说明它适用于SQL Server 2008,但我认为它是适用的。

2

请检查数据库文件增长类型,如果是受限制的,请将其更改为不受限制。


2
我遇到了同样的问题。原因是虚拟内存文件“pagefile.sys”位于我们数据库数据文件(D:驱动器)所在的相同驱动器上。它的大小翻倍并填满了磁盘,但Windows没有发现它,即使我们看起来有80GB可用空间,实际上并没有。
重启SQL服务器没有帮助,也许碎片整理会给操作系统释放页面文件的时间,但我们只是重新启动了服务器,然后页面文件缩小了,一切正常。
有趣的是,在我们调查的30分钟内,Windows根本没有计算pagefile.sys的大小(80GB)。重启后,Windows找到了pagefile并将其大小包括在总磁盘使用量中(现在为40GB,仍然太大)。

1
根据我的经验,此消息出现在主文件(.mdf)没有空间保存数据库的元数据时。该文件包括系统表,它们只保存其数据到其中。
为文件腾出一些空间,命令就可以正常工作了。 就是这样,享受吧。

0
我们的问题是硬盘可用空间已经降到零。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接