Notes
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
S'applique à :SQL Server
Cet article s'applique aux instances SQL Server.
Remarque
Cet article est axé sur SQL Server. Pour en savoir plus sur cette erreur dans les plateformes Azure SQL, reportez-vous à Dépannage des erreurs de journal des transactions avec Azure SQL Database et Dépannage des erreurs de journal des transactions avec Azure SQL Managed Instance. Azure SQL Database et Azure SQL Managed Instance sont basés sur la dernière version stable du moteur de base de données Microsoft SQL Server. Une grande partie du contenu est donc similaire, même si les options et les outils de résolution des problèmes peuvent différer.
Option 1 : Exécuter les étapes directement dans un notebook exécutable via Azure Data Studio
Avant d’essayer d’ouvrir ce notebook, vérifiez que Azure Data Studio est installé sur votre ordinateur local. Pour l’installer, accédez au téléchargement et à l’installation d’Azure Data Studio.
Option 2 : Suivez les étapes manuellement
Cet article décrit les réactions possibles à un journal des transactions saturé et émet quelques suggestions qui vous permettront d'éviter cette situation à l'avenir.
Lorsque le journal des transactions est plein, le moteur de base de données SQL Server émet une erreur 9002. Le journal peut être renseigné quand la base de données est en ligne ou en cours de récupération. Si le journal se remplit tandis que la base de données est en ligne, la base de données reste en ligne mais elle peut uniquement être lue, et pas être mise à jour. Si le journal se remplit pendant la récupération, le moteur de base de données marque la base de données comme RESOURCE PENDING
. Dans les deux cas, une intervention de l'utilisateur est nécessaire pour libérer de l'espace disque.
Raisons courantes d’un journal des transactions saturé
La réponse adéquate à un journal des transactions saturé dépend en partie de la ou des conditions qui ont motivé le remplissage du journal. Les causes courantes sont les suivantes :
- Journal non tronqué
- Volume de disque plein
- La taille du journal est définie sur une valeur maximale fixe ou la croissance automatique est désactivée
- Synchronisation de la réplication ou du groupe de disponibilité qui ne peut pas se terminer
Suivez ces étapes spécifiques pour vous aider à trouver la raison d’un journal des transactions complet et à résoudre le problème.
- Tronquer le journal
- Résoudre un problème de disque plein
- Modifier la limite de taille du journal ou activer la croissance automatique
1. Tronquer le journal
Une solution courante à ce problème consiste à garantir que les sauvegardes de journal des transactions sont effectuées pour votre base de données, ce qui garantit que le journal est tronqué. Si aucun historique récent du journal des transactions n’est indiqué pour la base de données avec un journal des transactions saturé, la solution au problème est simple : reprendre les sauvegardes régulières du journal des transactions de la base de données.
Pour plus d’informations, consultez Gérer la taille du fichier journal des transactions et réduire un fichier.
Explication de la troncation du journal
Il y a une différence entre tronquer un journal des transactions et réduire un journal des transactions. La troncation du journal se produit normalement pendant une sauvegarde du journal des transactions, et c’est une opération logique qui supprime les enregistrements validés dans le journal, tandis que la réduction du journal libère de l’espace physique sur le système de fichiers en réduisant la taille du fichier. La troncation du journal se produit sur une limite de fichier journal virtuel (VLF) et un fichier journal peut contenir plusieurs fichiers journaux virtuels. Un fichier journal ne peut être réduit que s'il y a de l'espace vide à l'intérieur du fichier journal à récupérer. La réduction d’un fichier journal seul ne peut pas résoudre le problème d’un fichier journal saturé. Au lieu de cela, vous devez découvrir pourquoi le fichier journal est saturé et ne peut pas être tronqué.
Avertissement
Les données qui sont déplacées pour réduire un fichier peuvent être dispersées à n'importe quel emplacement disponible dans le fichier. Cela provoque la fragmentation de l'index et peut ralentir les performances des requêtes qui recherchent une plage de l'index. Pour éliminer la fragmentation, reconstruisez les index dans le fichier après réduction. Pour plus d’informations, consultez Réduction d’une base de données.
Qu’est-ce qui empêche la troncation du journal ?
Pour découvrir ce qui empêche la troncation du journal dans un cas donné, reportez-vous aux colonnes log_reuse_wait
et log_reuse_wait_desc
de la vue catalogue sys.databases
. Pour plus d’informations, consultez sys.databases. Pour obtenir une description des facteurs susceptibles de retarder la troncation du journal, consultez Journal des transactions.
L’ensemble suivant de commandes T-SQL vous aide à identifier si le journal des transactions d’une base de données n’est pas tronqué et à en déterminer la raison. Le script suivant recommande également les étapes de résolution du problème :
SET NOCOUNT ON;
DECLARE
@SQL AS VARCHAR (8000),
@log_reuse_wait AS TINYINT,
@log_reuse_wait_desc AS NVARCHAR (120),
@dbname AS SYSNAME,
@database_id AS INT,
@recovery_model_desc AS VARCHAR (24);
IF (OBJECT_id(N'tempdb..#CannotTruncateLog_Db') IS NOT NULL)
BEGIN
DROP TABLE #CannotTruncateLog_Db;
END
--get info about transaction logs in each database.
IF (OBJECT_id(N'tempdb..#dm_db_log_space_usage') IS NOT NULL)
BEGIN
DROP TABLE #dm_db_log_space_usage;
END
SELECT *
INTO #dm_db_log_space_usage
FROM sys.dm_db_log_space_usage
WHERE 1 = 0;
DECLARE log_space CURSOR
FOR SELECT NAME
FROM sys.databases;
OPEN log_space;
FETCH NEXT FROM log_space INTO @dbname;
WHILE @@FETCH_STATUS = 0
BEGIN
SET @SQL = '
INSERT INTO #dm_db_log_space_usage (
database_id,
total_log_size_in_bytes,
used_log_space_in_bytes,
used_log_space_in_percent,
log_space_in_bytes_since_last_backup
)
SELECT database_id,
total_log_size_in_bytes,
used_log_space_in_bytes,
used_log_space_in_percent,
log_space_in_bytes_since_last_backup
FROM ' + QUOTENAME(@dbname) + '.sys.dm_db_log_space_usage;';
BEGIN TRY
EXECUTE (@SQL);
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ErrorMessage;
END CATCH
FETCH NEXT FROM log_space INTO @dbname;
END
CLOSE log_space;
DEALLOCATE log_space;
--select the affected databases
SELECT
sdb.name AS DbName,
sdb.log_reuse_wait,
sdb.log_reuse_wait_desc,
CASE
WHEN log_reuse_wait = 1 THEN 'No checkpoint has occurred since the last log truncation, or the head of the log has not yet moved beyond'
WHEN log_reuse_wait = 2 THEN 'A log backup is required before the transaction log can be truncated.'
WHEN log_reuse_wait = 3 THEN 'A data backup or a restore is in progress (all recovery models). Please wait or cancel backup'
WHEN log_reuse_wait = 4 THEN 'A long-running active transaction or a deferred transaction is keeping log from being truncated. You can attempt a log backup to free space or complete/rollback long transaction'
WHEN log_reuse_wait = 5 THEN 'Database mirroring is paused, or under high-performance mode, the mirror database is significantly behind the principal database. (Full recovery model only)'
WHEN log_reuse_wait = 6 THEN 'During transactional replication, transactions relevant to the publications are still undelivered to the distribution database. Investigate the status of agents involved in replication or Changed Data Capture (CDC). (Full recovery model only.)'
WHEN log_reuse_wait = 7 THEN 'A database snapshot is being created. This is a routine, and typically brief, cause of delayed log truncation.'
WHEN log_reuse_wait = 8 THEN 'A transaction log scan is occurring. This is a routine, and typically a brief cause of delayed log truncation.'
WHEN log_reuse_wait = 9 THEN 'A secondary replica of an availability group is applying transaction log records of this database to a corresponding secondary database. (Full recovery model only.)'
WHEN log_reuse_wait = 13 THEN 'If a database is configured to use indirect checkpoints, the oldest page on the database might be older than the checkpoint log sequence number (LSN).'
WHEN log_reuse_wait = 16 THEN 'An In-Memory OLTP checkpoint has not occurred since the last log truncation, or the head of the log has not yet moved beyond a VLF.'
ELSE 'None'
END AS log_reuse_wait_explanation,
sdb.database_id,
sdb.recovery_model_desc,
lsu.used_log_space_in_bytes / 1024 AS Used_log_size_MB,
lsu.total_log_size_in_bytes / 1024 AS Total_log_size_MB,
100 - lsu.used_log_space_in_percent AS Percent_Free_Space
INTO #CannotTruncateLog_Db
FROM sys.databases AS sdb
INNER JOIN #dm_db_log_space_usage AS lsu
ON sdb.database_id = lsu.database_id
WHERE log_reuse_wait > 0;
SELECT * FROM #CannotTruncateLog_Db;
DECLARE no_truncate_db CURSOR FOR
SELECT
log_reuse_wait,
log_reuse_wait_desc,
DbName,
database_id,
recovery_model_desc
FROM #CannotTruncateLog_Db;
OPEN no_truncate_db;
FETCH NEXT FROM no_truncate_db
INTO
@log_reuse_wait,
@log_reuse_wait_desc,
@dbname,
@database_id,
@recovery_model_desc;
WHILE @@FETCH_STATUS = 0
BEGIN
IF (@log_reuse_wait > 0)
BEGIN
SELECT '-- ' + QUOTENAME(@dbname) + ' database has log_reuse_wait = ' + @log_reuse_wait_desc + ' --' AS 'Individual Database Report';
END
IF (@log_reuse_wait = 1)
BEGIN
SELECT 'Consider running the checkpoint command to attempt resolving this issue or further t-shooting may be required on the checkpoint process. Also, examine the log for active VLFs at the end of file' AS Recommendation;
SELECT 'USE ' + QUOTENAME(@dbname) + '; CHECKPOINT' AS CheckpointCommand;
SELECT 'SELECT * FROM sys.dm_db_log_info(' + CONVERT (VARCHAR, @database_id) + ')' AS VLF_LogInfo;
END
ELSE IF (@log_reuse_wait = 2)
BEGIN
SELECT 'Is ' + @recovery_model_desc + ' recovery model the intended choice for ' + QUOTENAME(@dbname) + ' database? Review recovery models and determine if you need to change it. https://learn.microsoft.com/sql/relational-databases/backup-restore/recovery-models-sql-server' AS RecoveryModelChoice;
SELECT 'To truncate the log consider performing a transaction log backup on database ' + QUOTENAME(@dbname) + ' which is in ' + @recovery_model_desc + ' recovery model. Be mindful of any existing log backup chains that could be broken' AS Recommendation;
SELECT 'BACKUP LOG ' + QUOTENAME(@dbname) + ' TO DISK = ''some_volume:\some_folder\' + QUOTENAME(@dbname) + '_LOG.trn '';' AS BackupLogCommand;
END
ELSE IF (@log_reuse_wait = 3)
BEGIN
SELECT 'Either wait for or cancel any active backups currently running for database ' + QUOTENAME(@dbname) + '. To check for backups, run this command:' AS Recommendation;
SELECT 'SELECT * FROM sys.dm_exec_requests WHERE command LIKE ''backup%'' OR command LIKE ''restore%''' AS FindBackupOrRestore;
END
ELSE IF (@log_reuse_wait = 4)
BEGIN
SELECT 'Active transactions currently running for database ' + QUOTENAME(@dbname) + '. To check for active transactions, run these commands:' AS Recommendation;
SELECT 'DBCC OPENTRAN (' + QUOTENAME(@dbname) + ')' AS FindOpenTran;
SELECT 'SELECT database_id, db_name(database_id) AS dbname, database_transaction_begin_time, database_transaction_state, database_transaction_log_record_count, database_transaction_log_bytes_used, database_transaction_begin_lsn, stran.session_id FROM sys.dm_tran_database_transactions dbtran LEFT OUTER JOIN sys.dm_tran_session_transactions stran ON dbtran.transaction_id = stran.transaction_id WHERE database_id = ' + CONVERT (VARCHAR, @database_id) AS FindOpenTransAndSession;
END
ELSE IF (@log_reuse_wait = 5)
BEGIN
SELECT 'Database Mirroring for database ' + QUOTENAME(@dbname) + ' is behind on synchronization. To check the state of DBM, run the commands below:' AS Recommendation;
SELECT 'SELECT db_name(database_id), mirroring_state_desc, mirroring_role_desc, mirroring_safety_level_desc FROM sys.database_mirroring WHERE mirroring_guid IS NOT NULL and mirroring_state <> 4 AND database_id = ' + CONVERT (sysname, @database_id) AS CheckMirroringStatus;
SELECT 'Database Mirroring for database ' + QUOTENAME(@dbname) + ' may be behind: check unsent_log, send_rate, unrestored_log, recovery_rate, average_delay in this output' AS Recommendation;
SELECT 'EXECUTE msdb.sys.sp_dbmmonitoraddmonitoring 1; EXECUTE msdb.sys.sp_dbmmonitorresults ' + QUOTENAME(@dbname) + ', 5, 0; WAITFOR DELAY ''00:01:01''; EXECUTE msdb.sys.sp_dbmmonitorresults ' + QUOTENAME(@dbname) + '; EXECUTE msdb.sys.sp_dbmmonitordropmonitoring' AS CheckMirroringStatusAnd;
END
ELSE IF (@log_reuse_wait = 6)
BEGIN
SELECT 'Replication transactions still undelivered FROM publisher database ' + QUOTENAME(@dbname) + ' to Distribution database. Check the oldest non-distributed replication transaction. Also check if the Log Reader Agent is running and if it has encountered any errors' AS Recommendation;
SELECT 'DBCC OPENTRAN (' + QUOTENAME(@dbname) + ')' AS CheckOldestNonDistributedTran;
SELECT 'SELECT top 5 * FROM distribution..MSlogreader_history WHERE runstatus in (6, 5) OR error_id <> 0 AND agent_id = find_in_mslogreader_agents_table ORDER BY time desc ' AS LogReaderAgentState;
END
ELSE IF (@log_reuse_wait = 9)
BEGIN
SELECT 'Always On transactions still undelivered FROM primary database ' + QUOTENAME(@dbname) + ' to Secondary replicas. Check the Health of AG nodes and if there is latency is Log block movement to Secondaries' AS Recommendation;
SELECT 'SELECT availability_group = CAST(ag.name AS VARCHAR(30)), primary_replica = CAST(ags.primary_replica AS VARCHAR(30)), primary_recovery_health_desc = CAST(ags.primary_recovery_health_desc AS VARCHAR(30)), synchronization_health_desc = CAST(ags.synchronization_health_desc AS VARCHAR(30)), ag.failure_condition_level, ag.health_check_timeout, automated_backup_preference_desc = CAST(ag.automated_backup_preference_desc AS VARCHAR(10)) FROM sys.availability_groups ag join sys.dm_hadr_availability_group_states ags on ag.group_id=ags.group_id' AS CheckAGHealth;
SELECT 'SELECT group_name = CAST(arc.group_name AS VARCHAR(30)), replica_server_name = CAST(arc.replica_server_name AS VARCHAR(30)), node_name = CAST(arc.node_name AS VARCHAR(30)), role_desc = CAST(ars.role_desc AS VARCHAR(30)), ar.availability_mode_Desc, operational_state_desc = CAST(ars.operational_state_desc AS VARCHAR(30)), connected_state_desc = CAST(ars.connected_state_desc AS VARCHAR(30)), recovery_health_desc = CAST(ars.recovery_health_desc AS VARCHAR(30)), synchronization_health_desc = CAST(ars.synchronization_health_desc AS VARCHAR(30)), ars.last_connect_error_number, last_connect_error_description = CAST(ars.last_connect_error_description AS VARCHAR(30)), ars.last_connect_error_timestamp, primary_role_allow_connections_desc = CAST(ar.primary_role_allow_connections_desc AS VARCHAR(30)) FROM sys.dm_hadr_availability_replica_cluster_nodes arc join sys.dm_hadr_availability_replica_cluster_states arcs on arc.replica_server_name=arcs.replica_server_name join sys.dm_hadr_availability_replica_states ars on arcs.replica_id=ars.replica_id join sys.availability_replicas ar on ars.replica_id=ar.replica_id join sys.availability_groups ag on ag.group_id = arcs.group_id and ag.name = arc.group_name ORDER BY CAST(arc.group_name AS VARCHAR(30)), CAST(ars.role_desc AS VARCHAR(30))' AS CheckReplicaHealth;
SELECT 'SELECT database_name = CAST(drcs.database_name AS VARCHAR(30)), drs.database_id, drs.group_id, drs.replica_id, drs.is_local, drcs.is_failover_ready, drcs.is_pending_secondary_suspend, drcs.is_database_joined, drs.is_suspended, drs.is_commit_participant, suspend_reason_desc = CAST(drs.suspend_reason_desc AS VARCHAR(30)), synchronization_state_desc = CAST(drs.synchronization_state_desc AS VARCHAR(30)), synchronization_health_desc = CAST(drs.synchronization_health_desc AS VARCHAR(30)), database_state_desc = CAST(drs.database_state_desc AS VARCHAR(30)), drs.last_sent_lsn, drs.last_sent_time, drs.last_received_lsn, drs.last_received_time, drs.last_hardened_lsn, drs.last_hardened_time, drs.last_redone_lsn, drs.last_redone_time, drs.log_send_queue_size, drs.log_send_rate, drs.redo_queue_size, drs.redo_rate, drs.filestream_send_rate, drs.end_of_log_lsn, drs.last_commit_lsn, drs.last_commit_time, drs.low_water_mark_for_ghosts, drs.recovery_lsn, drs.truncation_lsn, pr.file_id, pr.error_type, pr.page_id, pr.page_status, pr.modification_time FROM sys.dm_hadr_database_replica_cluster_states drcs join sys.dm_hadr_database_replica_states drs on drcs.replica_id=drs.replica_id and drcs.group_database_id=drs.group_database_id left outer join sys.dm_hadr_auto_page_repair pr on drs.database_id=pr.database_id order by drs.database_id' AS LogMovementHealth;
SELECT 'For more information see https://learn.microsoft.com/troubleshoot/sql/availability-groups/error-9002-transaction-log-large' AS OnlineDOCResource;
END
ELSE IF (@log_reuse_wait IN (10, 11, 12, 14))
BEGIN
SELECT 'This state is not documented and is expected to be rare and short-lived' AS Recommendation;
END
ELSE IF (@log_reuse_wait = 13)
BEGIN
SELECT 'The oldest page on the database might be older than the checkpoint log sequence number (LSN). In this case, the oldest page can delay log truncation.' AS Finding;
SELECT 'This state should be short-lived, but if you find it is taking a long time, you can consider disabling Indirect Checkpoint temporarily' AS Recommendation;
SELECT 'ALTER DATABASE ' + QUOTENAME(@dbname) + ' SET TARGET_RECOVERY_TIME = 0 SECONDS;' AS DisableIndirectCheckpointTemporarily;
END
ELSE IF (@log_reuse_wait = 16)
BEGIN
SELECT 'For memory-optimized tables, an automatic checkpoint is taken when transaction log file becomes bigger than 1.5 GB since the last checkpoint (includes both disk-based and memory-optimized tables)' AS Finding;
SELECT 'Review https://learn.microsoft.com/archive/blogs/sqlcat/logging-and-checkpoint-process-for-memory-optimized-tables-2' AS ReviewBlog;
SELECT 'USE ' + QUOTENAME(@dbname) + '; CHECKPOINT;' AS RunCheckpoint;
END
FETCH NEXT FROM no_truncate_db INTO
@log_reuse_wait,
@log_reuse_wait_desc,
@dbname,
@database_id,
@recovery_model_desc;
END
CLOSE no_truncate_db;
DEALLOCATE no_truncate_db;
Important
Si la base de données était en cours de récupération lorsque l’erreur 9002 s’est produite, après avoir résolu le problème, récupérez la base de données à l’aide de ALTER DATABASE database_name SET ONLINE.
LOG_BACKUP log_reuse_wait
L’action la plus courante à prendre en compte si vous voyez LOG_BACKUP
ou log_reuse_wait
si vous souhaitez examiner votre modèle de récupération de base de données et sauvegarder le journal des transactions de votre base de données.
Prendre en compte le modèle de récupération de la base de données
Le journal des transactions peut ne pas se tronquer avec la catégorie LOG_BACKUP
ou log_reuse_wait
, car vous ne l'avez jamais sauvegardé. Dans de nombreux cas, votre base de données utilise le modèle de récupération FULL
ou BULK_LOGGED
, mais vous n’avez pas sauvegardé votre journal des transactions. Vous devez envisager soigneusement chaque modèle de récupération de base de données : effectuez des sauvegardes régulières du journal des transactions sur toutes les bases de données utilisant les modèles de récupération FULL
ou BULK_LOGGED
, afin de réduire les occurrences de l’erreur 9002. Pour plus d’informations, consultez Modes de récupération.
Sauvegarder le journal
Sous le modèle de récupération FULL
ou BULK_LOGGED
, si le journal des transactions n’a pas été sauvegardé récemment, la sauvegarde pourrait être ce qui empêche la troncation du journal. Vous devez sauvegarder le journal des transactions pour permettre la publication des enregistrements de journal et la troncation du journal. Si le journal n'a jamais été sauvegardé, vous devez en créer deux sauvegardes pour permettre au moteur de base de données de le tronquer à l'endroit exact de la dernière sauvegarde. Le fait de tronquer le journal permet de libérer de l'espace pour les nouveaux enregistrements de ce dernier. Pour empêcher le journal de se remplir à nouveau, effectuez les sauvegardes régulièrement et plus fréquemment. Pour plus d’informations, consultez Modes de récupération.
Un historique complet de toutes les opérations de restauration et de sauvegarde SQL Server sur une instance de serveur est stocké dans la base de données système msdb
. Pour consulter l’historique de sauvegarde complet d’une base de données, utilisez l’exemple de script suivant :
SELECT bs.database_name,
CASE
WHEN bs.type = 'D' AND bs.is_copy_only = 0 THEN 'Full Database'
WHEN bs.type = 'D' AND bs.is_copy_only = 1 THEN 'Full Copy-Only Database'
WHEN bs.type = 'I' THEN 'Differential database backup'
WHEN bs.type = 'L' THEN 'Transaction Log'
WHEN bs.type = 'F' THEN 'File or filegroup'
WHEN bs.type = 'G' THEN 'Differential file'
WHEN bs.type = 'P' THEN 'Partial'
WHEN bs.type = 'Q' THEN 'Differential partial'
END + ' Backup' AS backuptype,
bs.recovery_model,
bs.Backup_Start_Date AS BackupStartDate,
bs.Backup_Finish_Date AS BackupFinishDate,
bf.physical_device_name AS LatestBackupLocation,
bs.backup_size / 1024. / 1024. AS backup_size_mb,
bs.compressed_backup_size / 1024. / 1024. AS compressed_backup_size_mb,
database_backup_lsn, -- For tlog and differential backups, this is the checkpoint_lsn of the FULL backup it is based on.
checkpoint_lsn,
begins_log_chain
FROM msdb.dbo.backupset AS bs
LEFT OUTER JOIN msdb.dbo.backupmediafamily AS bf
ON bs.[media_set_id] = bf.[media_set_id]
WHERE recovery_model IN ('FULL', 'BULK-LOGGED')
AND bs.backup_start_date > DATEADD(month, -2, SYSDATETIME()) --only look at last two months
ORDER BY bs.database_name ASC, bs.Backup_Start_Date DESC;
Un historique complet de toutes les opérations de restauration et de sauvegarde SQL Server sur une instance de serveur est stocké dans la base de données système msdb
. Pour plus d’informations sur l’historique de sauvegarde, consultez Historique de sauvegarde et informations d’en-tête (SQL Server).
Créer une sauvegarde de fichier journal
Exemple de procédure de sauvegarde du journal :
BACKUP LOG [dbname] TO DISK = 'some_volume:\some_folder\dbname_LOG.trn';
Important
Si la base de données est endommagée, reportez-vous à la section Sauvegarde de la fin du journal (SQL Server).
ACTIVE_TRANSACTION log_reuse_wait
Les étapes de résolution des problèmes pour la raison ACTIVE_TRANSACTION
incluent la découverte de la transaction durable et sa résolution (dans certains cas, à l’aide de la commande KILL
).
Découvrir des transactions de longue durée
Une transaction longue peut entraîner le remplissage du journal des transactions. Pour rechercher des transactions de longue durée, utilisez l’une des options suivantes :
sys.dm_tran_database_transactions :
Cet affichage de gestion dynamique retourne des informations sur les transactions au niveau de la base de données. Pour une transaction de longue durée, les colonnes d’intérêt particulier incluent l’heure du premier enregistrement du journal (
database_transaction_begin_time
), l’état actuel de la transaction (database_transaction_state
) et le numéro de séquence de journal (LSN) de l’enregistrementBEGIN
dans le journal des transactions (database_transaction_begin_lsn
).-
Cette instruction vous permet d'identifier l'ID du propriétaire de la transaction et éventuellement de retrouver la source de la transaction pour y mettre fin dans les règles de l'art (la valider au lieu de la restaurer).
Supprimer une transaction
Parfois, il suffit d’arrêter la transaction. Vous devez éventuellement utiliser l’instruction KILL. Utilisez l’instruction KILL
avec une prudence extrême, en particulier lorsque les processus critiques sont en cours d’exécution que vous ne souhaitez pas mettre fin.
POINT DE CONTRÔLE log_reuse_wait
Aucun point de contrôle n'est apparu depuis la dernière troncation du journal ou le début du journal n'est pas encore allé au-delà d'un fichier journal virtuel (VLF), dans tous les modes de récupération.
Il s'agit d'une raison courante de retarder la troncation du journal. En cas de retard, envisagez d’exécuter la commande CHECKPOINT
sur la base de données ou d’examiner les fichiers journaux virtuels (VLF).
USE dbname;
CHECKPOINT;
SELECT * FROM sys.dm_db_log_info(db_id('dbname'));
AVAILABILITY_REPLICA log_reuse_wait
Quand les modifications de transaction au niveau du réplica du groupe de disponibilité Always On principal ne sont pas encore renforcées sur le réplica secondaire, le journal des transactions du réplica principal ne peut pas être tronqué. La taille du journal peut alors augmenter. Cela peut se produire peu importe que le réplica secondaire soit défini pour le mode de validation synchrone ou asynchrone. Pour plus d’informations sur la résolution de ce type de problème, consultez Erreur 9002. Le journal des transactions de la base de données est saturé en raison de l’erreur AVAILABILITY_REPLICA.
Réplication, suivi des modifications ou CDC
Les fonctionnalités telles que la réplication, le suivi des modifications et la capture des changements de données (CDC) s’appuient sur le journal des transactions. Par conséquent, si des transactions ou des modifications ne sont pas remises, cela peut empêcher la troncation du journal des transactions.
Utilisez DBCC OPENTRAN, le moniteur de réplication ou les procédures stockées pour le suivi des modifications et la capture des changements de données (CDC) pour examiner et résoudre les problèmes liés à ces fonctionnalités.
Trouver des informations sur les facteurs log_reuse_wait
Pour plus d’informations, consultez Facteurs pouvant retarder la troncation du journal.
2. Résoudre le volume de disque complet
Dans certains cas, le volume de disque qui héberge le fichier journal de transactions peut être rempli. Vous pouvez effectuer l’une des actions suivantes pour résoudre le scénario journal complet qui résulte d’un disque complet :
Espace disque disponible
Vous pouvez libérer de l'espace sur le disque où est stocké le fichier journal des transactions de la base de données en supprimant ou en déplaçant d'autres fichiers. Ceci permet au système de récupération d'augmenter automatiquement la taille du fichier journal.
Déplacer le fichier journal vers un autre disque
Si vous ne pouvez pas libérer suffisamment d’espace disque sur le lecteur où le fichier journal se trouve actuellement, essayez de déplacer ce fichier sur une autre unité disposant d’espace suffisant.
Important
Les fichiers journaux ne doivent jamais être placés sur des systèmes de fichiers compressés.
Consultez Déplacer des fichiers de base de données pour plus d’informations sur la modification de l’emplacement d’un fichier journal.
Ajout d’un fichier journal sur un autre disque
Ajoutez un nouveau fichier journal à la base de données sur un autre disque disposant d’un espace suffisant à l’aide de ALTER DATABASE <database_name> ADD LOG FILE
. Plusieurs fichiers journaux d’une base de données unique doivent être considérés comme une condition temporaire pour résoudre un problème d’espace, et non une condition à long terme. La plupart des bases de données ne doivent avoir qu’un seul fichier journal des transactions. Continuez à examiner la raison pour laquelle le journal des transactions est plein et ne peut pas être tronqué. Envisagez d’ajouter des fichiers journaux de transactions temporaires supplémentaires uniquement en tant qu’étape de résolution des problèmes avancée.
Pour plus d’informations, consultez Ajouter des fichiers de données ou journaux à une base de données.
Script de l’utilitaire pour les actions recommandées
Ces étapes peuvent être partiellement automatisées en exécutant le script T-SQL suivant pour identifier les fichiers journaux qui utilisent un pourcentage important d’espace disque et suggèrer des actions :
DECLARE @log_reached_disk_size AS BIT = 0;
SELECT [name] AS LogName,
physical_name,
CONVERT (BIGINT, size) * 8 / 1024 AS LogFile_Size_MB,
volume_mount_point,
available_bytes / 1024 / 1024 AS Available_Disk_space_MB,
(CONVERT (BIGINT, size) * 8.0 / 1024) / (available_bytes / 1024 / 1024) * 100 AS file_size_as_percentage_of_disk_space,
db_name(mf.database_id) AS DbName
FROM sys.master_files AS mf
CROSS APPLY sys.dm_os_volume_stats(mf.database_id, file_id)
WHERE mf.[type_desc] = 'LOG'
AND (CONVERT (BIGINT, size) * 8.0 / 1024) / (available_bytes / 1024 / 1024) * 100 > 90 --log is 90% of disk drive
ORDER BY size DESC;
IF @@ROWCOUNT > 0
BEGIN
SET @log_reached_disk_size = 1;
-- Discover if any logs have filled the volume they reside on, or are close to filling the volume.
-- Either add a new file to a new drive, or shrink an existing file.
-- If it cannot shrink, direct the script to recommend next steps.
DECLARE @db_name_filled_disk AS sysname, @log_name_filled_disk AS sysname, @go_beyond_size AS BIGINT;
DECLARE log_filled_disk CURSOR
FOR SELECT db_name(mf.database_id),
name
FROM sys.master_files AS mf
CROSS APPLY sys.dm_os_volume_stats(mf.database_id, file_id)
WHERE mf.[type_desc] = 'LOG'
AND (CONVERT (BIGINT, size) * 8.0 / 1024) / (available_bytes / 1024 / 1024) * 100 > 90 --log is 90% of disk drive
ORDER BY size DESC;
OPEN log_filled_disk;
FETCH NEXT FROM log_filled_disk INTO @db_name_filled_disk, @log_name_filled_disk;
WHILE @@FETCH_STATUS = 0
BEGIN
SELECT 'Transaction log for database "' + @db_name_filled_disk + '" has nearly or completely filled disk volume it resides on!' AS Finding;
SELECT 'Consider using one of the below commands to shrink the "' + @log_name_filled_disk + '" transaction log file size or add a new file to a NEW volume' AS Recommendation;
SELECT 'DBCC SHRINKFILE(''' + @log_name_filled_disk + ''')' AS Shrinkfile_Command;
SELECT 'ALTER DATABASE ' + @db_name_filled_disk + ' ADD LOG FILE ( NAME = N''' + @log_name_filled_disk + '_new'', FILENAME = N''NEW_VOLUME_AND_FOLDER_LOCATION\' + @log_name_filled_disk + '_NEW.LDF'', SIZE = 81920KB , FILEGROWTH = 65536KB )' AS AddNewFile;
SELECT 'If shrink does not reduce the file size, likely it is because it has not been truncated. Please review next section below. See https://learn.microsoft.com/sql/t-sql/database-console-commands/dbcc-shrinkfile-transact-sql' AS TruncateFirst;
SELECT 'Can you free some disk space on this volume? If so, do this to allow for the log to continue growing when needed.' AS FreeDiskSpace;
FETCH NEXT FROM log_filled_disk INTO @db_name_filled_disk, @log_name_filled_disk;
END
CLOSE log_filled_disk;
DEALLOCATE log_filled_disk;
END
3. Modifier la limite de taille du journal ou activer la croissance automatique
L’erreur 9002 peut être générée si la taille du journal des transactions est définie sur une limite supérieure ou si la fonctionnalité de croissance automatique n’est pas autorisée. Dans ce cas, l’activation de la croissance automatique ou l’augmentation manuelle de la taille du journal peut aider à résoudre le problème. Utilisez cette commande T-SQL pour rechercher ces fichiers journaux et suivez les recommandations fournies :
SELECT DB_NAME(database_id) AS DbName,
name AS LogName,
physical_name,
type_desc,
CONVERT (BIGINT, SIZE) * 8 / 1024 AS LogFile_Size_MB,
CONVERT (BIGINT, max_size) * 8 / 1024 AS LogFile_MaxSize_MB,
(SIZE * 8.0 / 1024) / (max_size * 8.0 / 1024) * 100 AS percent_full_of_max_size,
CASE WHEN growth = 0 THEN 'AUTOGROW_DISABLED' ELSE 'Autogrow_Enabled' END AS AutoGrow
FROM sys.master_files
WHERE file_id = 2
AND (SIZE * 8.0 / 1024) / (max_size * 8.0 / 1024) * 100 > 90
AND max_size NOT IN (-1, 268435456)
OR growth = 0;
IF @@ROWCOUNT > 0
BEGIN
DECLARE @db_name_max_size AS sysname, @log_name_max_size AS sysname, @configured_max_log_boundary AS BIGINT, @auto_grow AS INT;
DECLARE reached_max_size CURSOR
FOR SELECT db_name(database_id),
name,
CONVERT (BIGINT, SIZE) * 8 / 1024,
growth
FROM sys.master_files
WHERE file_id = 2
AND ((SIZE * 8.0 / 1024) / (max_size * 8.0 / 1024) * 100 > 90
AND max_size NOT IN (-1, 268435456)
OR growth = 0);
OPEN reached_max_size;
FETCH NEXT FROM reached_max_size INTO @db_name_max_size, @log_name_max_size, @configured_max_log_boundary, @auto_grow;
WHILE @@FETCH_STATUS = 0
BEGIN
IF @auto_grow = 0
BEGIN
SELECT 'The database "' + @db_name_max_size + '" contains a log file "' + @log_name_max_size + '" whose autogrow has been DISABLED' AS Finding;
SELECT 'Consider enabling autogrow or increasing file size via these ALTER DATABASE commands' AS Recommendation;
SELECT 'ALTER DATABASE ' + @db_name_max_size + ' MODIFY FILE ( NAME = N''' + @log_name_max_size + ''', FILEGROWTH = 65536KB)' AS AutoGrowth;
END
ELSE
BEGIN
SELECT 'The database "' + @db_name_max_size + '" contains a log file "' + @log_name_max_size + '" whose max limit is set to ' + CONVERT (VARCHAR (24), @configured_max_log_boundary) + ' MB and this limit has been reached!' AS Finding;
SELECT 'Consider using one of the below ALTER DATABASE commands to either change the log file size or add a new file' AS Recommendation;
END
SELECT 'ALTER DATABASE ' + @db_name_max_size + ' MODIFY FILE ( NAME = N''' + @log_name_max_size + ''', MAXSIZE = UNLIMITED)' AS UnlimitedSize;
SELECT 'ALTER DATABASE ' + @db_name_max_size + ' MODIFY FILE ( NAME = N''' + @log_name_max_size + ''', MAXSIZE = something_larger_than_' + CONVERT (VARCHAR (24), @configured_max_log_boundary) + 'MB )' AS IncreasedSize;
SELECT 'ALTER DATABASE ' + @db_name_max_size + ' ADD LOG FILE ( NAME = N''' + @log_name_max_size + '_new'', FILENAME = N''SOME_FOLDER_LOCATION\' + @log_name_max_size + '_NEW.LDF'', SIZE = 81920KB , FILEGROWTH = 65536KB )' AS AddNewFile;
FETCH NEXT FROM reached_max_size INTO @db_name_max_size, @log_name_max_size, @configured_max_log_boundary, @auto_grow;
END
CLOSE reached_max_size;
DEALLOCATE reached_max_size;
END
ELSE
SELECT 'Found no files that have reached max log file size' AS Findings;
Augmenter la taille du fichier journal ou activer la croissance automatique
Si le disque du journal dispose d'espace libre, vous pouvez augmenter la taille du fichier journal. La taille maximale pour les fichiers journaux est de 2 téraoctets (To) par fichier journal.
Si la fonctionnalité de croissance automatique est désactivée, que la base de données est en ligne et que l’espace disque disponible est suffisant, effectuez les étapes suivantes :
Augmentez manuellement la taille du fichier pour générer un seul incrément de croissance. Il s’agit de recommandations générales sur la taille et la croissance du journal.
Activez la croissance automatique à l’aide de l’instruction
ALTER DATABASE
pour définir un incrément de croissance différent de zéro pour l’optionFILEGROWTH
. Consultez Considérations relatives aux paramètres de croissance automatique et de réduction automatique dans SQL Server.
Remarque
Dans les deux cas, si la limite de taille actuelle est atteinte, augmentez la MAXSIZE
valeur.
Contenu connexe
- MODIFIER LA BASE DE DONNÉES (Transact-SQL)
- Gérer la taille du fichier journal des transactions
- Sauvegardes du journal des transactions (SQL Server)
- sp_add_log_file_recover_suspect_db (Transact-SQL)
- MSSQLSERVER_9002
- Comment la structure de fichier journal peut affecter le temps de récupération de la base de données – Microsoft Tech Community