web-dev-qa-db-ja.com

ファイルが関連付けられていないファイルグループは削除できません

SQL Server 2017 CU3で奇妙なエラーメッセージが発生します。データベースを移行し、ファイルグループを再編成しています。 「再編成」とは、 ストアドプロシージャ を使用して、オブジェクトの新しいファイルグループにパーティション関数とパーティション構成を作成し、パーティション分割中にインデックスを再構築してから、パーティション分割を削除することを意味します。

最後に、いくつかの空のファイルグループを取得しました。それらのファイル削除されます。また、ファイルグループ自体も削除されます。これはほとんどの場合うまくいきます。ただし、2つのデータベースの場合、ファイルを削除しました...関連付けられているファイルがないファイルグループがありますが、

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を使用して、ファイルグループからファイルを削除する前に試してください。それは私には本当に意味がありませんが、私はそれを修正として説明する解決策を読みます。とにかく効果がなかった。


私はこれを読んでいくつかの希望を得ました question on server faultと以下を試しました:

  • すべての統計を更新
  • インデックスに関連しないすべての統計を削除します

しかし、これは効果がありませんでした。ファイルが関連付けられていないファイルグループがまだあり、ファイルグループを削除できません。これは一部のデータベースで発生し、他のデータベースでは発生しない(同じ構造を持つ)ため、完全に困惑します。 DBCC CHECK FILEGROUPこの空のファイルグループで、次のような一連のエラーメッセージが表示されます。

チェックされていないファイルグループ "CCC_APPLICATION_new"(ID 8)に存在するため、オブジェクト "STORY_TRANSLATIONSCCC"(ID 120387498)、インデックス "Ref90159CCC"(ID 2)の行セットID 72057594712162304を処理できません。

'STORY_TRANSLATIONSCCC'のDBCC結果。オブジェクト「STORY_TRANSLATIONSCCC」の0ページに0行あります。

これは正常ですか、それとも異常なことを示していますか?

この質問は重複している可能性がありますが、dba.stackexchangeに関する他の質問で私に役立つ解決策を見つけることができません。私が既に試したことをリストで見てください。これは 未使用のファイルグループを削除できない で説明されているソリューションと同じです。

詳細

エラーが発生する前に私が何をすべきかを理解するのに役立つかもしれません。新しいサーバーへの移行を計画しています。現在、これをテストインスタンスでテストしています。データベースは本番サーバーから復元され、復旧モデルはシンプルに切り替えられます。私の目標は、ファイルグループを再構築し、ファイルグループごとに1つのファイルを持つモデルから、ファイルグループごとに2つのファイルを持つモデルに移動することです。それを実現するために、それぞれ2つのファイルを持つ新しい空のファイルグループを作成し、データを移動します。残念ながら、ほとんどのオブジェクトにはLOBデータ(XMLおよびバイナリ)があります。そのため、パーティション化をヘルパーとして活用して、LOBデータも移動します。最後に、すべてのデータは新しいファイルグループにあり、古いファイルグループは空です。次に、すべてのファイルを削除し、それぞれのファイルグループも削除します。プライマリファイルグループはそのまま残り、別のファイルが追加されます。別の 私の質問 でサンプルスクリプトを見つけることができます。このプロセスは正常に機能しますが、2つのデータベースではファイルを削除できますが、ファイルグループは削除できません。驚いたことに、これらのデータベースの構造は、他のデータベースの構造と同じである必要があり、データの移動や古いファイルグループの削除のプロセスで問題が発生することはありませんでした。

問題が発生した2つのデータベースのファイルグループとファイルのリストを次に示します。

  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                   |
+-----------------+--------------------------+--------------------+----------------------------------------------------+

少しお役に立てば幸いです。ファイルグループ名が異なる2番目のデータベースもありますが、簡潔にするために省略しています。

8
Martin Guth

4か月後、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を介してデータをコピーし、古いテーブルを削除し、新しいテーブルの名前を変更します(もちろん、プロセス全体に外部キーがある場合は、外部キーを処理します)。 )

2
Martin Guth

データベース内のファイルグループの再確認

次のコマンドを発行して、ファイルグループに添付ファイルが残っていないことを確認します。

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

.... 2番目の出力は次のようになります。

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

ファイルグループの削除

ファイルグループの1つに関連付けられたファイルがまだある場合、ファイルグループの論理ファイルとファイルグループ自体を削除する完全なコマンドは次のようになります。

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に関連付けられているファイル(logical_name/pyhsical_file_name)が実際にない場合、トランザクションログバックアップを実行するとトランザクションが解放され、ファイルグループの削除を妨げる可能性があります。

911にダイヤル

他のすべてが失敗した場合は、Microsoftとの電話をかけることを検討してください。


メタデータの不一致

さらに調査した後に追加

明らかに、データベース内のメタデータがオブジェクトの実際の場所を反映していない場合があります。

参照:
- FIX:テーブルパーティションを切り替えて、対応するファイルとファイルグループを削除した後のメタデータの不整合エラー (Microsoftサポート)
- FIX:SQL Serverでファイルグループまたはパーティション構成と関数を削除または削除しようとするとエラーが発生します (Microsoftサポート)

これら2つのケースは、それぞれSQL Server 2014 SP1の累積的な更新および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)

4