无法删除没有相关文件的文件组


8

我在SQL Server 2017 CU3上遇到一些奇怪的错误消息。我正在迁移数据库并重组文件组。“重新组织”是指我使用存储过程,该过程在对象的新文件组上创建分区函数和分区方案,在分区时重建索引,然后删除分区。

最后,我有一些空文件组。他们的文件删除。文件组本身也将被删除。在大多数情况下,此方法效果很好。但是对于两个数据库,我删除了文件... 剩下一个文件组,没有文件关联,但是

ALTER DATABASE REMOVE FILEGROUP

引发错误5042:

无法删除文件组“ xyz”,因为它不为空。

我如何摆脱那个空文件组...可能是什么问题?

我已经阅读了一些常见问题,但是它们在我的系统中不存在:

  • 已检查:

    SELECT * FROM sys.partition_schemes;
    SELECT * FROM sys.partition_functions;

    0行...数据库中没有分区对象

  • UPDATE STATISTICS 对于数据库中的所有对象

    没有效果

  • 检查文件组上的索引:

    SELECT * FROM  sys.data_spaces ds
    INNER JOIN sys.indexes i
    ON ds.data_space_id = i.data_space_id
    WHERE ds.name = 'xyz'

    0行

  • 检查文件组中的对象:

    SELECT
        au.*,
        ds.name AS [data_space_name],
        ds.type AS [data_space_type],
        p.rows,
        o.name AS [object_name]
    FROM sys.allocation_units au
        INNER JOIN sys.data_spaces ds
            ON au.data_space_id = ds.data_space_id
        INNER JOIN sys.partitions p
            ON au.container_id = p.partition_id
        INNER JOIN sys.objects o
            ON p.object_id = o.object_id
    WHERE au.type_desc = 'LOB_DATA'
    AND ds.name ='xyz'

    0行

在从文件组中删除文件之前,我还尝试了DBCC SHRINKFILE使用参数EMPTYFILE。这对我来说真的没有意义,但是我阅读了解决方案以将其描述为修复程序。无论如何都没有效果。


我有一些希望阅读有关服务器故障的问题,并尝试了以下方法:

  • 更新所有统计信息
  • 删除所有与索引无关的统计信息

但是,这没有效果。我仍然有一个没有文件关联的文件组,并且该文件组无法删除。我完全感到困惑,因为这发生在某些数据库中,而不是在其他数据库中(结构相同)。当我DBCC CHECK FILEGROUP对这个空文件组执行操作时,会收到一堆错误消息,如下所示:

无法处理对象“ STORY_TRANSLATIONSCCC”(ID 120387498),索引“ Ref90159CCC”(ID 2)的行集ID 72057594712162304,因为它位于文件组“ CCC_APPLICATION_new”(ID 8)上,未经检查。

“ STORY_TRANSLATIONSCCC”的DBCC结果。0页中的对象“ STORY_TRANSLATIONSCCC”中有0行。

这是正常现象还是表明有异常之处?

这个问题可能是重复的,但是我在dba.stackexchange上的其他问题中找不到适合我的解决方案。请查看列表,我已经尝试过了。这与“ 不能删除未使用的文件组 ”中描述的解决方案相同。

更多细节

可能有助于在错误发生之前了解我的操作。我正在计划迁移到新服务器。我目前正在测试实例上对此进行测试。从生产服务器还原数据库,并将恢复模型切换为简单模型。我的目标是重组文件组,并从每个文件组一个文件的模型转移到每个文件组两个文件的模型。为此,我创建了一个新的空文件组,每个文件组有两个文件,并将数据移到上方。不幸的是,大多数对象都具有LOB数据(XML和二进制)...因此,我也利用分区作为助手来移动lob数据。最后,所有数据都驻留在新文件组中,而旧文件组为空。然后,我删除所有文件,并删除相应的文件组。主文件组保留,仅添加另一个文件。我的问题。此过程工作正常,但可以删除两个数据库中的文件,但不能删除文件组。令人惊讶的是,如果在移动数据和删除旧文件组的过程中没有遇到问题,则这些数据库的结构应该与其他数据库的结构相同。

因此,这是发生问题的两个数据库的文件组和文件的列表:

  1. CCC_GENTE

之前

