SQL Server Differential vs Log Backup: Which One Restores What, and How the Chain Breaks

A differential holds everything changed since the last full backup. A log backup holds everything since the last log backup. Restore the full, then only the newest differential, then the logs after it. The trap is that any ordinary full backup, taken by anyone, silently becomes the new base for your differentials.

Which Files Do You Actually Need

Mid restore is the wrong moment to work out how these differ, so the short version first.

  • A differential is cumulative. It carries every extent changed since its base full backup, so you restore the base and then only the most recent differential.
  • A log backup is sequential. Each one continues from the last, so you restore them all, in order, from the one taken after whatever data backup you restored.

Which means the restore sequence is: full, newest differential if you have one, then every log backup since. Everything except the last statement takes WITH NORECOVERY.


Read Your Own Chain First

Before any of this matters, look at what you actually have. 3 columns in msdb.dbo.backupset tell you whether your chain is intact. Run it in the database you are restoring, not in master:

SELECT
    bs.database_name,
    backup_type = CASE bs.type
                      WHEN 'D' THEN CASE WHEN bs.is_copy_only = 1
                                         THEN 'Full (COPY_ONLY)' ELSE 'Full' END
                      WHEN 'I' THEN 'Differential'
                      WHEN 'L' THEN 'Log'
                      ELSE bs.type END,
    bs.name,
    bs.backup_start_date,
    bs.checkpoint_lsn,          -- on a full: the value a later differential points back to
    bs.differential_base_lsn,   -- on a differential: which full it actually needs
    bs.begins_log_chain,        -- 1 = a NEW log chain starts here, i.e. an old one ended
    bs.is_copy_only
FROM msdb.dbo.backupset AS bs
WHERE bs.database_name = DB_NAME()
  AND bs.backup_start_date >= DATEADD(DAY, -30, SYSDATETIME())
ORDER BY bs.backup_start_date, bs.backup_set_id;
SSMS results showing a nine step SQL Server backup chain, with differential_base_lsn unchanged after a log backup and after a COPY_ONLY full, then moving to the new value after an ordinary full backup

differential_base_lsn on a differential tells you exactly which full backup it needs. begins_log_chain set to 1 anywhere except your very first log backup means a chain ended and a new one started, and that is a break that already happened. To check every database at once rather than one at a time, Get Backup Chain Integrity runs the same reasoning across the instance.


What Moves the Differential Base, Measured

Microsoft documents that a copy-only full does not affect the base. What it never states in a sentence is whether a log backup does. So rather than assert it, here is the answer read straight out of msdb after running the sequence on a lab instance. These are the rows from the capture above that carry the point:

name                     type  copy_only  checkpoint_lsn     differential_base_lsn
-----------------------  ----  ---------  -----------------  ---------------------
S1_FULL                  D             0  44000000035200001  NULL
S4_DIFF_after_LOG        I             0  44000000059200001  44000000035200001   <- unchanged
S6_DIFF_after_COPYONLY   I             0  44000000076800001  44000000035200001   <- unchanged
S7_FULL_ordinary         D             0  44000000088800001  NULL
S8_DIFF_after_FULL       I             0  44000000100800001  44000000088800001   <- MOVED

Read the differential_base_lsn column against the checkpoint_lsn of S1_FULL. A log backup leaves it pinned. A copy-only full leaves it pinned. Only the ordinary full at step 7 moves it, and the differential immediately after now points somewhere new.

Microsoft“The differential bitmap isn’t updated by a copy-only backup. Therefore, a copy-only backup doesn’t affect subsequent differential backups.”

You can reproduce that table on any test instance in about a minute, and it is worth doing once so the behaviour stops being something you half remember.


What Breaks the Chain

