Back up and restore a database in Causal Cluster

This tutorial provides a detailed example of how to back up and restore a database in a running Causal Cluster.

The following example assumes that you want to restore a database backup, which has users and roles associated with it, in a running Causal Cluster with three core servers. For more information on how to set up a Causal Cluster with three cores, see Set up a local Causal 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 Backup.

1. Prepare to back up your database

Before you perform the backup, it is good to take a note of the data and metadata (users and roles) of the database that you want to restore, which you can later use to verify that the restore is successful.

  1. In the Neo4j instance, where the database is running, log in to the Cypher Shell command-line console with your credentials.

    $neo4j-home/bin$> ./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. Change the active database to movies1 using :USE DATABASE movies1. This example database uses the dataset from Movie Graph (from Neo4j Browser → Favorites → Example Graphs).

  3. Run a query to count the number of nodes in the database.

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

    neo4j@movies1> MATCH (n)-[r]->() RETURN count(r) AS countRelationships;
    +--------------------+
    | countRelationships |
    +--------------------+
    | 253                |
    +--------------------+
    
    1 row available after 29 ms, consumed after another 0 ms
  5. Run a query to see if there are any custom roles associated with this database.

    neo4j@movies1> SHOW ALL PRIVILEGES;
    +-------------------------------------------------------------------------------------------+
    | access    | action       | resource         | graph     | segment           | role        |
    +-------------------------------------------------------------------------------------------+
    | "GRANTED" | "execute"    | "database"       | "*"       | "FUNCTION(*)"     | "PUBLIC"    |
    | "GRANTED" | "execute"    | "database"       | "*"       | "PROCEDURE(*)"    | "PUBLIC"    |
    | "GRANTED" | "access"     | "database"       | "DEFAULT" | "database"        | "PUBLIC"    |
    | "GRANTED" | "match"      | "all_properties" | "*"       | "NODE(*)"         | "admin"     |
    | "GRANTED" | "write"      | "graph"          | "*"       | "NODE(*)"         | "admin"     |
    | "GRANTED" | "match"      | "all_properties" | "*"       | "RELATIONSHIP(*)" | "admin"     |
    | "GRANTED" | "write"      | "graph"          | "*"       | "RELATIONSHIP(*)" | "admin"     |
    | "GRANTED" | "access"     | "database"       | "*"       | "database"        | "admin"     |
    | "GRANTED" | "admin"      | "database"       | "*"       | "database"        | "admin"     |
    | "GRANTED" | "constraint" | "database"       | "*"       | "database"        | "admin"     |
    | "GRANTED" | "index"      | "database"       | "*"       | "database"        | "admin"     |
    | "GRANTED" | "token"      | "database"       | "*"       | "database"        | "admin"     |
    | "GRANTED" | "match"      | "all_properties" | "*"       | "NODE(*)"         | "architect" |
    | "GRANTED" | "write"      | "graph"          | "*"       | "NODE(*)"         | "architect" |
    | "GRANTED" | "match"      | "all_properties" | "*"       | "RELATIONSHIP(*)" | "architect" |
    | "GRANTED" | "write"      | "graph"          | "*"       | "RELATIONSHIP(*)" | "architect" |
    | "GRANTED" | "access"     | "database"       | "*"       | "database"        | "architect" |
    | "GRANTED" | "constraint" | "database"       | "*"       | "database"        | "architect" |
    | "GRANTED" | "index"      | "database"       | "*"       | "database"        | "architect" |
    | "GRANTED" | "token"      | "database"       | "*"       | "database"        | "architect" |
    | "GRANTED" | "match"      | "all_properties" | "*"       | "NODE(*)"         | "editor"    |
    | "GRANTED" | "write"      | "graph"          | "*"       | "NODE(*)"         | "editor"    |
    | "GRANTED" | "match"      | "all_properties" | "*"       | "RELATIONSHIP(*)" | "editor"    |
    | "GRANTED" | "write"      | "graph"          | "*"       | "RELATIONSHIP(*)" | "editor"    |
    | "GRANTED" | "access"     | "database"       | "*"       | "database"        | "editor"    |
    | "GRANTED" | "match"      | "all_properties" | "movies1" | "NODE(*)"         | "myrole"    |
    | "GRANTED" | "write"      | "graph"          | "movies1" | "NODE(*)"         | "myrole"    |
    | "GRANTED" | "match"      | "all_properties" | "movies1" | "RELATIONSHIP(*)" | "myrole"    |
    | "GRANTED" | "write"      | "graph"          | "movies1" | "RELATIONSHIP(*)" | "myrole"    |
    | "GRANTED" | "access"     | "database"       | "movies1" | "database"        | "myrole"    |
    | "GRANTED" | "match"      | "all_properties" | "*"       | "NODE(*)"         | "publisher" |
    | "GRANTED" | "write"      | "graph"          | "*"       | "NODE(*)"         | "publisher" |
    | "GRANTED" | "match"      | "all_properties" | "*"       | "RELATIONSHIP(*)" | "publisher" |
    | "GRANTED" | "write"      | "graph"          | "*"       | "RELATIONSHIP(*)" | "publisher" |
    | "GRANTED" | "access"     | "database"       | "*"       | "database"        | "publisher" |
    | "GRANTED" | "token"      | "database"       | "*"       | "database"        | "publisher" |
    | "GRANTED" | "match"      | "all_properties" | "*"       | "NODE(*)"         | "reader"    |
    | "GRANTED" | "match"      | "all_properties" | "*"       | "RELATIONSHIP(*)" | "reader"    |
    | "GRANTED" | "access"     | "database"       | "*"       | "database"        | "reader"    |
    +-------------------------------------------------------------------------------------------+
    
    39 rows available after 1 ms, consumed after another 3 ms

    The result shows that there is one custom role myrole.

  6. Run a query to see all users associated with this role.

    neo4j@movies1> SHOW USERS;
    +----------------------------------------------------------------------+
    | user     | roles                | passwordChangeRequired | suspended |
    +----------------------------------------------------------------------+
    | "neo4j"  | ["admin", "PUBLIC"]  | FALSE                  | FALSE     |
    | "user1" | ["myrole", "PUBLIC"] | FALSE                  | FALSE     |
    +----------------------------------------------------------------------+
    
    2 rows available after 1 ms, consumed after another 1 ms
  7. Exit the Cypher Shell command-line console.

    neo4j@movies1> :exit;
    
    Bye!

