SQL Server Log Won’t Truncate: What log_reuse_wait_desc Is Telling You

SQL Server already knows why your log will not truncate, and it keeps the answer in one column. Read log_reuse_wait_desc in sys.databases before you shrink anything or change a recovery model. Three of the thirteen values account for almost every real case.

The Log Will Not Truncate and the Backups Are Running

A transaction log is filling a disk, or it has stopped shrinking, and the backup job says it succeeded. Before touching anything, ask SQL Server why it will not reuse the space. It already knows, and it will tell you in one column.

SELECT
    name,
    recovery_model_desc,
    log_reuse_wait_desc
FROM sys.databases
WHERE state_desc = 'ONLINE'
ORDER BY CASE WHEN log_reuse_wait_desc = 'NOTHING' THEN 1 ELSE 0 END, name;
SSMS results showing log_reuse_wait_desc per database, six on LOG_BACKUP and six on NOTHING

That column is log_reuse_wait_desc. It is the single most useful thing in sys.databases during a log incident, because it turns “the log is full” into a specific, named reason with a specific fix. Everything else in this post is what the values mean.


Reading It On A Real Instance

Output from the lab, using Get-LogReuseWaits, which adds recovery model, log size and last log backup beside the reason:

database_name    recovery_model  log_reuse_wait  log_size_mb  last_log_backup          status
---------------  --------------  --------------  -----------  -----------------------  --------------------------
DBAMonitor       FULL            LOG_BACKUP            584.0  NULL                     ACTION: take a log backup
DemoDatabase     FULL            LOG_BACKUP            512.0  2026-07-28 08:00:02.000  ACTION: take a log backup
migdb_37A45A06   FULL            LOG_BACKUP            160.0  2026-07-28 08:00:02.000  ACTION: take a log backup
migdb_7049216A   FULL            LOG_BACKUP            160.0  2026-07-28 08:00:02.000  ACTION: take a log backup
migdb_751FB44B   FULL            LOG_BACKUP            160.0  2026-07-28 08:00:02.000  ACTION: take a log backup
migdb_B8A15B78   FULL            LOG_BACKUP            160.0  2026-07-28 08:00:03.000  ACTION: take a log backup
migdb_A9250FB6   FULL            NOTHING               160.0  2026-07-28 08:00:02.000  OK
zzidx_db         FULL            NOTHING                72.0  NULL                     OK

Six databases in FULL recovery waiting on a log backup, and a last log backup 35 days old. That is not six problems. It is one missing job, and the column found it in a second.


Every Value, And What To Do About It

Microsoft documents thirteen values. Three of them account for almost every real incident, so those get the detail:

LOG_BACKUP
This means the job is missing, not that the job failed. The database is in FULL or BULK_LOGGED and the log cannot reuse space until a log backup runs. If the log has never been backed up, Microsoft is specific that you need two backups, because the first only establishes the point the second can truncate to.Do this take a log backup. Then ask whether a log backup job exists for this database at all, because a database quietly switched to FULL with no schedule is how this usually happens.
ACTIVE_TRANSACTION
This is a person or an application, not a setting. Something is holding a transaction open. This is the one that ambushes people, because it stops truncation even in SIMPLE recovery, where most of us stop thinking about the log at all.Do this run DBCC OPENTRAN, then sys.dm_tran_database_transactions. Find the session and deal with the transaction. Killing it is a decision, not a reflex.
AVAILABILITY_REPLICA
This means look at the other server. A secondary has not hardened the log yet. Microsoft is explicit that this happens in both synchronous and asynchronous commit mode, which catches people who assume an async replica cannot hold the primary back.Do this look at the other server. Nothing you do on the primary releases that space while a secondary is disconnected or suspended.

The Rarer Values

You are unlikely to meet these, and most clear on their own. They are here so that a value you have never seen does not turn into an investigation.

  • NOTHING and CHECKPOINT, healthy. If the file is still enormous, that is a sizing question, not a truncation one.
  • ACTIVE_BACKUP_OR_RESTORE, a data backup or restore is running. Self-clearing, and only a problem when a full backup takes hours.
  • REPLICATION, transactions not yet delivered to the distributor. Change data capture counts here too. Check the Log Reader Agent is alive, because a dead one grows the log without limit.
  • DATABASE_MIRRORING, the mirror is paused or a long way behind. Increasingly rare, since mirroring is deprecated.
  • DATABASE_SNAPSHOT_CREATION, a snapshot is being created. Worth knowing that DBCC CHECKDB builds an internal one, so this can appear during a routine integrity check.
  • LOG_SCAN, something is reading the log. Routine and normally brief.
  • OLDEST_PAGE, indirect checkpoints are on and the oldest dirty page predates the checkpoint LSN. More visible than it used to be, because indirect checkpoint is the default for databases created on SQL Server 2016 and later.
  • XTP_CHECKPOINT, an In-Memory OLTP checkpoint is needed. Only relevant with a memory-optimized filegroup, where Microsoft says to expect this or CHECKPOINT as normal.
  • SLOG_SCAN, Accelerated Database Recovery is scanning its secondary log stream. SQL Server 2019 and later, and the value the documentation covers worst, see below.

Microsoft’s Own Two Pages Disagree

Worth knowing before you go looking things up mid-incident, because it will waste your time otherwise. The sys.databases reference lists thirteen values and points you at the transaction log page for “more detailed explanations”. That second page does not cover SLOG_SCAN at all, and it lists a value called OTHER_TRANSIENT that the first page does not.

So the page with the fullest explanations is missing the newest value, and the two pages disagree about a string. Neither is wrong exactly, they were updated at different times. If you land on the transaction log page and cannot find your value, that is why.


Frequently Asked Questions

My log is still huge after I fixed the wait. Why?

Because truncation and shrinking are different things. Truncation frees space inside the file for reuse. It never makes the file smaller on disk. Microsoft puts it plainly: “Shrinking a log file alone can’t solve the problem of a full log file. Instead, you must discover why the log file is full and can’t be truncated.” Fix the reason first, then decide whether the file is genuinely the wrong size.

I took a log backup and it still says LOG_BACKUP.

If that log had never been backed up before, that is expected. Microsoft: “If the log has never been backed up, you must create two log backups to permit the Database Engine to truncate the log to the point of the last backup.” Take a second one. If it persists past that, re-run the query, because the reason has probably changed to something else.

Can this bite me in SIMPLE recovery?

Yes, and this is the most common misunderstanding on the topic. SIMPLE means you cannot take log backups, so LOG_BACKUP will never appear. It does not mean the log cannot fill. ACTIVE_TRANSACTION stops truncation under every recovery model, so one forgotten open transaction will grow a SIMPLE database’s log until the disk does.

Why does my value not appear in Microsoft’s list?

Ids 10, 11 and 12 are documented only as “For internal use only” with no published description, and they are expected to be rare and short-lived. If you catch one, re-query rather than investigate. Anything else is worth reporting, because the documented set is small and stable.

Is there an official query for this?

Not a short one. The sys.databases reference page has three examples and none of them touch this column. What Microsoft does publish is a roughly 150 line diagnostic script, and it lives on the error 9002 troubleshooting page, not on the catalog view page. The three-column query above is the version you can actually remember at 2am.


Related


Summary

When a log will not truncate, SQL Server already knows why and stores the answer in log_reuse_wait_desc. Read that column before you shrink anything, change a recovery model, or add a file. Three values cover almost every case: a missing log backup, an open transaction, or a secondary replica that has not caught up. The rest are mostly routine and clear on their own.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *