Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new unquarantine procedure + deprecate quarantine #1985

Merged
merged 9 commits into from
Dec 20, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -160,75 +160,50 @@ It produces a database dump that can be further examined and potentially repaire
[[quarantine]]
== Quarantined databases

There are two ways to get a database into a `quarantined` state:

* By using the xref:procedures.adoc#procedure_dbms_quarantineDatabase[`dbms.quarantineDatabase`] procedure locally to isolate a specific database.
The procedure must be executed on the instance whose copy of the database you want to quarantine.
A reason for that can be, for example, when a database is unable to start on a given instance due to a file system permissions issue with the volume where the database is located or when a recently started database begins to log errors.
The quarantine state renders the database inaccessible on that instance and prevents its state from being changed, for example, with the `START DATABASE` command.
+
[NOTE]
====
If running in a cluster, database management commands such as `START DATABASE foo` will still take effect on the instances which have *not* quarantined `foo`.
====

* When a database encounters a severe error during its normal run, which prevents it from a further operation, Neo4j stops that database and brings it into a `quarantined` state.
When a database encounters a severe error during its normal run, which prevents it from a further operation, Neo4j stops that database and brings it into a `quarantined` state.
Meaning, it is not possible to restart it with a simple `START DATABASE` command.
You have to execute `CALL dbms.quarantineDatabase(databaseName, false)` on the instance with the failing database in order to lift the quarantine.
You have to execute `CALL dbms.unquarantineDatabase(server, databaseName, operation)` in order to lift the quarantine, specifying as `server` the instance with the failing database.
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved

After lifting the quarantine, the instance will automatically try to bring the database to the desired state.

[NOTE]
====
It is recommended to run the quarantine procedure over the `bolt://` protocol rather than `neo4j://`, which may route requests to unexpected instances.
====

*Syntax:*

`CALL dbms.quarantineDatabase(databaseName,setStatus,reason)`
`CALL dbms.unquarantineDatabase(server, databaseName, operation)`
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved

*Arguments:*
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved

[options="header"]
|===
| Name | Type | Description
| `server` | String | The identifier of the server where the quarantine for database will be lifted.
| `databaseName` | String | The name of the database that will be put into or removed from quarantine.
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved
| `setStatus` | Boolean | `true` for placing the database into quarantine; `false` for lifting the quarantine.
| `reason` | String | (Optional) The reason for placing the database in quarantine.
| `operation` | String | Optional operation to apply while lifting the quarantine.
|===

[NOTE]
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved
====
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved
The possible values for the optional operation are:

* `keepStateKeepStore` -- do nothing; leave store and cluster state as they are.
* `replaceStateKeepStore` -- join as a new member, clearing the current cluster state but keeping the store.
* `replaceStateReplaceStore` -- join as a new member, clearing both the current cluster state and the store.

If you choose to clear the current cluster state, the server will try to join as a new member,
but this joining can succeed if and only if there is a majority of old members "letting" the new members in.
Let's assume our cluster has a topology with three primaries.
If there is only one server in `QUARANTINED` mode, then it is safe to choose `replaceStateKeepStore` or `replaceStateReplaceStore`.
If there are two servers in `QUARANTINED` mode, then you should not use concurrently `replaceStateKeepStore` or `replaceStateReplaceStore` for both servers because there would be no majority to let them in.
====
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved

*Returns:*
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved

[options="header"]
|===
| Name | Type | Description
| `databaseName` | String | The name of the database.
| `quarantined` | String | Actual state.
| `result` | String | Result of the last operation.
The result contains the user, the time, and the reason for the quarantine.
|===
The procedure doesn't return any value.

[NOTE]
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved
====
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved
The `dbms.quarantineDatabase` procedure replaces xref:procedures.adoc#procedure_dbms_cluster_quarantinedatabase[`dbms.cluster.quarantineDatabase`], which has been deprecated in Neo4j 4.3 and will be removed with the next major version.
The `dbms.unquarantineDatabase` procedure replaces xref:procedures.adoc#procedure_dbms_quarantineDatabase[`dbms.quarantineDatabase`], which has been deprecated in Neo4j 5.26.
NataliaIvakina marked this conversation as resolved.
Show resolved Hide resolved
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved
====
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved

.Quarantine a database
[source, cypher]
----
neo4j@system> CALL dbms.quarantineDatabase("foo",true);
----
[queryresult]
----
+--------------------------------------------------------------------------------------+
| databaseName | quarantined | result |
+--------------------------------------------------------------------------------------+
| "foo" | TRUE | "By neo4j at 2020-10-15T15:10:41.348Z: No reason given" |
+--------------------------------------------------------------------------------------+

