Tutorial: Back up and restore a single database in a cluster

This tutorial provides a detailed example of how to back up and restore a database, in this example version 3.5, in a running (already upgraded/migrated) 4.x cluster.

The following example assumes that your database has users and roles associated with it and describes how to back it up, migrate it into a standalone instance, and then restore it in a running cluster. For more information on how to set up a cluster, see Operations Manual → Set up a local cluster.

In a Neo4j DBMS, every database is backed up individually. Therefore, it is very important to plan your backup strategy for each of them. For more detailed information on how to design an appropriate backup strategy for your setup, see Operations Manual 3.5 → Backup.

Prepare to back up the database

Before you perform the backup, it is good to take a note of the data and metadata of the database that you want to restore. You can use this information later to verify that the restore is successful and to recreate the database users and roles. In this example, the database uses the Movie Graph dataset from the Neo4j Browser → Favorites → Example Graphs.

  1. In the 3.5 Neo4j instance, where the database is running, navigate to the /bin folder and log in to the Cypher® Shell command-line console with your credentials. For more information about the Cypher Shell command-line interface (CLI) and how to use it, see Operations Manual → Cypher Shell.

    ./cypher-shell -u neo4j -p <password>
    Connected to Neo4j at neo4j://localhost:7687 as user neo4j.
    Type :help for a list of available commands or :exit to exit the shell.
    Note that Cypher queries must end with a semicolon.
  2. Run a query to count the number of nodes in the database.

    MATCH (n) RETURN count(n) AS countNode;
    +-----------+
    | countNode |
    +-----------+
    | 171       |
    +-----------+
    
    1 row available after 22 ms, consumed after another 1 ms
  3. Run a query to count the number of relationships.

    MATCH (n)-[r]->() RETURN count(r) AS countRelationships;
    +--------------------+
    | countRelationships |
    +--------------------+
    | 253                |
    +--------------------+
    
    1 row available after 29 ms, consumed after another 0 ms
  4. Run the following two queries to see if there is a schema defined.

    CALL db.constraints()
    0 rows available after 2 ms, consumed after another 0 ms

    The result shows that there are no constraints defined.

    CALL db.indexes;
    +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | description              | indexName | tokenNames | properties | state    | type                  | progress | provider                              | id | failureMessage |
    +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
    | "INDEX ON :Movie(title)" | "index_1" | ["Movie"]  | ["title"]  | "ONLINE" | "node_label_property" | 100.0    | {version: "1.0", key: "native-btree"} | 1  | ""             |
    +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------+

    The result shows that there is one index defined on the property title of the :Movie node.

  5. Run a query to list all users associated with this database and their roles.

    CALL dbms.security.listUsers;
    +-----------------------------------------+
    | username | roles                | flags |
    +-----------------------------------------+
    | "user1"  | ["editor", "reader"] | []    |
    | "neo4j"  | ["admin"]            | []    |
    +-----------------------------------------+
    
    2 rows available after 2 ms, consumed after another 0 ms

    The result shows two users - the default neo4j user, which has admin privileges, and a custom user user1, which has the combined privileges of the built-in roles editor and reader.

  6. Exit the Cypher Shell command-line console.

    :exit;
    
    Bye!

Back up the database

Now you are ready to back up the database.

Navigate to the /bin folder, and run the following command to back up the database in your targeted folder. If the folder where you want to place your backup does not exist, you have to create it. In this example, it is called /tmp/3.5.24.

./neo4j-admin backup --backup-dir=/tmp/3.5.24 --name=graphdbbackup

For details on performing a backup and the different command options, see Operations Manual 3.5 → Perform a backup.

Migrate the database backup to a 4.x standalone instance

To migrate the database backup and upgrade its store, you can spin up a standalone Neo4j instance and use the command neo4j-admin restore.

neo4j-admin restore must be invoked as the neo4j user to ensure the appropriate file permissions. For more information, see Operations Manual → Administrative commands.

If the --prepare-restore option has been disabled when backing up your database, you must run the neo4j-admin prepare-restore command before you can restore your database. This is to apply the latest transactions pulled at the backup time but not yet applied to the store. For more information, see Prepare a database for restoring.

  1. In the neo4j.conf file of a 4.x standalone instance, set dbms.allow_upgrade=true.

  2. Start the server.

  3. Navigate to the /bin folder and run the following command to restore the database backup.

    ./neo4j-admin restore --from=/tmp/3.5.24/graphdbbackup --database=graphdbbackup
  4. Run the following command to verify that the database graphdbbackup exists:

    ls -al ../data/databases
    total 0
    drwxr-xr-x@  6 username  staff   192  4 Dec 14:15 .
    drwxr-xr-x@  5 username  staff   160  7 Dec 09:35 ..
    drwxr-xr-x  42 username  staff  1344  4 Dec 14:15 graphdbbackup
    drwxr-xr-x  37 username  staff  1184  4 Dec 14:06 neo4j
    -rw-r--r--   1 username  staff     0  4 Dec 14:06 store_lock
    drwxr-xr-x  38 username  staff  1216  4 Dec 14:06 system

    However, restoring a database does not automatically create it. Therefore, it will not be visible if you do SHOW DATABASES in Cypher Shell or Neo4j Browser.

  5. Log in to the Cypher Shell command-line console.

  6. Change the active database to system (:USE system;), and create the graphdbbackup database.

    CREATE DATABASE graphdbbackup;
    0 rows available after 145 ms, consumed after another 0 ms
  7. Verify that the graphdbbackup database is online.

    SHOW DATABASES;
    +-------------------------------------------------------------------------------------------------------+
    | name            | address          | role         | requestedStatus | currentStatus | error | default |
    +-------------------------------------------------------------------------------------------------------+
    | "graphdbbackup" | "localhost:7687" | "standalone" | "online"        | "online"      | ""    | FALSE   |
    | "neo4j"         | "localhost:7687" | "standalone" | "online"        | "online"      | ""    | TRUE    |
    | "system"        | "localhost:7687" | "standalone" | "online"        | "online"      | ""    | FALSE   |
    +-------------------------------------------------------------------------------------------------------+
    
    3 rows available after 175 ms, consumed after another 9 ms
  8. Change the active database to graphdbbackup, and repeat steps 2, 3, and 4 from the section Prepare to back up the database, to verify that all the data has been successfully restored.

