In this final part of our series on SQL Server database snapshots, I’m going to talk about what, I think, is the most forgotten feature/use of snapshots: data recovery. If you (or ‘a friend’) makes a mistake and deletes data you shouldn’t have, or perhaps accidentally drops a table, if you have a snapshot, you can restore that lost data. Now, before I go any further, I am in no way, shape, or form suggesting that you use database snapshots as your backup/restore solution. Let me reiterate that: DO NOT RELY ON SNAPSHOTS FOR YOUR BACKUP/RESTORE SOLUTION! Got it? Excellent! Now then, where was I?
Restoring from snapshots comes in especially handy in testing scenarios. You’ve got this mammoth database and a developer wants you to take a backup so he can test some data changes and then have you restore the database to its prior state afterwards. Depending on the size of the database and the speed of your disk subsystem, this entire process could take hours. Who’s got that kind of time? A faster solution would be to create a snapshot of the database prior to the testing, and just restore from that afterwards. Why is this faster? Because a) you’re not writing out all of the data when you create the snapshot like you would with a backup and b) you’re not writing back all the data when you restore from a snapshot like you would if you restored from a backup. See a pattern here? When you recover from a snapshot you only write back the data that was changed since the snapshot was taken.
Let’s look at an example.
/* create the snapshot */ USE master; GO CREATE DATABASE AW_Snap1 ON ( NAME = 'AdventureWorks_Data', FILENAME = 'D:Program FilesMicrosoft SQL ServerMSSQL10.D1DB08MSMSSQLDATAAW_Snap1.ss') AS SNAPSHOT OF Adventureworks; GO /* Query the database and snapshot */ SELECT * from AW_Snap1.Sales.SalesOrderDetail where SalesOrderID = 57049; SELECT * from AdventureWorks.Sales.SalesOrderDetail where SalesOrderID = 57049; GO
For the sake of drama, let’s imagine “someone” dropped a table in the database.
/* oops! someone dropped the table! */ DROP TABLE AdventureWorks.Sales.SalesOrderDetail; GO SELECT * from AW_Snap1.Sales.SalesOrderDetail where SalesOrderID = 57049; SELECT * from AdventureWorks.Sales.SalesOrderDetail where SalesOrderID = 57049; GO
DON’T PANIC! Just restore from the snapshot.
/* no problem, restore from the snapshot */ USE master; GO RESTORE DATABASE AdventureWorks FROM DATABASE_SNAPSHOT = 'AW_Snap1'; GO /* table is back */ SELECT * from AW_Snap1.Sales.SalesOrderDetail where SalesOrderID = 57049; SELECT * from AdventureWorks.Sales.SalesOrderDetail where SalesOrderID = 57049; GO
Pretty cool, huh?
As with most things in life, there are some restrictions and considerations to keep in mind when restoring from a snapshot. For one thing, the snapshot you’re restoring from can be the only current snapshot on the database, so drop all the other ones first. Also, you can’t do a point in time recovery using snapshots (well, unless that point in time is the moment that snapshot was created). On the same point, all data changes made since the snapshot was created will be lost. Snapshot restores don’t fix problems like media failure, and they can’t restore over databases with compressed or read-only filegroups. Restoring from a snapshot breaks the log backup chain, so always take a full backup after restoring from a snapshot.
I hope this series has helped introduce you to the possibilities for using database snapshots in your own environment. And if you have any questions, feel free to leave a comment.