web-dev-qa-db-fra.com

"Le groupe de fichiers principal est complet" dans SQL Server 2008 Standard sans raison apparente

Notre base de données est actuellement à 64 Go et l'une de nos applications a commencé à échouer avec l'erreur suivante:

System.Data.SqlClient.SqlException: impossible d'allouer de l'espace pour l'objet 'cnv.LoggedUnpreparedSpos'.'PK_LoggedUnpreparedSpos' dans la base de données 'travelgateway' car le groupe de fichiers 'PRIMARY' est saturé. Créez de l'espace disque en supprimant des fichiers inutiles, en déposant des objets dans le groupe de fichiers, en ajoutant d'autres fichiers au groupe de fichiers ou en définissant la croissance automatique des fichiers existants dans le groupe de fichiers.

J'ai tout revérifié: tous les fichiers d'un même groupe de fichiers sont autorisés à s'autograsser avec des incréments raisonnables (100 Mo pour un fichier de données, 10% pour un fichier journal), plus de 100 Go d'espace libre sont disponibles pour la base de données, tempdb est également configuré pour s'ouvrir automatiquement avec beaucoup d'espace disque libre sur son lecteur.

Pour résoudre un problème, j'ai ajouté un deuxième fichier au groupe de fichiers et l'erreur a disparu. Mais je suis mal à l'aise face à toute cette situation.

Où est le problème ici, les gars?

44
Anton Gogolev

OK, ça marche. Il s'avère qu'un volume NTFS où se trouvaient les fichiers de base de données a eu lourdement fragmenté. Arrêté SQL Server, défragmenter le tout et tout allait bien depuis.

26
Anton Gogolev

Anton,

Il est recommandé de ne pas créer d’objets utilisateur dans le groupe de fichiers principal. Lorsque vous avez de la bande passante, créez un nouveau groupe de fichiers, déplacez les objets utilisateur et laissez les objets système en principal.

Les requêtes suivantes vous aideront à identifier l'espace utilisé dans chaque fichier et les tables principales qui ont le plus grand nombre de lignes et s'il y a des tas. C’est un bon point de départ pour étudier cette question.

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
19
Sankar Reddy

Couru dans le même problème et au début défragmenter semblait fonctionner. Mais c'était pour peu de temps. Il s’avère que le serveur utilisé par le client exécute le Express version et que la limite de licence est d’environ 10gb

Donc, même si la taille était définie sur "illimité", ce n'était pas le cas.

18
Hugo Delsing

J'ai également rencontré le même problème, où la taille initiale de la base de données est définie sur 4 Go et la croissance automatique définie par 1 Mo. Le lecteur TrueCrypt chiffré virtuel sur lequel se trouvait la base de données semblait disposer de beaucoup d'espace.

J'ai changé quelques-unes des choses ci-dessus:

  • J'ai fait passer le service Windows de Sql Server Express de automatic à manual, De sorte que seul le serveur «normal» Sql est en cours d'exécution. (Même si j'utilise Sql Server 2008 R2, ce qui devrait permettre 10 Go.)
  • J'ai changé la croissance automatique de 1 Mo à 10%
  • J'ai changé la taille de l'incrément de croissance automatique de 10% à 1000 Mo
  • J'ai défragmenté le lecteur
  • Je rétrécis la base de données:
    • manuellement DBCC SHRINKDATABASE('...')
    • automatiquement un clic droit sur la base de données | "propriétés" | "Auto Shrink" | "Tronquer le journal au point de contrôle")

