Невозможно удалить файловую группу без связанных файлов

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эту пустую файловую группу, я получаю кучу сообщений об ошибках, таких как:

Не удается обработать набор строк с идентификатором 72057594712162304 объекта "STORY_TRANSLATIONSCCC" (ID 120387498), индекс "Ref90159CCC" (ID 2), поскольку он находится в файловой группе "CCC_APPLICATION_new" (ID 8), которая не была проверена.

Результаты DBCC для STORY_TRANSLATIONSCCC. Для объекта "STORY_TRANSLATIONSCCC" имеется 0 строк на 0 страницах.

Это нормально или это указывает на что-то необычное?

Этот вопрос может быть дубликатом, однако я не могу найти рабочее исправление для меня в других вопросах на dba.stackexchange. Пожалуйста, посмотрите на список того, что я уже пробовал. Это идентично решениям, описанным в разделе Невозможно удалить неиспользуемые файловые группы .

Подробнее

Может быть, это помогает понять, что я делаю, прежде чем ошибка произойдет. Я планирую переход на новый сервер. В настоящее время я тестирую это на тестовом экземпляре. Базы данных восстанавливаются с сервера prod, а модель восстановления переключается на простую. Моя цель - реструктурировать файловые группы и перейти от модели с одним файлом на файловую группу к модели с двумя файлами на файловую группу. Чтобы добиться этого, я создаю новые пустые файловые группы по два файла в каждой и перемещаю данные. К сожалению, большинство объектов имеют 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: Спасибо за ссылку. Однако у меня нет полнотекстовых индексов, и я сам удалил функции и схемы разделов ... поэтому я думаю, что ссылка не относится к моей проблеме.
Мартин Гут,
Можете ли вы напечатать всю ошибку 5042, состояние дает, в чем проблема.
Шон Галларди - Пользователь на пенсии,
@ SeanGallardy-Microsoft: Сообщение 5042, Уровень 16, Состояние 8, Строка 1 Файловую группу 'FG_AUDIT' невозможно удалить, поскольку она не пуста.
Мартин Гут,
Спасибо :) Состояние 8 означает, что файловая группа используется объектом. Это отличается от статьи поддержки (это состояние 12, которое означает, что fg используется схемой разбиения). Странно, что вы сказали, что в файловой группе нет файлов. Я предполагаю, что с момента возникновения проблемы было выполнено несколько резервных копий журналов (если они полностью / навалом)?
Шон Галларди - Пенсионер

Ответы:

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.

... тогда вам придется удалить свойство READ_ONLY в xyzфайловой группе:

ALTER DATABASE [DB] MODIFY FILEGROUP [xyz] READWRITE

Теперь вы сможете удалить логический файл файловой группы и саму файловую группу.

Открытые транзакции

Если у вас действительно нет файла (логическое_имя / имя_файла_файла), связанного с файловой группой, которую xyzвы пытаетесь удалить, то выполнение резервного копирования журнала транзакций может освободить все транзакции, препятствующие дальнейшему удалению файловой группы.

Наберите 911

Если ничего не помогает, вы можете рассмотреть возможность вызова в Microsoft.


Несовпадение метаданных

Добавлено после дальнейшего исследования

По-видимому, бывают случаи, когда метаданные в базе данных не отражают фактическое местоположение объектов.

Ссылка:
- ИСПРАВЛЕНИЕ: ошибка несоответствия метаданных после переключения разделов таблицы и удаления соответствующих файлов и групп файлов (поддержка Microsoft)
- ИСПРАВЛЕНИЕ: Ошибка возникает при попытке удалить или удалить группы файлов или схемы и функции разделов в SQL Server (поддержка Microsoft)

Похоже, что эти два случая были решены с помощью накопительного обновления 3 для SQL Server 2014 с пакетом обновления 1 ( SP1) и накопительного обновления 1 для SQL Server 2016 соответственно. Они не относятся к вашей ситуации, но показывают, что иногда метаданные могут быть неправильными.

Элемент, который, кажется, блокирует удаление вашей файловой группы, является индексом, который может храниться с неверными метаданными.

Возможное решение

Попробуйте перестроить индекс, на 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: проблема с переключением разделов и метаданных (блог 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)

Джон ака hot2use
источник
sp_helpfilegroup: FG_AUDIT groupid 2 filecount 0 нет файлов
Мартин Гут,
база данных находится в простой модели восстановления, и в настоящее время нет открытых транзакций (на тестовом сервере в целом)
Martin Guth
Спасибо за ответ. Не могли бы вы добавить эту информацию в свой вопрос? Я дам вашему сообщению об ошибке ( ...CCC_APPLICATION_new...это временная файловая группа?) Еще несколько мыслей и попытаюсь воспроизвести в моей среде.
Джон aka hot2use
1
CCC_APPLICATION_new - это не временная файловая группа ... это файловая группа, в которую было перемещено содержимое ... ее следует переименовать в "CCC_APPLICATION" ... однако это работает только в том случае, если файловая группа без связанного файла с именем CCC_APPLICATION была удалена или переименован (но не хочу, чтобы он болтался)
Мартин Гут,
1
для пояснения: у меня проблема в двух разных базах данных ... одна со старой файловой группой CCC_APPLICATION и новой файловой группой CCC_APPLICATION_new, а другая со старой файловой группой FG_AUDIT и новой файловой группой CCC_AUDIT
Мартин Гут,
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,