2. Back up your 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/4.2.2.

To perform the backup, run the following command:

$neo4j-home/bin$>./neo4j-admin backup --backup-dir=/tmp/4.2.2 --database=movies1 --include-metadata=all

The option --include-metadata=all creates a cypher script, which you can later use to restore the database’s users, roles, and privileges.

For details on performing a backup and the different command options, see Perform a backup.

3. Delete the database that you want to replace

Before you restore the database backup, you will have to delete the database that you want to replace with that backup. If you want to restore the backup as an additional database in your DBMS, then you can proceed to Restore the database backup on all cluster members directly.

On one of the cluster members, run the Cypher command DROP DATABASE to delete the database that you want to replace. Dropping a database also deletes all users and roles associated with it. 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, change the active database to system, and run the command DROP DATABASE to delete the database that you want to replace. In this example, the database is called movies.

    neo4j@system> DROP DATABASE movies;
    0 rows available after 82 ms, consumed after another 0 ms

    If you are unable to delete the database (e.g., because Neo4j is not running), you must run neo4j-admin unbind first instead. If you fail to do this, the store files you have (post restore) will be out of sync with the cluster state you have for that database, leading to logical corruption.

  2. You can run SHOW DATABASES to verify that the database movies does not exist.

    neo4j@system> SHOW DATABASES;
    +----------------------------------------------------------------------------------------------+
    | name     | address          | role       | requestedStatus | currentStatus | error | default |
    +----------------------------------------------------------------------------------------------+
    | "neo4j"  | "localhost:7687" | "follower" | "online"        | "online"      | ""    | TRUE    |
    | "neo4j"  | "localhost:7688" | "leader"   | "online"        | "online"      | ""    | TRUE    |
    | "neo4j"  | "localhost:7689" | "follower" | "online"        | "online"      | ""    | TRUE    |
    | "system" | "localhost:7687" | "follower" | "online"        | "online"      | ""    | FALSE   |
    | "system" | "localhost:7688" | "follower" | "online"        | "online"      | ""    | FALSE   |
    | "system" | "localhost:7689" | "leader"   | "online"        | "online"      | ""    | FALSE   |
    | "test"   | "localhost:7687" | "leader"   | "online"        | "online"      | ""    | FALSE   |
    | "test"   | "localhost:7688" | "follower" | "online"        | "online"      | ""    | FALSE   |
    | "test"   | "localhost:7689" | "follower" | "online"        | "online"      | ""    | FALSE   |
    +----------------------------------------------------------------------------------------------+
    
    9 rows available after 7 ms, consumed after another 3 ms

4. Restore the database backup on all cluster members

On each cluster member, run the following command to restore the database backup. For details on performing a restore and the different command options, see Restore a backup.

$neo4j-home/bin$>./neo4j-admin restore --from=/tmp/4.2.2/movies1 --database=movies1
You need to execute $HOME/path/to/core-member/data/scripts/movies1/restore_metadata.cypher. To execute the file use cypher-shell command with parameter `movies1`
restorePath=/tmp/{neo4j-version-exact}/movies1, restoreStatus=successful, reason=

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