+-----------------+------------+
| Filegroup       | Filename   |
+-----------------+------------+
| CCC_APPLICATION | CCC_APP    |
+-----------------+------------+
| CCC_ARCHIVE     | CCC_ARCHIV |
+-----------------+------------+
| CCC_AXN         | CCC_AXN    |
+-----------------+------------+
| CCC_GDV         | CCC_GDV    |
+-----------------+------------+
| PRIMARY         | CCC        |
+-----------------+------------+

    +-----------------+--------------------------+--------------------+----------------------------------------------------+
| Filegroup name  | Filegroup temporary name | Filename (logical) | Status                                             |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| CCC_APPLICATION | -                        | CCC_APP            | file removed, filegroup  cannot be removed (error) |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| CCC_ARCHIVE     | -                        | CCC_ARCHIV         | file and filegroup removed                         |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| CCC_AXN         | -                        | CCC_AXN            | file and filegroup removed                         |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| CCC_GDV         | -                        | CCC_GDV            | file and filegroup removed                         |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| PRIMARY         | -                        | CCC                | file renamed to PRIMARY_1                          |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| PRIMARY         | -                        | PRIMARY_2          | new file added                                     |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| CCC_APPLICATION | CCC_APPLICATION_new      | CCC_APPLICATION_1  | new filegroup renamed at the end                   |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| CCC_APPLICATION | CCC_APPLICATION_new      | CCC_APPLICATION_2  | new filegroup renamed at the end                   |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| CCC_ARCHIVE     | CCC_ARCHIVE_new          | CCC_ARCHIVE_1      | new filegroup renamed at the end                   |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| CCC_ARCHIVE     | CCC_ARCHIVE_new          | CCC_ARCHIVE_2      | new filegroup renamed at the end                   |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| CCC_AXN         | CCC_AXN_new              | CCC_AXN_1          | new filegroup renamed at the end                   |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| CCC_AXN         | CCC_AXN_new              | CCC_AXN_2          | new filegroup renamed at the end                   |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| CCC_GDV         | CCC_GDV_new              | CCC_GDV_1          | new filegroup renamed at the end                   |
+-----------------+--------------------------+--------------------+----------------------------------------------------+
| CCC_GDV         | CCC_GDV_new              | CCC_GDV_2          | new filegroup renamed at the end                   |
+-----------------+--------------------------+--------------------+----------------------------------------------------+

我希望能有所帮助。还有另一个数据库,其中文件组的名称不同,但是为了简洁起见,我不再赘述。


1
我知道它没有提到SQL2017,但我想知道该错误是否在2017年仍然存在?support.microsoft.com/en-us/help/3132058/...
SqlWorldWide

@SqlWorldWide:感谢您的链接。但是我没有全文索引,并且确实删除了自己的分区函数和方案……因此我猜该链接不适用于我的问题。
Martin Guth '18

您可以打印整个 5042错误,状态给出了问题所在。
Sean Gallardy-退休用户'18

@ SeanGallardy-Microsoft:消息5042,级别16,状态8,行1无法删除文件组'FG_AUDIT',因为它不为空。
Martin Guth

谢谢:)状态8表示文件组正在被一个对象使用。这与支持文章不同(状态12,表示分区方案使用了fg)。奇怪的是您说文件组中没有文件。我假设自问题发生以来已进行了多次日志备份(如果是完整备份/批量备份)?
肖恩·加拉迪-退休用户'18

Answers:


4

仔细检查数据库中的文件组

通过发出以下命令,验证文件组中是否没有附加的文件:

use [DB]
go
sp_helpfilegroup 

这将产生一个文件组列表:

 groupname | groupid | filecount
-----------+---------+-----------
 PRIMARY   | 1       | 1
 xyz       | 2       | 1

...然后对列出的每个文件组执行

use [DB]
go
sp_helpfilegroup @filegroupname='PRIMARY'
go
sp_helpfilegroup @filegroupname='xyz'

输出可能如下所示:

 groupname | groupid | filecount
-----------+---------+------------
 xyz       | 2       | 1

....第二个输出可能是:

  file_in_group    | fileid | filename                          | size    | maxsize   | growth  
 ------------------+--------+-----------------------------------+---------+-----------+---------
  xyz_logical_name | 3      | X:\SQL\SQL_DATA\xyz_filegroup.ndf | 5120 KB | Unlimited | 1024 KB  

删除文件组

如果仍然有一个文件与其中一个文件组关联,则删除文件组的逻辑文件和文件组本身的完整命令为:

