Multi-tenant support in Memgraph enables users to manage multiple isolated databases within a single instance. The primary objective is to facilitate efficient resource isolation, maintain data integrity, and manage access for different clients.
In the current version, all isolated databases share the underlying resources so there is no provision to restrict CPU or RAM usage for a specific database. Instead, global limitations are imposed on Memgraph as a whole.
A default database named 'memgraph' is automatically created during startup. New users are granted access only to this default database. The default database name cannot be altered.
Isolated databases within Memgraph function as distinct single-database Memgraph instances. Queries executed on a specific database should operate as if it were the sole database in the system, preventing cross-database contamination. Users interact with individual databases, and cross-database queries are prohibited.
At present, all isolated databases share identical configurations. There is no provision to specify a per-database configuration.
The sole distinction lies in the location of the data directory. The designated
data directory serves as the root and retains data associated with the default
database. Other databases are housed in new directories within
memgraph database also includes a directory
data_directory/databases/memgraph, which contains symbolic links leading back
to the root. Some links are proactively generated and their status may vary
based on configuration.
Users interact with multi-tenant features through specialized Cypher queries:
CREATE DATABASE name: Creates a new database.
DROP DATABASE name: Deletes a specified database.
SHOW DATABASES: Lists all active databases, indicating the currently selected one.
USE DATABASE name: Switches focus to a specific database (disabled during transactions).
GRANT DATABASE name TO user: Grants a user access to a specified database.
REVOKE DATABASE name FROM user: Revokes a user's access to a specified database.
SET MAIN DATABASE name FOR user: Sets a user's default (landing) database.
SHOW DATABASE PRIVILEGES FOR user: Lists a user's database access rights.
Administrators assign default databases to users, ensuring a seamless and secure connection experience. Users cannot connect to Memgraph if they lack access rights to their default database. This situation may arise from database deletion or revoked access rights.
Authentication and authorization data are shared across databases, providing a unified source of truth. A single user can access multiple databases with a global set of privileges, but currently, per-database privileges cannot be granted.
Access to all databases can be granted or revoked using wildcards:
GRANT DATABASE * TO user; or
REVOKE DATABASE * FROM user;.
Administrators manage multi-tenant privileges with:
MULTI_DATABASE_USE: Enables database switching and listing.
MULTI_DATABASE_EDIT: Permits database creation and deletion.
data_recovery_on_startup flag replaces
facilitating recovery of individual databases and their contents during startup.
storage_recover_on_startup is still functional but deprecated.
storage_delete_on_drop is set to true, the underlying directories
associated with the dropped database will be deleted.
Neo4j drivers interact with multi-tenant databases in two ways:
- Through Cypher queries.
- By defining the
USE DATABASEquery is disabled when the database field is defined. The query consistently runs against the specified database.
Example using Neo4j Python driver:
import neo4j driver = neo4j.GraphDatabase.driver("bolt://localhost:7687", auth=("user", "pass")) with driver.session() as session: session.run(...) # Executes on the default database session.run("USE DATABASE db1") session.run(...) # Executes on db1 with driver.session(database="db2") as session: session.run(...) # Executes on db2 session.run("USE DATABASE db1") # Error: database switching disabled
Audit logs now encompass the active database name, positioned immediately after the username field.
The multi-tenant feature ensures backwards compatibility, facilitating smooth version upgrades and downgrades without disrupting user experience. During an upgrade, previous data is migrated to the default database, while downgrading retains data solely in the default database.