Home / Databases / SQL Server

DatabasesTroubleshootingAdvanced

SQL Server log shipping out of sync: restore job failing, LSN gaps and how to re-seed the secondary

The log shipping secondary falls behind and alerts fire. Find whether backup, copy or restore is failing, fix LSN chain breaks caused by extra log backups, and re-initialise the secondary only when you must.

Deepak Bhardwaj5 min read

Applies toSQL Server 2016-2022 transaction log shipping (primary, secondary, optional monitor server), SQL Server Agent

Symptoms

  • Alert 14421: "The log shipping secondary database ... has restore threshold of N minutes and is out of sync."
  • Alert 14420: "The log shipping primary database ... has backup threshold of N minutes and has not performed a backup log operation."
  • The LSRestore_<primary>_<db> job fails repeatedly, or succeeds but restores nothing.

Log shipping is three Agent jobs: backup (primary), copy (secondary), restore (secondary). Find which one broke.

Step 1: Status overview

On the monitor server (or primary/secondary if no monitor):

EXEC master.dbo.sp_help_log_shipping_monitor;

On the secondary, details per database:

SELECT secondary_database, last_copied_file, last_copied_date,
       last_restored_file, last_restored_date, last_restored_latency
FROM   msdb.dbo.log_shipping_monitor_secondary;

And the job history messages, which hold the real error:

SELECT TOP (20) j.name, h.run_date, h.run_time, h.run_status, h.message
FROM   msdb.dbo.sysjobhistory h
JOIN   msdb.dbo.sysjobs j ON j.job_id = h.job_id
WHERE  j.name LIKE 'LS%'
ORDER  BY h.instance_id DESC;

Log shipping's own detailed log:

SELECT TOP (50) log_time, message
FROM   msdb.dbo.log_shipping_monitor_error_detail
ORDER  BY log_time DESC;

Step 2: Backup job failing (primary)

Message Cause Fix
Access denied to backup share Agent/SQL service account lost rights on the share Fix share + NTFS permissions
Disk full on backup share Retention cleanup not keeping up Free space; check backup_retention_period
BACKUP LOG cannot be performed because there is no current database backup Database switched to SIMPLE and back, or was never fully backed up Take a full backup; investigate the recovery model change

Step 3: Copy job failing (secondary)

Usually permissions or network: the secondary's Agent service account must read the primary's backup share, and write the local copy folder.

# Run as the secondary's SQL Agent service account (or check with its credentials)
Test-Path \\sqlprimary\LSBackup\SalesDB
Get-ChildItem \\sqlprimary\LSBackup\SalesDB | Sort-Object LastWriteTime -Descending | Select -First 5

Step 4: Restore job failing: the LSN chain is broken

The most common restore error:

The log in this backup set begins at LSN 41000000045600001, which is too recent to apply to the database.
An earlier log backup that includes LSN 41000000044800001 can be restored.

Something took a log backup outside log shipping (a backup tool, a maintenance plan, a DBA running BACKUP LOG to free space). That backup went somewhere else, so the secondary is missing a piece of the chain.

Find it on the primary:

SELECT bs.backup_start_date, bs.first_lsn, bs.last_lsn, bmf.physical_device_name, bs.user_name
FROM   msdb.dbo.backupset bs
JOIN   msdb.dbo.backupmediafamily bmf ON bmf.media_set_id = bs.media_set_id
WHERE  bs.database_name = 'SalesDB' AND bs.type = 'L'
  AND  bs.backup_start_date > DATEADD(day, -2, GETDATE())
ORDER  BY bs.backup_start_date;

Look for a file whose path isn't the log shipping folder, with an LSN range covering the gap.

Fix: restore the missing file manually, then let the job continue

Copy that file to the secondary and restore it:

RESTORE LOG SalesDB
FROM DISK = N'E:\Recovery\SalesDB_extra_log.trn'
WITH NORECOVERY;      -- or STANDBY = N'E:\LSStandby\SalesDB.tuf' if the secondary is readable

Then run the restore job; it picks up from the next file.

Tip

If the out-of-band backup was COPY_ONLY, it doesn't break the chain at all, and the cause is something else. Ask backup tool owners to use COPY_ONLY (or exclude log-shipped databases from their log backups).

Other restore errors

Message Cause Fix
Exclusive access could not be obtained because the database is in use Users connected to a STANDBY secondary Tick "Disconnect users" in the restore settings, or schedule restores outside reporting hours
Restore job "succeeds" but last_restored_file is old Files are skipped because they're older than the last restored LSN, or copy isn't bringing new files Check copy job; check file timestamps
The file ... cannot be found Retention deleted files before they were restored (secondary was down) Restore from another copy of the files, or re-seed
Out of disk on data/log drives File growth on primary not matched on secondary Add space; same drive layout

Step 5: When you must re-seed

If the missing log backup is gone for good, or the secondary was recovered (WITH RECOVERY) by mistake, the chain can't be repaired. Options:

Differential bridge (faster): if a full backup taken before the gap is already restored on the secondary, a differential from the primary taken now can bridge it:

-- Primary
BACKUP DATABASE SalesDB TO DISK = N'\\sqlprimary\Seed\SalesDB_diff.bak' WITH DIFFERENTIAL, COMPRESSION;

-- Secondary
RESTORE DATABASE SalesDB FROM DISK = N'\\sqlprimary\Seed\SalesDB_diff.bak' WITH NORECOVERY;

This works only if the secondary's last restored point is based on the same full backup the differential is based on (same differential base). Otherwise:

Full re-seed:

-- Primary
BACKUP DATABASE SalesDB TO DISK = N'\\sqlprimary\Seed\SalesDB_full.bak' WITH COMPRESSION, CHECKSUM;

-- Secondary
RESTORE DATABASE SalesDB FROM DISK = N'\\sqlprimary\Seed\SalesDB_full.bak'
WITH NORECOVERY, REPLACE,
     MOVE 'SalesDB'     TO N'F:\Data\SalesDB.mdf',
     MOVE 'SalesDB_log' TO N'G:\Log\SalesDB_log.ldf';

Keep the log shipping jobs disabled while the full restore runs, then enable them; the next log backups after the full apply normally.

Warning

RESTORE ... WITH REPLACE overwrites the secondary database. Double-check you are connected to the secondary server before running it.

Step 6: Check thresholds and alert job

SELECT secondary_database, restore_threshold, threshold_alert_enabled
FROM   msdb.dbo.log_shipping_monitor_secondary;

Make sure the LSAlert_<server> job is enabled and SQL Agent alerts for 14420/14421 notify an operator.

Prevent it next time

  • Exclude log-shipped databases from any other log backup process, or force COPY_ONLY.
  • Keep backup file retention longer than your longest expected secondary outage.
  • Use a monitor server and route alerts 14420/14421 to on-call, not just the Agent log.
  • Practise a DR failover and a re-seed once a year so the steps are familiar.