USE [DB]
GO
ALTER DATABASE [DB] REMOVE FILE [xyz_logical_name]
GO
ALTER DATABASE [DB] REMOVE FILEGROUP [xyz]
GO

文件组“ xyz”是默认值

如果在尝试删除文件组的逻辑文件时收到错误消息,如下所示:

Msg 5031, Level 16, State 1, Line 88
Cannot remove the file 'xyz_logical_name' because it is the only file in the DEFAULT filegroup.

...然后您必须将PRIMARY文件组设置为文件DEFAULT组:

ALTER DATABASE [DB] MODIFY FILEGROUP [PRIMARY] DEFAULT

文件组“ xyz”为只读

但是,如果错误消息如下:

Msg 5055, Level 16, State 2, Line 88 
Cannot add, remove, or modify file 'xyz_logical_name'. The file is read-only.

...那么您将必须删除xyz文件组上的READ_ONLY属性:

ALTER DATABASE [DB] MODIFY FILEGROUP [xyz] READWRITE

现在,您应该能够删除文件组的逻辑文件和文件组本身。

未结交易

如果您确实没有与xyz要删除的文件组关联的文件(逻辑名称/ pyhsical_file_name),则执行事务日志备份可能会释放任何阻碍进一步删除文件组的事务。

拨打911

如果其他所有方法均失败,则您可能要考虑与Microsoft进行通话。


元数据不匹配

经过进一步研究后添加

显然,在某些情况下,数据库中的元数据无法反映对象的实际位置。

参考:
- FIX:元数据切换表分区和删除相应的文件和文件组后不一致的错误(Microsoft支持)
- FIX:当您尝试删除或出现错误删除的文件组或SQL Server分区方案和功能(Microsoft支持)

对于SQL Server 2014 SP1的累积更新3对于SQL Server 2016的累积更新1,似乎已经解决了这两种情况。它们不适用于您的情况,但是它们表明有时元数据可能是错误的。

似乎阻止文件组删除的项目是索引,该索引可能存储有错误的元数据。

可能的解决方案

考虑重建Ref90159CCC错误消息中引用的索引。

Cannot process rowset ID 72057594712162304 of object 
"STORY_TRANSLATIONSCCC" (ID 120387498), index "Ref90159CCC" (ID 2), 
because it resides on filegroup "CCC_APPLICATION_new" (ID 8), 
which was not checked.

下面的文章描述了类似的情况,并显示了作者如何发现罪魁祸首并解决了这种情况。

参考:SQL Server:交换机分区和元数据不一致问题(Blog dbi-services.com)


查找与过时文件组相关的对象

我安装了此脚本,以检查表/索引/分区/等的尽可能多的隐藏位置。可能仍然与删除的文件组文件有关:

