.3. Transaction log backup
A
fundamental component of database management systems like SQL Server is
the transaction log. Each database has its own transaction log, which
SQL Server uses for several purposes, including the following:
The log records each database transaction, as well as the individual database modifications made within each transaction.
If
a transaction is canceled before it completes, either at the request of
an application or due to a system error, the transaction log is used to
undo, or roll back, the transaction's modifications.
A
transaction log is used during a database restore to roll forward
completed transactions and roll back incomplete ones. This process also
takes place for each database when SQL Server starts up.
The transaction log plays a key role in log shipping and database mirroring.
Regular transaction log backups, as shown here, are crucial in retaining the ability to recover a database to a point in time:
-- Transaction Log Backup to Disk
BACKUP LOG [AdventureWorks2008]
TO DISK = N'G:\SQL Backup\AdventureWorks-Trn.bak'
WITH INIT
As you can see in figure 3, each transaction log backup forms part of what's called a log chain.
The head of a log chain is a full database backup, performed after the
database is first created, or when the database's recovery model,
discussed shortly, is changed. After this, each transaction log backup
forms a part of the chain. To restore a database to a point in time, an
unbroken chain of transaction logs is required, from a full backup to
the required point of recovery.
Consider figure 3.
Starting at point 1, we perform a full database backup, after which
differential and transaction log backups occur. Each of the backups
serves as part of the chain. When restoring to a point in time, an
unbroken sequence of log backups is required. For example, if we lost
backup 4, we wouldn't be able to restore past the end of backup 3 at 6
a.m. Tuesday. Attempting to restore the transaction log from log backup
5 would result in an error message similar to that shown in figure 4.
In
addition to protecting against potential data loss, regular log backups
limit the growth of the log file. With each transaction log backup,
certain log records, discussed in more detail shortly, are removed,
freeing up space for new log entries. As covered earlier, the
transaction log in a database in full recovery mode will continuing
growing indefinitely until a transaction log backup occurs.
The
frequency of transaction log backups is an important consideration. The
two main determining factors are the rate of database change and the
sensitivity to data loss.
Transaction log backup frequency
Frequent
transaction log backups reduce the exposure to data loss. If the
transaction log disk is completely destroyed, then all changes since
the last log backup will be lost. Assuming a transaction log backup was
performed 15 minutes before the disk destruction, the maximum data loss
would be 15 minutes (assuming the log backup file isn't contained on
the backup disk!). In contrast, if transaction log backups are only
performed once a day (or longer), the potential for data loss is large,
particularly for databases with a high rate of change.
The
more frequent the log backups, the more restores will be required in a
recovery situation. In order to recover up to a given point, we need to
restore each transaction log backup between the last full (or
differential) backup and the required recovery point. If transaction
log backups were taken every minute, and the last full or differential
backup was 24 hours ago, there would be 1,440 transaction log backups
to restore! Clearly, we need to get the balance right between potential
data loss and the complexity of the restore. Again, the determining
factors are the rate of database change and the maximum allowed data
loss, usually defined in a service level agreement.
In
a moment we'll run through a point-in-time restore, which will
illustrate the three backup types working together. Before we do that,
we need to cover tail log backups.
Tail log backups
When restoring a database that's currently attached to a server instance, SQL Server will generate an error unless the tail
of the transaction log is first backed up. The tail refers to the
section of log that hasn't been backed up yet—that is, new transactions
since the last log backup.
A tail log backup is performed using the WITH NORECOVERY
option, which immediately places the database in the restoring mode,
guaranteeing that the database won't change after the tail log backup
and thus ensuring that all changes are captured in the backup.
Backing up the tail of a transaction log using the WITH NO_TRUNCATE option should be limited to situations in which the database is damaged and inaccessible. The COPY_ONLY option, covered shortly, should be used in its place.
|
When
restoring up to the point of failure, the tail log backup represents
the very last transaction log backup, with all restores preceding it
performed using the WITH NORECOVERY option. The tail log is then restored using the WITH RECOVERY option to recover the database up to the point of failure, or a time before failure using the STOPAT command.
So let's put all this together with an example. In listing 1,
we first back up the tail of the log before restoring the database to a
point in time. We begin with restoring the full and differential
backups using the WITH NORECOVERY option, and then roll forward the transaction logs to a required point in time.
Example 1. Recovering a database to a point in time
-- Backup the tail of the transaction log BACKUP LOG [AdventureWorks2008] TO DISK = N'G:\SQL Backup\AdventureWorks-Tail.bak' WITH INIT, NORECOVERY
-- Restore the full backup RESTORE DATABASE [AdventureWorks2008] FROM DISK = N'G:\SQL Backup\AdventureWorks.bak' WITH NORECOVERY GO
-- Restore the differential backup RESTORE DATABASE [AdventureWorks2008] FROM DISK = N'G:\SQL Backup\AdventureWorks-Diff.bak' WITH NORECOVERY GO
-- Restore the transaction logs RESTORE LOG [AdventureWorks2008] FROM DISK = N'G:\SQL Backup\AdventureWorks-Trn.bak' WITH NORECOVERY GO
-- Restore the final tail backup, stopping at 11.05AM RESTORE LOG [AdventureWorks2008] FROM DISK = N'G:\SQL Backup\AdventureWorks-Tail.bak' WITH RECOVERY, STOPAT = 'June 24, 2008 11:05 AM' GO
|
As we covered earlier, the NO_TRUNCATE
option of a transaction log backup, used to perform a backup without
removing log entries, should be limited to situations in which the
database is damaged and inaccessible. Otherwise, use the COPY_ONLY option.
4. COPY_ONLY backups
We defined a log chain as the sequence of transaction log backups from a given base.
The base for a transaction log chain, as with differential backups, is
a full backup. In other words, before restoring a transaction log or
differential backup, we first restore a full backup that preceded the
log or differential backup.
Take the example presented earlier in figure 3,
where we perform a full backup on Sunday night, nightly differential
backups, and six hourly transaction log backups. In a similar manner to
the code in listing 1,
to recover to 6 p.m. on Tuesday, we'd recover Sunday's full backup,
followed by Tuesday's differential and the three transaction log
backups leading up to 6 p.m.
Now let's
assume that a developer, on Monday morning, made an additional full
backup, and moved the backup file to their workstation. The
differential restore from Tuesday would now fail. Why? A differential
backup uses a Differential Changed Map (DCM) to track which extents
have changed since the last full backup. The DCM in the differential
backup from Tuesday now relates to the full backup made by the
developer on Monday morning. In our restore code, we're not using the
full backup from Monday—hence the failure.
Now,
there are a few ways around this problem. First, we have an unbroken
transaction log backup sequence, so we can always restore the full
backup, followed by all of the log
backups since Sunday. Second, we can track down the developer and ask
him for the full backup and hope that he hasn't deleted it!
-- Perform a COPY ONLY Transaction Log Backup
BACKUP LOG [AdventureWorks2008]
TO DISK = N'G:\SQL Backup\AdventureWorks-Trn_copy.bak'
WITH COPY_ONLY