Tout à peu de succès (je pourrais insérer quelques disques supplémentaires, mais bientôt rencontré le même problème) . Le fichier d'échange mentionné par Tobbi, m'a fait essayer un plus grand lecteur virtuel. (Même si mon lecteur ne doit contenir aucun fichier système de ce type, je le lance sans qu'il soit souvent monté.)

  • J'ai créé un nouveau disque virtuel plus grand avec TrueCrypt

En faisant cela, je me suis heurté à une question TrueCrypt, si je vais stocker des fichiers de plus de 4 Go ( comme indiqué dans cette question sur le SuperUser ).

  • J'ai dit à TrueCrypt que je stockerais des fichiers de plus de 4 Go 

Après ces deux derniers, je me débrouillais bien et je suppose que ce dernier a fait l'affaire. Je pense que TrueCrypt choisit un système de fichiers exfat ( comme décrit ici ), qui limite tous les fichiers à 4 Go. (Donc, je n'ai probablement pas eu besoin d'agrandir le lecteur après tout, mais je l'ai quand même fait.)

C’est probablement un cas très rare aux frontières, mais peut-être est-il utile à quelqu'un.

3
Yahoo Serious

Faites une chose, rendez-vous dans les propriétés de la base de données. Sélectionnez les fichiers et augmentez la taille initiale de la base de données .__ et définissez le groupe de fichiers principal comme étant auto-incrémenté.

Vous pourrez utiliser la base de données comme précédemment.

3
vishal walujwar

Je viens de rencontrer le même problème. La raison en était que le fichier de mémoire virtuelle "pagefile.sys" était situé sur le même lecteur que nos fichiers de données pour nos bases de données (lecteur D:). Le disque avait doublé de taille et rempli le disque, mais Windows ne l’a pas relevé, c’est-à-dire qu’il semblait que nous avions 80 Go d’espace libre alors que nous ne l’avions pas fait.

Redémarrer le serveur SQL n’a pas aidé, une défragmentation aurait peut-être donné le temps au système d’exploiter le fichier d'échange, mais nous avons simplement redémarré le serveur et le tour est joué.

Ce qui est intéressant, c’est que pendant les 30 minutes que nous avons examinées, Windows n’a pas du tout calculé la taille du fichier pagefile.sys (80 Go). Après le redémarrage, Windows a trouvé le fichier d'échange et inclus sa taille dans l'utilisation totale du disque (maintenant 40 Go - ce qui est toujours trop volumineux).

2
Tobbi

veuillez vérifier le type de croissance du fichier de la base de données, si sa restriction le rend illimité

2
annonymous

J'ai constaté que cela se produit car: http://support.Microsoft.com/kb/913399

SQL Server ne publie que toutes les pages utilisées par une table de segment de mémoire lorsque les conditions suivantes sont remplies: Une suppression de cette table a lieu. UNE le verrouillage au niveau de la table est en cours. Remarque Une table de tas est une table qui n'est pas associé à un index clusterisé.

Si les pages ne sont pas désallouées, les autres objets de la base de données ne peuvent pas réutiliser les pages. 

Toutefois, lorsque vous activez un niveau d'isolation basé sur la gestion des versions de ligne dans un fichier Base de données SQL Server 2005, les pages ne peuvent pas être publiées, même si un le verrouillage au niveau de la table est en cours.

La solution de Microsoft: http://support.Microsoft.com/kb/913399

Pour contourner ce problème, appliquez l'une des méthodes suivantes: Incluez un indicateur TABLOCK dans l'instruction DELETE s'il s'agit d'une ligne le niveau d'isolation basé sur la gestion des versions n'est pas activé. Par exemple, utilisez un déclaration semblable à la suivante: 

SUPPRIMER DE TableName AVEC (TABLOCK)

Note représente le nom de la table. Utilisez le TRUNCATE Instruction TABLE si vous souhaitez supprimer tous les enregistrements de la table . Par exemple, utilisez une instruction semblable à la suivante: 

TRUNCATE TABLE NomTable

Créez un index clusterisé sur une colonne de la table. Pour plus des informations sur la création d'un index clusterisé sur une table, voir le Rubrique "Création d'un index clusterisé" dans SQL

Vous remarquerez au bas du lien qu'il n'est PAS noté que cela s'applique à SQL Server 2008, mais je pense que c'est le cas.

2
ajdams

notre problème était que le disque dur était réduit à zéro.

0
batman