WITH MOVE costs disk space and destroys nothing, which means you find out the backup is good before the existing database is gone.This is a safety check, not a corruption. There is a database called Sales on this instance, your backup file also contains a database called Sales, and SQL Server can tell they are not the same database. It is refusing to overwrite one with the other until you say that is what you meant.
Names match. Lineage does not. A database restored from a different server, or dropped and recreated, carries a different family GUID even with an identical name.
Read the File Before You Decide
RESTORE HEADERONLY FROM DISK = N'D:\Backups\Sales.bak';
That reads the backup without touching anything, and the columns that matter are DatabaseName, ServerName, BackupStartDate, RecoveryModel and BackupType. Two questions get answered at once: is this the file you thought it was, and is it from the server you thought.
Then compare against what is on the instance:
SELECT d.name,
d.recovery_model_desc,
d.create_date,
(SELECT MAX(b.backup_finish_date)
FROM msdb.dbo.backupset AS b
WHERE b.database_name = d.name) AS last_backup
FROM sys.databases AS d
WHERE d.name = N'Sales';
If create_date on the instance is newer than the backup, someone has recreated the database since that file was taken, which is exactly the situation the check exists to catch.
The Three Ways Forward
| You want to | Do this | Cost |
|---|---|---|
| Overwrite the existing database on purpose | WITH REPLACE | Waives two safety checks, see below |
| Keep the existing one and restore alongside | New name plus WITH MOVE | Disk space for a second copy |
| Replace it cleanly | DROP DATABASE first, then restore | The existing database is gone before you know the restore works |
The middle option is the one to prefer on a production instance, because nothing is destroyed until you have proved the restore is good.
RESTORE DATABASE SalesRestore
FROM DISK = N'D:\Backups\Sales.bak'
WITH MOVE 'Sales' TO N'E:\Data\SalesRestore.mdf',
MOVE 'Sales_log' TO N'F:\Log\SalesRestore_ldf.ldf',
RECOVERY, STATS = 5;
Get the logical names from the file rather than guessing them:
RESTORE FILELISTONLY FROM DISK = N'D:\Backups\Sales.bak';
What WITH REPLACE Actually Waives
This is the part worth knowing before you type it, because WITH REPLACE is usually described as “force it” and that undersells the risk.
RESTORE DATABASE Sales
FROM DISK = N'D:\Backups\Sales.bak'
WITH REPLACE, RECOVERY;
It waives three checks, not one:
- the database-identity check that produced 3154
- the check that the tail of the existing log has been backed up
- the check that the files it is about to overwrite on disk belong to this database and are not in use by another one
The second one is the dangerous half. Any committed transaction written to the existing database since its last log backup is destroyed with no further warning. On a FULL recovery database that is real, committed, customer-visible work.
So the honest sequence, when overwriting is genuinely what you want:
BACKUP LOG Sales TO DISK = N'D:\Backups\Sales_tail.trn' WITH NORECOVERY;
Then restore with REPLACE. If the tail backup fails because the data files are already gone, that is fine, and it is also the moment to be certain about what you are overwriting.
Microsoft’s reference covers the REPLACE option impact in RESTORE Statements in full, and it lists all three overridden checks.
Common Questions
Is WITH REPLACE safe?
How do I see what is really in the backup file?
RESTORE HEADERONLY reads it without touching anything, and RESTORE FILELISTONLY gives you the logical file names for WITH MOVE. Both answer “is this the file I think it is” before you commit to anything.The names match, so why does SQL Server think they are different databases?
Can I get at the data without touching the database that is already there?
WITH MOVE for each logical file, as in the example above. It costs disk space for a second copy and destroys nothing, so you find out whether the backup is good before deciding what to do with the existing database.Related Scripts
- Restore From a Newer SQL Server Version (Error 3169), the sibling mismatch error, for when the backup set is the wrong one rather than the wrong version
- The Log in This Backup Set Is Too Recent or Too Early to Apply (Errors 4305, 4326 and 3159), the sibling error when the chain itself, not the database identity, is the problem
- Generate Restore With Move Script, writes the restore-alongside statement, new name and a MOVE for every file, from the backup header, so the safe option above needs no typed paths
- Get Backup Chain Integrity, find the gaps before you need them
- Get Last Restore History, what was restored onto this instance, and when
- Cannot Recover the Master Database (Error 3417), the same closing-message shape when the instance will not start
- Backup Failed or the Restore Is Stuck, every other restore message, sorted by which one you are holding
- Database Cannot Be Opened, Mid-Restore, the state a half-finished restore leaves behind
Leave a Reply