Skip to content

Commit 846479a

Browse files
Document anomalies under read-committed. (#1601) (#1613)
Slightly restructure locking section to accommodate these changes. --------- Cherry-picked from #1601 Co-authored-by: Satia Herfert <[email protected]>
1 parent 1f7fb5a commit 846479a

File tree

5 files changed

+68
-20
lines changed

5 files changed

+68
-20
lines changed

modules/ROOT/content-nav.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@
125125
126126
* xref:database-internals/index.adoc[]
127127
** xref:database-internals/transaction-management.adoc[]
128-
** xref:database-internals/locks-deadlocks.adoc[]
128+
** xref:database-internals/concurrent-data-access.adoc[]
129129
** xref:database-internals/transaction-logs.adoc[]
130130
** xref:database-internals/checkpointing.adoc[]
131131
** xref:database-internals/store-formats.adoc[]

modules/ROOT/pages/configuration/configuration-settings.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5228,7 +5228,7 @@ m|+++neo4j+++
52285228
== Transaction settings
52295229

52305230
The transaction settings helps you manage the transactions in your database, for example, the transaction timeout, the lock acquisition timeout, the maximum number of concurrently running transactions, etc.
5231-
For more information, see xref:/database-internals/transaction-management.adoc#_manage-transactions[Manage transactions] and xref:/database-internals/locks-deadlocks.adoc[Locks and deadlocks].
5231+
For more information, see xref:/database-internals/transaction-management.adoc#_manage-transactions[Manage transactions] and xref:/database-internals/concurrent-data-access.adoc[Concurrent data access].
52325232

52335233

52345234
[role=label--dynamic]

modules/ROOT/pages/database-internals/locks-deadlocks.adoc renamed to modules/ROOT/pages/database-internals/concurrent-data-access.adoc

Lines changed: 64 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,7 @@
1-
= Locks and deadlocks
2-
:description: This page discusses how locks are used in Neo4j, isolation levels, default locking behavior, deadlocks and strategies to avoid deadlocks, delete semantics, creating unique nodes, and transaction events.
1+
= Concurrent data access
2+
:description: This page discusses concurrent data access, how locks are used in Neo4j, isolation levels, default locking behavior, deadlocks and strategies to avoid deadlocks, delete semantics, creating unique nodes, and transaction events.
33

4-
When a write transaction occurs, Neo4j takes locks to preserve data consistency while updating.
5-
6-
== Locks
7-
8-
Locks are taken automatically by the queries that users run.
9-
They ensure that a node/relationship is locked to one particular transaction until that transaction is completed.
10-
In other words, a lock on a node or a relationship by one transaction pauses other transactions to concurrently modify the same node or relationship.
11-
As such, locks prevent concurrent modifications of shared resources between transactions.
12-
13-
=== Isolation levels
14-
15-
Locks are used in Neo4j to ensure data consistency and isolation levels.
16-
They not only protect logical entities (such as nodes and relationships) but also the integrity of internal data structures.
4+
== Isolation levels
175

186
Neo4j supports the following isolation levels:
197

@@ -25,8 +13,14 @@ Using locks allows for simulating the effects of higher levels of isolation by o
2513
For example, if a write lock is taken on a common node or relationship, then all transactions are serialized on that lock -- giving the effect of a _serializable isolation level_.
2614
For more information on how to manually acquire write locks, see <<transactions-isolation-lostupdates>>.
2715

16+
== Anomalies
17+
18+
Depending on the isolation level, different anomalies may occur when multiple transactions concurrently read or write the same data.
19+
20+
All the anomalies listed here can only occur with the read-committed isolation level.
21+
2822
[[transactions-isolation-lostupdates]]
29-
=== Lost updates in Cypher
23+
=== Lost updates
3024

3125
In Cypher, it is possible to acquire write locks to simulate improved isolation in some cases.
3226
Consider the case where multiple concurrent Cypher queries increment the value of a property.
@@ -106,6 +100,60 @@ REMOVE n._LOCK_
106100

107101
The existence of the `+SET n._LOCK_+` statement before the read of the `n.prop` read ensures the lock is acquired before the read action, and no updates are lost due to enforced serialization of all concurrent queries on that specific node.
108102

103+
=== Non-repeatable reads
104+
105+
A non-repeatable read is when the same transaction reads the same data but gets inconsistent results.
106+
This can easily happen if reading the same data twice in a query and the data gets modified in-between by another concurrent query.
107+
108+
.Non-repeatable read
109+
====
110+
The following example query shows that reading the same property twice can give inconsistent results.
111+
If there are other queries running concurrently, it is not guaranteed that `p1` and `p2` have the same value.
112+
113+
[source, cypher, role="noheader"]
114+
----
115+
MATCH (n:Example {id: 42})
116+
WITH n.prop AS p1
117+
// another concurrent query changes the value of n.prop here.
118+
WITH *, n.prop AS p2
119+
RETURN p1, p2
120+
----
121+
====
122+
123+
The easiest way to work around this is to only read each property once, and keep it as long as needed in the query.
124+
125+
=== Missing and double reads
126+
127+
When scanning an xref:performance/index-configuration.adoc[index], entities may be observed multiple times or skipped entirely, even if they are present in the index.
128+
This is true even for indexes that back link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/constraints/examples/#constraints-examples-node-uniqueness[uniqueness constraints].
129+
130+
During the scan, if another concurrent query changes an entity's property to a position ahead of the scan, the entity might appear again in the index.
131+
Similarly, the entity may not appear at all if the property is changed to a previously scanned position.
132+
133+
This anomaly can only occur with operators that scan an index, or parts of an index, for example link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/planning-and-tuning/operators/operators-detail/#query-plan-node-index-scan[`NodeIndexScan`] or link:{neo4j-docs-base-uri}/cypher-manual/{page-version}/planning-and-tuning/operators/operators-detail/#query-plan-directed-relationship-index-seek-by-range[`DirectedRelationshipIndexSeekByRange`].
134+
135+
.Missing and double read
136+
====
137+
In the following query, each node `n` that has the property `prop` is expected to appear exactly once.
138+
However, concurrent updates that modify the `prop` property during index scanning may cause a node to appear multiple times or not at all in the result set.
139+
[source, cypher, role="noheader"]
140+
----
141+
MATCH (n:Example) WHERE n.prop IS NOT NULL
142+
RETURN n
143+
----
144+
====
145+
146+
== Locks
147+
148+
When a write transaction occurs, Neo4j takes locks to preserve data consistency while updating.
149+
150+
Locks are used in Neo4j to ensure data consistency and isolation levels.
151+
They not only protect logical entities (such as nodes and relationships) but also the integrity of internal data structures.
152+
153+
Locks are taken automatically by the queries that users run.
154+
They ensure that a node/relationship is locked to one particular transaction until that transaction is completed.
155+
In other words, a lock on a node or a relationship by one transaction pauses other transactions to concurrently modify the same node or relationship.
156+
As such, locks prevent concurrent modifications of shared resources between transactions.
109157

110158
[[transactions-locking]]
111159
=== Default locking behavior

modules/ROOT/pages/database-internals/index.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ However, you can also manually acquire write locks if you want to achieve a high
2121
The following sections describe the transactional behavior in detail and how to control it:
2222

2323
* xref:database-internals/transaction-management.adoc[]
24-
* xref:database-internals/locks-deadlocks.adoc[]
24+
* xref:database-internals/concurrent-data-access.adoc[]
2525
* xref:database-internals/transaction-logs.adoc[]
2626
* xref:database-internals/checkpointing.adoc[]
2727
* xref:database-internals/store-formats.adoc[]

modules/ROOT/pages/database-internals/transaction-management.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ The interaction cycle of working with transactions follows the steps:
1313
. Perform database operations.
1414
. Commit or roll back the transaction.
1515

16-
It is crucial to finish each transaction because the xref:/database-internals/locks-deadlocks.adoc#_locks[locks] or memory acquired by a transaction are only released upon completion.
16+
It is crucial to finish each transaction because the xref:/database-internals/concurrent-data-access.adoc#_locks[locks] or memory acquired by a transaction are only released upon completion.
1717
All non-committed transactions are rolled back as part of resource cleanup at the end of the statement.
1818
No resource cleanup is required for a transaction that is explicitly committed or rolled back, and the transaction closure is an empty operation.
1919

0 commit comments

Comments
 (0)