Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Si applica a:SQL Server
Questo articolo è relativo alle istanze di SQL Server.
Nota
Questo articolo è incentrato su SQL Server. Per informazioni più specifiche su questo errore nelle piattaforme Azure SQL, vedere Risoluzione degli errori del log delle transazioni con database SQL di Azure e Risoluzione degli errori del log delle transazioni con Istanza gestita di SQL di Azure. Database SQL di Azure e Istanza gestita di SQL di Azure si basano sulla versione stabile più recente del motore di database di Microsoft SQL Server, quindi gran parte del contenuto è simile anche se le opzioni e gli strumenti per la risoluzione dei problemi possono differire.
Opzione 1: Eseguire i passaggi direttamente in un notebook eseguibile tramite Azure Data Studio
Prima di provare ad aprire questo notebook, controllare che Azure Data Studio sia installato nel computer locale. Per installare, passare a Scaricare e installare Azure Data Studio.
Opzione 2: Seguire manualmente i passaggi
In questo articolo vengono illustrate le risposte possibili a un log delle transazioni pieno e viene spiegato come evitare tale situazione in futuro.
Quando il log delle transazioni diventa pieno, il motore di database di SQL Server genera un errore 9002. Il log può riempirsi quando il database è online o in stato di recupero. Se il log si riempie quando il database è online, il database rimane online, ma può solo essere letto, non aggiornato. Se il log viene riempito durante il ripristino, il motore di database contrassegna il database come RESOURCE PENDING
. In entrambi i casi, è richiesto che l'utente intervenga per liberare spazio nel log.
Motivi comuni per un log delle transazioni pieno
La risposta appropriata a un log delle transazioni pieno dipende in parte dalle condizioni che ne hanno causato il riempimento. Le cause comuni includono:
- Il log non viene troncato
- Il volume del disco è pieno
- Le dimensioni del log sono impostate su un valore massimo fisso o l'aumento automatico è disabilitato
- Non è possibile completare la sincronizzazione delle repliche o dei gruppi di disponibilità
Seguire questi passaggi specifici per trovare il motivo di un log delle transazioni completo e risolvere il problema.
- Tronca il log
- Risolvere un disco pieno
- Modificare il limite di dimensioni del log o abilitare l'aumento automatico
1. Truncare il log
Una soluzione comune a questo problema consiste nel garantire che i backup del log delle transazioni vengano eseguiti per il database, assicurando che il log venga troncato. Se non è indicata alcuna cronologia recente del log delle transazioni per il database con un log delle transazioni completo, la soluzione al problema è semplice: riprendere i backup regolari del log delle transazioni del database.
Per altre informazioni, vedere Gestire le dimensioni del file di log delle transazioni e Ridurre le dimensioni di un file.
Spiegazione del troncamento del log
Esiste una differenza tra il troncamento di un log delle transazioni e la riduzione di un log delle transazioni. Il troncamento del log si verifica normalmente durante un backup del log delle transazioni ed è un'operazione logica che rimuove i record di cui è stato eseguito il commit all'interno del log, mentre il ridimensionamento del log recupera lo spazio fisico nel file system riducendo le dimensioni del file. Il troncamento del log si verifica in un limite VLF (Virtual-Log-File) e un file di log può contenere molti VLF. Un file di log può essere compattato solo se è disponibile spazio vuoto all'interno del file di log da recuperare. La compattazione di un file di log da sola non è in grado di risolvere il problema di un file di log completo. È invece necessario scoprire perché il file di log è pieno e non può essere troncato.
Avviso
I dati spostati per compattare un file possono essere sparsi in qualsiasi percorso disponibile all'interno del file. provocando la frammentazione dell'indice e possibilmente rallentando le prestazioni delle query che eseguono ricerche in un intervallo dell'indice. Per eliminare la frammentazione, valutare la possibilità di ricompilare gli indici sul file dopo la compattazione. Per altre informazioni, vedere Ridurre un database.
Cosa impedisce il troncamento del log?
Per individuare la condizione che impedisce il troncamento del log in un caso specifico, usare le colonne log_reuse_wait
e log_reuse_wait_desc
della vista del catalogo sys.databases
. Per altre informazioni, vedere sys.databases. Per le descrizioni dei fattori che possono ritardare il troncamento del log, vedere Log delle transazioni.
Il set di comandi T-SQL seguente consente di identificare se un log delle transazioni del database non viene troncato e il motivo. Lo script seguente consiglia anche i passaggi per risolvere il problema:
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;
Importante
Se il database è stato ripristinato quando si è verificato l'errore 9002, dopo aver risolto il problema, ripristinare il database usando ALTER DATABASE database_name SET ONLINE.
LOG_BACKUP log_reuse_wait
L'azione più comune da considerare se viene visualizzato LOG_BACKUP
o log_reuse_wait
consiste nell'esaminare il modello di recupero del database e eseguire il backup del log delle transazioni del database.
Esaminare il modello di recupero del database
Il log delle transazioni potrebbe non riuscire a troncare con LOG_BACKUP
o log_reuse_wait
categoria, perché non è mai stato eseguito il backup. In molti di questi casi, il database usa il FULL
modello di recupero o BULK_LOGGED
, ma non è stato eseguito il backup del log delle transazioni. È consigliabile considerare attentamente ogni modello di recupero del database: eseguire backup regolari del log delle transazioni in tutti i database in FULL
o BULK_LOGGED
modelli di ripristino, per ridurre al minimo le occorrenze dell'errore 9002. Per altre informazioni, vedere Modelli di recupero.
Eseguire il backup del log
Nel modello di recupero FULL
o BULK_LOGGED
, se il log delle transazioni non è stato sottoposto a backup di recente, il backup potrebbe essere ciò che impedisce il troncamento del log. È necessario eseguire il backup del log delle transazioni per consentire il rilascio dei record e il troncamento del log. Se non è mai stato eseguito il backup del log, è necessario creare due backup del log per consentire al motore di database di troncare il log in corrispondenza del punto dell'ultimo backup. Il troncamento del log rende disponibile spazio per nuovi record. Per evitare che il log si riempia di nuovo, eseguire backup regolari e più frequenti. Per altre informazioni, vedere Modelli di recupero.
Nel database di sistema msdb
viene archiviata una cronologia completa di tutte le operazioni di backup e ripristino di SQL Server eseguite in un'istanza del server. Per esaminare la cronologia completa di backup di un database, usare lo script di esempio seguente:
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;
Nel database di sistema msdb
viene archiviata una cronologia completa di tutte le operazioni di backup e ripristino di SQL Server eseguite in un'istanza del server. Per altre informazioni sulla cronologia dei backup, vedere Informazioni sulla cronologia e sull'intestazione dei backup (SQL Server).
Creare un backup del log delle transazioni
Esempio di come eseguire il backup del log:
BACKUP LOG [dbname] TO DISK = 'some_volume:\some_folder\dbname_LOG.trn';
Importante
Se il database è danneggiato, vedere Backup della parte finale del log (SQL Server).
TRANSAZIONE_ATTIVA log_reuse_wait
I passaggi per la risoluzione dei problemi ACTIVE_TRANSACTION
includono la scoperta e la risoluzione della transazione a esecuzione prolungata (in alcuni casi utilizzando il comando KILL
per farlo).
Scoprire le transazioni di lunga durata
Una transazione a esecuzione prolungata può causare il riempimento del log delle transazioni. Per cercare transazioni con esecuzione prolungata, usare una delle opzioni seguenti:
sys.dm_tran_database_transactions:
Questa vista a gestione dinamica restituisce informazioni sulle transazioni a livello di database. Per una transazione a esecuzione prolungata, le colonne di particolare interesse includono l'ora del primo record di log (
database_transaction_begin_time
), lo stato corrente della transazione (database_transaction_state
) e il numero di sequenza del log (LSN) delBEGIN
record nel log delle transazioni (database_transaction_begin_lsn
).-
Questa istruzione consente di identificare l'ID utente del proprietario della transazione, in modo da risalire, se lo si desidera, all'origine della transazione per terminarla in modo più appropriato, ovvero tramite il commit invece del rollback.
Terminare una transazione
In alcuni casi è necessario terminare la transazione usando l'istruzione KILL. Usare l'istruzione KILL
con estrema cautela, soprattutto quando vengono eseguiti processi critici che non si vogliono terminare.
CHECKPOINT attesa_riutilizzo_log
Nessun checkpoint si è verificato dopo l'ultimo troncamento del log, oppure l'inizio del log non si è ancora spostato oltre un file di log virtuale (VLF) in tutti i modelli di ripristino.
Questa è una ragione comune per ritardare il troncamento del log. In caso di ritardi, è consigliabile eseguire il comando CHECKPOINT
nel database o esaminare le VLF del log.
USE dbname;
CHECKPOINT;
SELECT * FROM sys.dm_db_log_info(db_id('dbname'));
Replica_di_disponibilità attesa_di_riutilizzo_del_log
Quando le modifiche delle transazioni sulla replica primaria del gruppo di disponibilità Always On non sono ancora state finalizzate sulla replica secondaria, il log delle transazioni della replica primaria non può essere troncato. Questo può causare l'aumento del log, indipendentemente dal fatto che la replica secondaria sia impostata per la modalità di commit sincrono o asincrono. Per informazioni su come risolvere questo tipo di problema, vedere Errore 9002. Il log delle transazioni per il database è pieno a causa di un errore di AVAILABILITY_REPLICA.
Replica, rilevamento delle modifiche o CDC
Le funzionalità come replica, rilevamento modifiche e change data capture (CDC) si basano sul log delle transazioni, quindi se le transazioni o le modifiche non vengono recapitate, è possibile impedire il troncamento del log delle transazioni.
Usare DBCC OPENTRAN, Monitoraggio replica o stored procedure per il rilevamento modifiche e CDC per analizzare e risolvere eventuali problemi con queste funzionalità.
Trovare informazioni sui fattori log_reuse_wait
Per altre informazioni, vedere Fattori che possono posticipare il troncamento del log.
2. Risolvere il problema del disco pieno
In alcune situazioni il volume del disco che ospita il file di log delle transazioni può diventare pieno. È possibile eseguire una delle azioni seguenti per risolvere lo scenario del log pieno risultante da un disco pieno:
Spazio libero su disco
Potrebbe essere possibile liberare spazio sull'unità disco contenente il file del log delle transazioni per il database, eliminando o spostando altri file. L'aumento dello spazio disponibile su disco consente al sistema di recupero di ingrandire automaticamente il file di log.
Spostare il file di log in un altro disco
Se non è possibile liberare spazio su disco sufficiente nell'unità che attualmente contiene il file di log, prendere in considerazione lo spostamento del file in un'altra unità con spazio adeguato.
Importante
È consigliabile non memorizzare mai file di log in file system compressi.
Per informazioni su come modificare il percorso di un file di log, vedere Spostare i file di database .
Aggiungere un file di log a un altro disco
Aggiungere un nuovo file di log al database in un altro disco contenente spazio sufficiente usando ALTER DATABASE <database_name> ADD LOG FILE
. La presenza di più file di log per un singolo database deve essere considerata una condizione temporanea per risolvere un problema di spazio, non una condizione a lungo termine. La maggior parte dei database dovrebbe avere un solo file di log delle transazioni. Continuare a esaminare il motivo per cui il log delle transazioni è pieno e non può essere troncato. Prendere in considerazione l'aggiunta di file di log delle transazioni temporanei aggiuntivi solo come passaggio avanzato per la risoluzione dei problemi.
Per ulteriori informazioni, vedere Aggiungere file di dati o file di log a un database.
Script di utilità per le azioni consigliate
Questi passaggi possono essere parzialmente automatizzati eseguendo il seguente script T-SQL, per identificare i file di log che usano una grande percentuale di spazio su disco e suggerirà le azioni da intraprendere:
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. Modificare il limite di dimensioni del log o abilitare l'aumento automatico
L'errore 9002 può essere generato se le dimensioni del log delle transazioni sono impostate su un limite superiore o se la funzionalità di aumento automatico non è consentita. In questo caso, il problema può essere risolto abilitando l'aumento automatico o aumentando manualmente le dimensioni del log. Usare questo comando T-SQL per trovare tali file di log e seguire le indicazioni fornite:
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;
Aumentare le dimensioni del file di log o abilitare l'aumento automatico
Se nel disco del log è disponibile spazio, è possibile aumentare le dimensioni del file di log. La dimensione massima per i file di log è 2 terabyte per file di log.
Se l'aumento automatico è disabilitato, il database è online ed è disponibile spazio sufficiente sul disco, considerare l’esecuzione di uno dei passaggi seguenti:
Aumentare manualmente le dimensioni del file per produrre un incremento di crescita singolo. Questi sono consigli generali sull'aumento e sulle dimensioni dei log.
Attivare l'aumento automatico usando l'istruzione
ALTER DATABASE
per impostare un incremento di crescita diverso da zero per l'opzioneFILEGROWTH
. Vedere Considerazioni sulle impostazioni di aumento e compattazione automatici in SQL Server.
Nota
In entrambi i casi, se viene raggiunto il limite di dimensioni corrente, aumentare il valore MAXSIZE
.
Contenuto correlato
- ALTER DATABASE (Transact-SQL)
- Gestione delle dimensioni del file di log delle transazioni
- Backup del log delle transazioni (SQL Server)
- sp_add_log_file_recover_suspect_db (Transact-SQL)
- MSSQLSERVER_9002
- Effetto di una struttura del file di log sul tempo di recupero di un database - Microsoft Tech Community