SQL Server Snapshots

28 Apr 2020

sql

Summary of Paul Mcilreavy blog post Keep your dev loop as short as possible with Sql Server Snapshots

Azure Data Studio Extension automating that process

https://github.com/ecirpnaes/DbSnapshotCreator

To take snapshot

USE [Master];
GO
CREATE DATABASE [snapshot_name] ON
(
    NAME = 'database_logical_data_file_name',
    FILENAME = 'C:\Users\mateu\snapshot_name.ss'
)
AS SNAPSHOT OF [database_name];
GO

The database_data_file_name should match the logical file name of the .mdf database file

To restore from snapshot

USE [Master];
GO
ALTER DATABASE [database_name] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
RESTORE DATABASE [database_name] FROM DATABASE_SNAPSHOT = 'snapshot_name';
ALTER DATABASE [database_name] SET MULTI_USER;
GO

There can only be one snapshot of the database present in the sql server. If multiple snapshots of the same database are found, the restore operation will fail with Database cannot be reverted. Either the primary or the snapshot names are improperly specified, all other snapshots have not been dropped, or there are missing files. Fortunately, it is safe to delete older snapshot and afterwards restore from the newer one.

More details in this stack overflow answer

  1. You have multiple snapshots defined, try refreshing the snapshots folder in ssms or run select * from sys.databases where source_database_id IS NOT NULL to see if you have more snapshots. Because snapshots are 'copy on write', you cannot restore if you have multiple snapshots for a single database.

  2. You are not specifying correctly the logical name of the snapshot. Run select * from sys.databases where source_database_id IS NOT NULL to check the the logical name of the snapshot. Then rerun the restore using that name.

  3. Your snapshot file is not linked anymore with the snapshot (snapshot got somehow corrupted). The statement below queries the pages in the snapshot file. Run it and see if you have any errors. select db_name(database_id) [<database name>], database_id, count(*) from sys.dm_os_buffer_descriptors where database_id= (select top 1 database_id from sys.databases where source_database_id IS NOT NULL) group by database_id


Disclaimer: The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.