Back up the migrated database

To restore the migrated database in your cluster, you create a backup of it.

Navigate to the /bin folder, and run the following command to back up the database in your targeted folder. If the folder where you want to place your backup does not exist, you have to create it. In this example, it is called /tmp/4.0.11.

./neo4j-admin backup --backup-dir=/tmp/4.0.11 --database=graphdbbackup

For details on performing a backup and the different command options, see Operations Manual → Back up an online database.

Now you are ready to restore your migrated database backup into your running cluster.

Restore the migrated database on all cluster members

On each cluster member, navigate to the /bin folder, and run the following command to restore the backup of the migrated database. For details on performing a restore and the different command options, see Operations Manual → Restore command.

./neo4j-admin restore --from=/tmp/4.0.11/graphdbbackup --database=graphdbbackup

Then, on each cluster member, run the following command to verify that the database graphdbbackup exists:

ls -al ../data/databases
total 0
drwxr-xr-x@  6 username  staff   192  7 Dec 09:41 .
drwxr-xr-x@  5 username  staff   160  4 Dec 14:17 ..
drwxr-xr-x  38 username  staff  1216  7 Dec 09:41 graphdbbackup
drwxr-xr-x  37 username  staff  1184  7 Dec 08:57 neo4j
-rw-r--r--   1 username  staff     0  4 Dec 14:17 store_lock
drwxr-xr-x  38 username  staff  1216  7 Dec 08:56 system

Create the database backup on the cluster leader

You create the database backup only on one of your cluster members using the command CREATE DATABASE. The command is automatically routed to the leader, and from there, to the other cluster members.

  1. In the Cypher Shell command-line console on one of the cluster members, use the system database and create the database graphdbbackup.

    CREATE DATABASE graphdbbackup;
    0 rows available after 132 ms, consumed after another 0 ms
  2. Verify that the graphdbbackup database is online on all members.

    SHOW DATABASES;
    +-----------------------------------------------------------------------------------------------------+
    | name            | address          | role       | requestedStatus | currentStatus | error | default |
    +-----------------------------------------------------------------------------------------------------+
    | "graphdbbackup" | "localhost:7689" | "follower" | "online"        | "online"      | ""    | FALSE   |
    | "graphdbbackup" | "localhost:7688" | "leader"   | "online"        | "online"      | ""    | FALSE   |
    | "graphdbbackup" | "localhost:7687" | "follower" | "online"        | "online"      | ""    | FALSE   |
    | "neo4j"         | "localhost:7689" | "leader"   | "online"        | "online"      | ""    | TRUE    |
    | "neo4j"         | "localhost:7688" | "follower" | "online"        | "online"      | ""    | TRUE    |
    | "neo4j"         | "localhost:7687" | "follower" | "online"        | "online"      | ""    | TRUE    |
    | "system"        | "localhost:7689" | "leader"   | "online"        | "online"      | ""    | FALSE   |
    | "system"        | "localhost:7688" | "follower" | "online"        | "online"      | ""    | FALSE   |
    | "system"        | "localhost:7687" | "follower" | "online"        | "online"      | ""    | FALSE   |
    +-----------------------------------------------------------------------------------------------------+
  3. Change your active database to graphdbbackup and verify that all the data has been successfully restored by completing steps 2, 3, and 4 of the Prepare to back up the database section.

Recreate the database users and roles

On all cluster members, manually recreate all users and roles of the restored database using your notes from step 5 of the section Prepare to back up the database and the Cypher Manual → Cypher administration commands.

Example 1. Run the following commands against the system database to recreate the graphdbbackup database’s custom users and roles.
  1. Create the user user1.

    CREATE USER user1 IF NOT EXISTS
    SET PASSWORD 'password'
    SET STATUS ACTIVE;
  2. Grant the role reader to the user user1.

    GRANT ROLE reader TO user1;
  3. Grant the role editor to the user user1.

    GRANT ROLE editor TO user1;
  4. Verify that the user user1 has the same roles as in the database backup.

    SHOW USERS;
    +---------------------------------------------------------------------+
    | user    | roles                | passwordChangeRequired | suspended |
    +---------------------------------------------------------------------+
    | "neo4j" | ["admin"]            | FALSE                  | FALSE     |
    | "user1" | ["editor", "reader"] | TRUE                   | FALSE     |
    +---------------------------------------------------------------------+