3 row available after 100 ms, consumed after another 6 ms
----

.Check if a database is quarantined
[source, cypher]
----
Expand All @@ -251,7 +226,7 @@ neo4j@system> SHOW DATABASE foo;
====
A `quarantined` state is persisted for user databases.
This means that if a database is quarantined, it will remain so even if that Neo4j instance is restarted.
You can remove it only by running the xref:procedures.adoc#procedure_dbms_quarantineDatabase[`dbms.quarantineDatabase`] procedure on the instance where the quarantined database is located, passing `false` for the `setStatus` parameter.
You can remove it only by running the xref:procedures.adoc#procedure_dbms_unquarantineDatabase[`dbms.unquarantineDatabase`] procedure.
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved

The one exception to this rule is for the built-in `system` database.
Any quarantine for that database is removed automatically after instance restart.
Expand Down
46 changes: 45 additions & 1 deletion modules/ROOT/pages/procedures.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1056,7 +1056,7 @@ For more information, see the link:{neo4j-docs-base-uri}/cypher-manual/{page-ver
| *Mode* 3+| WRITE
|===

[role=label--enterprise-edition label--admin-only]
[role=label--enterprise-edition label--admin-only label--deprecated-2025.01]
NataliaIvakina marked this conversation as resolved.
Show resolved Hide resolved
[[procedure_dbms_quarantineDatabase]]
=== dbms.quarantineDatabase()

Expand All @@ -1076,6 +1076,43 @@ For more information, see the link:{neo4j-docs-base-uri}/cypher-manual/{page-ver
| *Mode* 3+| DBMS
|===

[NOTE]
====
It is recommended to use <<procedure_dbms_unquarantineDatabase,`dbms.unquarantineDatabase()`>> over `dbms.quarantineDatabase()` due to its improvements and new features (see the `operation` option ).
The deprecated `dbms.quarantineDatabase()` procedure is available in Cypher 5, but not in Cypher 25.
====

[role=label--enterprise-edition label--admin-only label--new-2025.01]
[[procedure_dbms_unquarantineDatabase]]
=== dbms.unquarantineDatabase()


.Details
|===
| *Syntax* 3+m| dbms.unquarantineDatabase(server, databaseName, operation) :: ()
| *Description* 3+a| Lift quarantine from a database on a given server.
.4+| *Input arguments* | *Name* | *Type* | *Description*
| `server` | `STRING` | The identifier of the server where the quarantine for database will be lifted.
| `databaseName` | `STRING` | The name of the database for the quarantine will be lifted.
Frannie-Ludmilla marked this conversation as resolved.
Show resolved Hide resolved
| `operation` | `STRING` | Optional operation to apply while lifting the quarantine.
| *Mode* 3+| DBMS
|===

[NOTE]
====
The possible values for the optional operation are:

* `keepStateKeepStore` -- do nothing; leave store and cluster state as they are.
* `replaceStateKeepStore` -- join as a new member, clearing the current cluster state but keeping the store.
* `replaceStateReplaceStore` -- join as a new member, clearing both the current cluster state and the store.

If you choose to clear the current cluster state, the server will try to join as a new member,
but this joining can succeed if and only if there is a majority of old members "letting" the new members in.
Let's assume our cluster has a topology with three primaries.
If there is only one server in `QUARANTINED` mode, then it is safe to choose `replaceStateKeepStore` or `replaceStateReplaceStore`.
If there are two servers in `QUARANTINED` mode, then you should not use concurrently `replaceStateKeepStore` or `replaceStateReplaceStore` for both servers because there would be no majority to let them in.
====

[role=label--admin-only label--deprecated-5.9]
[[procedure_dbms_upgrade]]
=== dbms.upgrade()
Expand Down Expand Up @@ -1925,6 +1962,13 @@ Replaced by: xref:procedures.adoc#procedure_dbms_routing_getroutingtable[`dbms.r
Before Neo4j 5.23, the procedure can be run only with the `Admin` privileges. +
Replaced by xref:clustering/server-syntax.adoc#server-management-syntax[`ENABLE SERVER`].

// New in v6
| xref:procedures.adoc#procedure_dbms_quarantineDatabase[`dbms.quarantineDatabase()`]
| label:no[]
| label:yes[]
| label:admin-only[] label:deprecated[Deprecated in 2025.01] +
Replaced by xref:procedures.adoc#procedure_dbms_unquarantineDatabase[`dbms.unquarantineDatabase()`]

| xref:procedures.adoc#procedure_dbms_setDatabaseAllocator[`dbms.setDatabaseAllocator()`]
| label:no[]
| label:yes[]
Expand Down
Loading