48

我们的数据库目前为 64 Gb,我们的一个应用程序开始失败并出现以下错误:

System.Data.SqlClient.SqlException: 无法为'cnv.LoggedUnpreparedSpos'.'PK_LoggedUnpreparedSpos'数据库中的对象分配空间,'travelgateway'因为'PRIMARY'文件组已满。通过删除不需要的文件、删除文件组中的对象、向文件组添加其他文件或为文件组中的现有文件设置自动增长来创建磁盘空间。

我仔细检查了所有内容:允许单个文件组中的所有文件以合理的增量自动增长(数据文件为 100 Mb,日志文件为 10%),超过 100 Gb 的可用空间可用于数据库,tempdb是设置为自动增长以及驱动器上有足够的可用硬盘空间。

为了解决问题,我将第二个文件添加到文件组中,并且错误消失了。但我对整个情况感到不安。

问题出在哪里,伙计们?

4

10 回答 10

28

好的,开始工作了。事实证明,数据库文件所在的 NTFS 卷碎片严重。停止 SQL Server,对整个事情进行碎片整理,从那以后一切都很好。

于 2010-03-26T08:09:52.663 回答
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
于 2009-12-25T05:30:11.033 回答
19

遇到同样的问题,起初碎片整理似乎有效。但这只是很短的时间。原来客户正在使用的服务器正在运行,Express version并且许可限制约为10gb.

因此,即使大小设置为“无限”,它也不是。

于 2015-01-23T13:36:57.273 回答
4

做一件事,转到数据库选择文件的属性并增加数据库的初始大小并将主文件组设置为自动增量。重启sql server。

您将能够像以前一样使用数据库。

于 2014-11-14T10:00:15.763 回答
3

我也遇到了同样的问题,初始数据库大小设置为 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 question 所示)。

  • 我告诉 TrueCrypt 我会存储大于 4 GB 的文件

在最后两个之后我做得很好,我假设最后一个成功了。我认为 TrueCrypt 选择了exfat文件系统(如此处所述),它将所有文件限制为 4GB。(所以我可能根本不需要扩大驱动器,但我还是做了。)

这可能是一个非常罕见的边界案例,但也许它对某人有帮助。

于 2012-11-29T13:48:23.413 回答
2

我发现发生这种情况是因为:http: //support.microsoft.com/kb/913399

SQL Server 仅在满足以下条件时才释放堆表使用的所有页面: 发生此表的删除。正在持有表级锁。注意 堆表是不与聚集索引关联的任何表。

如果页面没有被释放,数据库中的其他对象就不能重用这些页面。

但是,当您在 SQL Server 2005 数据库中启用基于行版本控制的隔离级别时,即使持有表级锁,也无法释放页面。

微软的解决方案:http: //support.microsoft.com/kb/913399

要变通解决此问题,请使用下列方法之一: 如果未启用基于行版本控制的隔离级别,则在 DELETE 语句中包含 TABLOCK 提示。例如,使用类似于以下的语句:

用(TABLOCK)从表名中删除

Note 代表表的名称。如果要删除表中的所有记录,请使用 TRUNCATE TABLE 语句。例如,使用类似于以下的语句:

截断表表名

在表的列上创建聚集索引。有关如何在表上创建聚集索引的详细信息,请参阅 SQL 中的“创建聚集索引”主题

您会在链接底部注意到它没有指出它适用于 SQL Server 2008,但我认为它确实适用

于 2009-12-23T14:58:05.097 回答
2

我刚刚遇到了同样的问题。原因是虚拟内存文件“pagefile.sys”与我们数据库的数据文件(D:驱动器)位于同一驱动器上。它的大小翻了一番并填满了磁盘,但 windows 没有拾取它,即看起来我们有 80 GB 的可用空间,而实际上我们没有。

重新启动 SQL 服务器并没有帮助,也许碎片整理会给操作系统时间来释放页面文件,但我们只是重新启动服务器,瞧,页面文件已经缩小,一切正常。

有趣的是,在我们调查的 30 分钟内,windows 根本没有计算 pagefile.sys 的大小(80gb)。重新启动后,windows 确实找到了页面文件并将其大小包含在总磁盘使用量中(现在 40gb - 这仍然太大)。

于 2012-07-18T23:29:07.833 回答
2

请检查数据库的文件增长类型,如果限制则不限制

于 2013-01-10T08:17:33.840 回答
1

根据我的经验,当主文件 (.mdf) 没有空间来保存数据库的元数据时,会出现此消息。该文件包括系统表,它们仅将数据保存到其中。

在文件中留出一些空间,命令再次起作用。仅此而已,享受

于 2019-06-01T01:14:54.977 回答
0

我们的问题是硬盘驱动器的可用空间降至零。

于 2016-10-21T18:25:39.630 回答