$neo4j-home/bin$>ls -al ../data/databases
total 0
drwxr-xr-x@  7 username  staff   224 17 Nov 15:50 .
drwxr-xr-x@  8 username  staff   256 17 Nov 15:50 ..
drwxr-xr-x  40 username  staff  1280 17 Nov 15:50 movies1
drwxr-xr-x  37 username  staff  1184 16 Nov 15:00 neo4j
-rw-r--r--   1 username  staff     0 16 Nov 15:00 store_lock
drwxr-xr-x  38 username  staff  1216 16 Nov 15:00 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. Create the database backup on the cluster leader

On one of the cluster members, run the restore cypher script restore_metadata.cypher to create the database and recreate all users and roles of the database backup. The command is automatically routed to the leader, and from there, to the other cluster members.

Using cat (UNIX)

$neo4j-home> cat data/scripts/movies1/restore_metadata.cypher | bin/cypher-shell -u neo4j -p password -a localhost:7688 -d system --param "database => 'movies1'"

Using type (Windows)

$neo4j-home> type data\scripts\movies1\restore_metadata.cypher | bin\cypher-shell.bat -u neo4j -p password -a localhost:7688 -d system --param "database => 'movies1'"

Verify the database restore

  1. In the Cypher Shell command-line console on one of the cluster members, run SHOW DATABASES to verify that the movies1 database is online on all members.

    neo4j@neo4j> SHOW DATABASES;
    +-----------------------------------------------------------------------------------------------+
    | name      | address          | role       | requestedStatus | currentStatus | error | default |
    +-----------------------------------------------------------------------------------------------+
    | "movies1" | "localhost:7688" | "follower" | "online"        | "online"      | ""    | FALSE   |
    | "movies1" | "localhost:7687" | "leader"   | "online"        | "online"      | ""    | FALSE   |
    | "movies1" | "localhost:7689" | "follower" | "online"        | "online"      | ""    | FALSE   |
    | "neo4j"   | "localhost:7688" | "leader"   | "online"        | "online"      | ""    | TRUE    |
    | "neo4j"   | "localhost:7687" | "follower" | "online"        | "online"      | ""    | TRUE    |
    | "neo4j"   | "localhost:7689" | "follower" | "online"        | "online"      | ""    | TRUE    |
    | "system"  | "localhost:7688" | "follower" | "online"        | "online"      | ""    | FALSE   |
    | "system"  | "localhost:7687" | "leader"   | "online"        | "online"      | ""    | FALSE   |
    | "system"  | "localhost:7689" | "follower" | "online"        | "online"      | ""    | FALSE   |
    +-----------------------------------------------------------------------------------------------+
    
    9 rows available after 3 ms, consumed after another 1 ms
  2. Change your active database to movies1 and verify the all the data has been successfully restored by completing the steps 1, 2, and 3 of the section Prepare to back up your database.

6. Recreate the database users and roles

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

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

    neo4j@system> CREATE USER user1 IF NOT EXISTS
          SET PASSWORD 'password'
          SET STATUS ACTIVE;
  2. Create the role myrole as a copy of the built-in role reader. You can see from the notes that myrole is a superset of reader. For more information on the Neo4j built-in roles, see Built-in roles.

    CREATE  ROLE myrole  AS COPY OF reader;
  3. Grant myrole the privilege to write on the graph movies1.

    GRANT WRITE ON GRAPH movies1 TO myrole;
  4. Grant the role myrole to the user user1.

    GRANT ROLE myrole TO user1;
  5. Verify that the role myrole has the same privileges as in the database backup.

    SHOW ROLE myrole PRIVILEGES;
    +------------------------------------------------------------------------------------+
    | access    | action   | resource         | graph     | segment           | role     |
    +------------------------------------------------------------------------------------+
    | "GRANTED" | "match"  | "all_properties" | "*"       | "NODE(*)"         | "myrole" |
    | "GRANTED" | "match"  | "all_properties" | "*"       | "RELATIONSHIP(*)" | "myrole" |
    | "GRANTED" | "access" | "database"       | "*"       | "database"        | "myrole" |
    | "GRANTED" | "write"  | "graph"          | "movies1" | "NODE(*)"         | "myrole" |
    | "GRANTED" | "write"  | "graph"          | "movies1" | "RELATIONSHIP(*)" | "myrole" |
    +------------------------------------------------------------------------------------+
    
    5 rows available after 176 ms, consumed after another 1 ms
  6. Verify that the user user1 has the same roles as in the database backup.

    SHOW USERS;
    +---------------------------------------------------------------------+
    | user    | roles                | passwordChangeRequired | suspended |
    +---------------------------------------------------------------------+
    | "neo4j" | ["admin", "PUBLIC"]  | FALSE                  | FALSE     |
    | "user1" | ["myrole", "PUBLIC"] | TRUE                   | FALSE     |
    +---------------------------------------------------------------------+
    
    2 rows available after 43 ms, consumed after another 1 ms