Someone else's full backup
The one that actually catches people. Microsoft defines the base as “the most recent, previous full data backup”, with no qualification about who took it. A consultant testing a restore, a third party agent, a developer grabbing a copy: any ordinary full silently becomes the new base, and tonight’s differential is useless without a file that may be on someone else’s storage.Do this make every out of band full backup COPY_ONLY, without exception. It is the entire reason the option exists.
Switching to SIMPLE and back
This ends the log chain, and switching back does not resume it. Microsoft is precise in the begins_log_chain definition: a chain begins at the first log backup after a database is created or when it is switched from simple back to full. Worse, the switch to FULL “takes effect only after the first data backup”, so there is a real window where the database behaves as SIMPLE and nothing is protected.Do this take a full or a differential immediately after switching back. Either starts the chain, which surprises people who assume only a full will do.
A missing log backup
Less fatal than people fear. It is a ceiling on your recovery point, not a total loss. Microsoft: “If a transaction log backup in this log chain is lost or damaged, you can restore only transaction logs before the missing transaction log.”Do this restore up to the gap and stop. Then work out why one is missing, because the same cause is probably still running.

Rarer Breaks

  • Recovering too early. Omit NORECOVERY on an intermediate restore and the database comes online. You cannot then continue, and Microsoft is explicit that you must restart the whole sequence from the full backup.
  • A read only database that gets rebuilt, restored, or detached and attached. For a read only database the differential base metadata lives in master, not in the database. Microsoft: “The SQL Server Database Engine can’t detect or prevent this problem.” Later differentials are quietly based on the wrong thing.
  • Losing master. Restore it before restoring any differential of a user database, for the same reason.
  • Bulk-logged recovery with bulk operations in the window. The log backup is still valid, but point in time recovery inside it is not available.

The One Habit That Prevents Most of This

🛑A COPY_ONLY backup will not break your chain. An ordinary full backup will. That is the whole rule. Every backup taken outside the schedule uses COPY_ONLY: restore tests, ad hoc copies for a developer, a consultant grabbing a snapshot, the third party agent somebody installed last year. A copy-only full leaves the differential base exactly where it was, and Microsoft’s wording is that differentials “behave as if the copy-only backup doesn’t exist”.

Two edges worth knowing. A copy-only log backup does not truncate the log, which is occasionally what you want and more often a surprise.

And COPY_ONLY with DIFFERENTIAL is not quite the no-op it is usually described as. Microsoft states that “if DIFFERENTIAL and COPY_ONLY are used together, COPY_ONLY is ignored, and a differential backup is created”. On SQL Server 2025 that is true of the backup and not of the metadata: the differential is created and based correctly, but msdb still records is_copy_only = 1 against it. It matters because a good many chain queries filter is_copy_only = 0, correctly, to find the last log backup that actually truncated. Reuse that filter to find the newest differential and you will skip this one.


Frequently Asked Questions

Do I restore every differential, or just one?

Just the most recent. A differential is cumulative, not incremental: each one contains everything changed since the base, not since the previous differential. Restore the full, then the latest differential, then the log backups taken after it.

Does a full backup truncate the log?

No, and this is a persistent myth. Under FULL or BULK_LOGGED, truncation follows a log backup, not a data backup. A full backup actually blocks truncation while it runs, which shows up as ACTIVE_BACKUP_OR_RESTORE in log_reuse_wait_desc. A full backup does include enough of the log to make the restored database consistent, which is probably where the confusion started.

Can I take differentials in SIMPLE recovery?

Yes. SIMPLE blocks log backups, not differentials, and Microsoft’s own SIMPLE model restore example uses one. What you lose is point in time recovery: your best possible recovery point becomes your last full or differential.

Why did my restore fail with a broken LSN chain?

Usually one of 3 things. A log backup is missing from the sequence, someone recovered the database part way through with WITH RECOVERY instead of NORECOVERY, or the differential you are restoring belongs to a different full than the one you restored. The query above answers the third in seconds: match the differential’s differential_base_lsn against the checkpoint_lsn of your fulls.

Is msdb history the same as having the backups?

No, and treating it as such has ended careers. msdb history is deleted by sp_delete_backuphistory, does not exist on a different server, and Microsoft warns that physical_device_name cannot be relied on as a restore path. The history tells you what the chain looked like. Only the files let you use it.


Related


Summary

A differential carries everything since the last full, so you restore only the newest one. Log backups are a sequence, so you restore them all in order. The failure that actually happens is not a corrupt file, it is an ordinary full backup taken by somebody outside the schedule, which silently reparents every differential that follows it. Make out of band backups COPY_ONLY, and read differential_base_lsn before you trust a chain you have not tested.

Comments

Leave a Reply

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