请替换DEFAULTRO为您过时的文件组的名称(例如CCC_APPLICATION

 /* ==================================================================
  Author......: hot2use
  Date........: 16.02.2018
  Version.....: 0.1
  Server......: LOCALHOST (first created for)
  Database....: StackExchange
  Owner.......: -
  Table.......: -
  Type........: Script
  Name........: ADMIN_Filegroup_Statement_All_Objects.sql
  Description.: Checks all objects related to filegroups based on the 
  ............  relationship between the data_space_id ID.
  ............      
  History.....:  0.1    h2u First created
  ............      
  ............      
 ================================================================== */
DECLARE @nvObsoleteFG AS NVARCHAR(50)
SET @nvObsoleteFG = N'DEFAULTRO'

SELECT -- DISTINCT use in conjunction with sys.allocation_units table and objects
       '-->'                            AS DataSpaceNfo
      ,ds.name                          AS DataSpaceName
      ,ds.data_space_id                 AS DatSpacID_DataSpace
      ,'-->'                            AS FileGroupNfo
      ,f.name                           AS FileGrpName
      ,f.data_space_id                  AS DatSpacID_FileGrp
      ,f.[type]                         AS FileGrpType
      ,'-->'                            AS DataBaseFilesNfo
      ,df.data_space_id                 AS DatSpacID_DBFiles
      ,df.[type]                        AS DBFilesType
      ,df.name                          AS DBFilesName
      ,'-->'                            AS ObjectNfo
      ,o.[object_id]                    AS OjbID
      ,o.name                           AS ObjName4HeapsClusters
      ,o.type_desc                      AS ObjTypeDesc
      ,'-->'                            AS IndexNfo
      ,i.name                           AS ObjName4Indexes
      ,i.type_desc                      AS IndTypeDesc
      ,i.[object_id]                    AS IndObjID
      ,i.index_id                       AS IndIndID
      ,'-->'                            AS PartSchemaNfo
      ,ps.name                          AS PartSchemaName
      ,ps.data_space_id                 AS DatSpacID_PartSchema
       -- ,au.type_desc                     AS AllocUnitTypeDesc
       -- ,au.data_space_id                 AS DatSpacID_AllocUnit
FROM   sys.data_spaces                  AS ds
       FULL JOIN sys.filegroups         AS f
            ON  ds.data_space_id = f.data_space_id
       FULL JOIN sys.database_files     AS df
            ON  f.data_space_id = df.data_space_id
       FULL JOIN sys.indexes            AS i
            ON  f.data_space_id = i.data_space_id
       FULL JOIN sys.partition_schemes  AS ps
            ON  f.data_space_id = ps.data_space_id
       FULL JOIN sys.objects            AS o
            ON  i.[object_id] = o.[object_id]         
       -- FULL JOIN sys.allocation_units   AS au
       --      ON  au.data_space_id = f.data_space_id

-- If you omit the whole WHERE clause you get an overview of everything (incl. MS objects)
WHERE  o.is_ms_shipped = 0
       -- if you omit the lower AND you'll get all items related to all filegroups
       AND (
               df.data_space_id=(
                   SELECT data_space_id
                   FROM   sys.filegroups
                   WHERE  NAME = @nvObsoleteFG
               )
               OR f.data_space_id=(
                      SELECT data_space_id
                      FROM   sys.filegroups
                      WHERE  NAME = @nvObsoleteFG
                  ) 
               OR df.data_space_id=(
                      SELECT data_space_id
                      FROM   sys.filegroups
                      WHERE  NAME = @nvObsoleteFG
                  )
               OR ps.data_space_id=(
                      SELECT data_space_id
                      FROM   sys.filegroups
                      WHERE  NAME = @nvObsoleteFG
                  )
           )

参考:我的个人剧本

运行它,查看是否显示了包含过时文件组的任何对象。使用data_space_id而不是名称。联接有意FULL捕获任何“孤立”引用。

或者,使用以下较小的脚本快速检查过时的文件组中的项目:

SELECT o.[name]
      ,o.[type]
      ,i.[name]
      ,i.[index_id]
      ,f.[name]
FROM   sys.indexes i
       INNER JOIN sys.filegroups f
            ON  i.data_space_id = f.data_space_id
       INNER JOIN sys.all_objects o
            ON  i.[object_id] = o.[object_id]
WHERE  i.data_space_id = f.data_space_id
       AND o.type = 'U' -- User Created Tables

参考:SQL SERVER –列出在数据库中所有文件组上创建的所有对象(SQLAuthority.com)


sp_helpfilegroup:FG_AUDIT groupid 2 filecount 0没有文件
Martin Guth

数据库处于简单的恢复模型中,并且目前(在整个测试服务器上)没有未完成的交易
Martin Guth,

感谢您的反馈。您可以将此信息添加到您的问题中吗?我会给您更多错误信息(...CCC_APPLICATION_new...;是临时文件组吗?),请多加考虑,并尝试在我的环境中重现。
约翰aka hot2use

1
CCC_APPLICATION_new不是临时文件组...它是内容已移动到的文件组...应将其重命名为“ CCC_APPLICATION” ...但是,只有在没有与文件关联的名为CCC_APPLICATION的文件组被删除或重命名(但不想让它闲逛)
Martin Guth

1
为了澄清:我在两个不同的数据库中遇到了问题...一个是旧文件组CCC_APPLICATION和新文件组CCC_APPLICATION_new,另一个是旧文件组FG_AUDIT和新文件组CCC_AUDIT
Martin Guth,

2

四个月后,Microsoft支持部门找到了解决方案。确实有一个表引用了这个大概是空的文件组。

该表由以下语句标识:

SELECT t.[name] FROM sys.tables t
   inner join sys.filegroups f
         on t.lob_data_space_id = f.data_space_id
   where f.name = 'xyz'

将数据移到新表并删除有问题的表后,文件组已成功删除。数据移动的过程是:创建具有相同结构和索引的新表,通过SELECT INTO复制数据,删除旧表,重命名新表(当然,如果整个过程中有外键,则要照顾外​​键) )


多年来,我一直在寻找这个答案。非常感谢!
Christian4145
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.