Наша база данных в настоящее время на уровне 64 Гбит, и одно из наших приложений начало перестать работать со следующей ошибкой:
System.Data.SqlClient.SqlException
: Не мог выделить место для объекта'cnv.LoggedUnpreparedSpos'.'PK_LoggedUnpreparedSpos'
в базе данных'travelgateway'
потому что'PRIMARY'
группа файлов полна. Создайте дисковое пространство путем удаления ненужных файлов, отбрасывания объектов в группе файлов, добавления дополнительных файлов к группе файлов или установки автороста на для существующих файлов в группе файлов.
Я перепроверил все: всем файлам в единственной группе файлов позволяют автовырасти с разумные инкременты (100 Мбит для файла данных, 10% для файла журнала), больше чем 100 Гбит свободного пространства доступны для базы данных, tempdb
набор должен автовырасти также с большим количеством свободного пространства жесткого диска на его диске.
Для разрешения проблемы я добавил второй файл к группе файлов, и ошибка пошла. Но я чувствую себя неловко об этой целой ситуации.
Где' проблема здесь, парни?
Хорошо, все заработало. Оказывается, том NTFS, на котором были расположены файлы БД, был сильно фрагментирован. Остановил SQL Server, все дефрагментировал, и с тех пор все в порядке.
Я обнаружил, что это происходит потому, что: http://support.microsoft.com/kb/913399
SQL Server освобождает все страницы, которые использует таблица кучи, когда выполняются следующие условия: Произойдет удаление этой таблицы. А удерживается блокировка на уровне таблицы. Примечание. Таблица кучи - это любая таблица, не связан с кластеризованным индексом.
Если страницы не освобождены, другие объекты в базе данных не могут повторно использовать страницы.
Однако при включении уровня изоляции на основе управления версиями строк в База данных SQL Server 2005, страницы не могут быть освобождены, даже если удерживается блокировка на уровне таблицы.
Решение Microsoft: http://support.microsoft.com/kb/913399
Чтобы обойти эту проблему, используйте один из следующих методов: Включите подсказку TABLOCK в оператор DELETE, если строка Уровень изоляции на основе управления версиями не включен. Например, используйте оператор, аналогичный следующему:
DELETE FROM TableName WITH (TABLOCK)
Примечание представляет имя таблицы. Используйте TRUNCATE TABLE, если вы хотите удалить все записи в таблице. Например, используйте оператор, подобный следующему:
TRUNCATE TABLE TableName
Создайте кластерный индекс для столбца таблицы. Для большего информацию о том, как создать кластерный индекс для таблицы, см. Тема «Создание кластерного индекса» в SQL
. Внизу ссылки вы заметите, что НЕ указано, что она применяется к SQL Server 2008, но я думаю, что это так
Антон,
В качестве лучшей практики не следует создавать пользовательские объекты в основной файловой группе. Когда у вас есть пропускная способность, создайте новую файловую группу, переместите объекты пользователей и оставьте системные объекты в первичной.
Следующие запросы помогут вам определить пространство, используемое в каждом файле и в верхних таблицах, которые имеют наибольшее количество строк, и если есть кучи. Это хорошая отправная точка для изучения данной проблемы.
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