Recently I used RavenDB embedded database in an application. As part of that, had to take care of its backup and restore operations. RavenDB’s official documentation of course covers embedded database backup and restore. I found it, however, bit scattered, not as thorough as the server one’s, and some conventions would better be made explicit. As a result, it took me some time to construct the steps from the documentation.
Besides the references in RavenDB official documentation site, a few walkthrough like article would make user’s life much easier; I hope there will be a lot of them someday. In this post, I have put together a brief overview of backup and restore, how to do that in RavenDB 3.5, and a few related points.
Overview of RavenDB’s Backup and Restore
RavenDB provides two methods for backup: full and incremental. Their meaning is as usual: full backup stores the entire snapshot of a database at some instant, incremental backup, on the other hand, stores the difference between the current snapshot of a database and a previous backup. Incremental backup is naturally faster than full backup, hence preferred for periodic backups.
Backup is an online operation: that is you can start a backup while the database is running and processing requests. Restore, on the other hand, is an offline operation: you cannot perform a restore without stopping the database.
Backup data (both full and incremental) is stored in a location specified while initiating a backup. A backup location can contain only one full backup; any attempt to perform a full backup to a location that already contains another backup fails with error. An incremental bakcup location, on the other hand, keeps accumulating backup data in the same location on each invocation of incremental backup.
During a restore, user specifies both the backup location and the target restore location. The restore location must not contain another database with the same name. If restoration is succeful the database is available at the restore location in the same state as it was during the time of backup.
Backup of an embedded database must be performed with the RavenDB client API; that is the same API—the IDocumentStore
and IDocumentSession
interfaces being part of it—that does other common tasks like creating a database connection, loading and storing data, etc. Restoration of embedded database, however, can be done with both the client API and the Raven.Server.exe program.
Initiating a Backup
Both backup and restore are invoked from an EmbeddableDocumentStore
instance as administrative database commands.
Initiating a backup of an embedded database is exceptionally simple. Initialize an EmbeddableDocumentStore
at the database location, call the StartBackup()
command method with appropritate parameters, the backup location is created if it doesn’t exist, and backup starts asynchronously. The EmbeddableDocumentStore
instance for backup doesn’t need to be dedicated for it; you can use the one that is being used by other operations.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public void Backup(string backupPath)
{
try
{
DocumentStore.DatabaseCommands.
GlobalAdmin.StartBackup(backupPath,
new DatabaseDocument
{
Id = Database
},
false,
Database
);
}
catch (Exception ex)
{
Logger.Error(ex);
throw;
}
}
Parameters to the StartBackup
method are obvious except the databaseDocument
. The databaseDocument
parameter takes some advanced settings of the database being backed up: like specifying the Id
in it lets you omit the database name during restore; Raven assumes that from the backup directory.
As mentioned before, backup is an asynchronous operation. The StartBackup
method returns an Operation
object that helps tracking completion of backup operation with methods WaitForCompletion
and its asynchronous counterpart WaitForCompletionAsync
.
Incremental Backup
Before initiating an incremental backup, check the following configurations of your storage engine (RavenDB supports two storage engines: Esent and Voron; the default is Esent; you can change it to Voron from configuration.) These configurations are mandatory, incremental backup fails if they are not set appropriately.
- Esent. Turn off (it is turned on by default) Esent’s circular logging during incremental backups. You can do it by setting Raven/Esent/CircularLog to
false
. - Voron. Set Raven/Voron/AllowIncrementalBackups to
true
.
There is no difference between starting a full backup and an incremental one except the incremental
parameter; to start an incremental backup, just set the incremental
boolean parameter to the StartBackup
method to true
.
Incremental backup expects a previous full backup of the database in the backup location. The very first incremental backup of a database is treated as a full backup by default; no need to set the incremental
parameter to false
for first backup. All subsequent incremental backups after the first one are stored as diffs—as timestamped subdirectories inside the backup location.
Restoring a Database
As mentioned in the overview section, restoration can be done with both the client API and the Raven.Server.exe program. Here I will cover only the client API. The Raven.Server.exe method is very similar to the client one (e.g. the same constraints, same parameters are required, etc.)
Like backup, initiating a restore operation from client API is straightforward. Create and initialize a temporary EmbeddableDocumentStore
for restore, call StartRestore
on it, the restore location is created if it doesn’t exist, and restore continues asynchronously.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public void Restore(string backupPath, string databaseLocation, string databaseName)
{
using (var documentStore = new EmbeddableDocumentStore())
{
documentStore.Initialize();
documentStore.DatabaseCommands.
GlobalAdmin.StartRestore(new DatabaseRestoreRequest
{
BackupLocation = backupPath,
DatabaseLocation = databaseLocation,
DatabaseName = databaseName
});
}
}
Use of the parameter DatabaseRestoreRequest
passed to StartRestore
should be obvious. Like backup, restore is also an asynchronous operation. Like StartBackup
, StartRestore
also returns an Operation
object with similar facilities for tracking the operation progress.
If restore is successful, the restored database should be available at the location (DatabaseLocation
) specified during restore.
EmbeddableDocumentStore for Restore
Do not set the document store’s DefaultDatabase
property to the name of the database to be restored. Doing so essentially creates a database with that name. Hence restore detects that another database with the same name is online and restoration fails.
Backup Location After a Restore from an Incremental Backup
Once you have restored from an incremental backup directory, you can no longer perform incremental backups to that same directory; Raven throws an InvalidOperationException
with message like “… Database missed a previous full bakcup before incremental backup.”
References
- Administration : Backup and Restore. Backup and restore administration guideline.
- Commands : How to start backup or restore operations? Backup and Resore commands reference.
- RavenDB Configurations Summary. Lists all RavenDB configurations.