Skip to content

Commit af38290

Browse files
Add best practice example to subqueries in transactions with deadlocks section (neo4j#1301)
Co-authored-by: Jens Pryce-Åklundh <[email protected]>
1 parent d667067 commit af38290

File tree

1 file changed

+48
-1
lines changed

1 file changed

+48
-1
lines changed

modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -956,7 +956,7 @@ CALL (row) {
956956
MERGE (y:Year {year: row.year})
957957
MERGE (m)-[r:RELEASED_IN]->(y)
958958
} IN 2 CONCURRENT TRANSACTIONS OF 10 ROWS ON ERROR RETRY FOR 3 SECONDS THEN CONTINUE REPORT STATUS AS status
959-
RETURN status.transactionID as transaction, status.committed AS successfulTransaction
959+
RETURN status.transactionId as transaction, status.committed AS successfulTransaction
960960
----
961961
// end::subqueries_in_transactions_deadlock_example[]
962962
@@ -1064,6 +1064,53 @@ The result shows that all transactions are now successful:
10641064
+-------------------------------------------------+
10651065
----
10661066
1067+
Deadlock resolution and transaction retries are time-consuming, making deadlock avoidance a preferred strategy.
1068+
This can be achieved by dividing a task into two distinct subqueries: a data-independent subquery run in parallel with maximum concurrency, and a data-dependent subquery executed serially (i.e. one transaction at a time) to avoid deadlocks.
1069+
In the below example, nodes and properties are created in a concurrent subquery, while the relationships connecting those nodes are created in a serial subquery.
1070+
This method benefits from the performance of concurrent transactions while avoiding deadlocks.
1071+
1072+
.Avoiding deadlocks by dividing an import task into a data-independent concurrent subquery followed by a data-dependent serial subquery
1073+
// tag::subqueries_in_transactions_deadlock_example_2[]
1074+
[source, cypher]
1075+
----
1076+
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/movies.csv' AS row
1077+
CALL (row) {
1078+
MERGE (m:Movie {movieId: row.movieId})
1079+
MERGE (y:Year {year: row.year})
1080+
RETURN m, y
1081+
} IN CONCURRENT TRANSACTIONS OF 10 ROWS ON ERROR RETRY THEN CONTINUE REPORT STATUS AS nodeStatus
1082+
CALL (m, y) {
1083+
MERGE (m)-[r:RELEASED_IN]->(y)
1084+
} IN TRANSACTIONS OF 10 ROWS ON ERROR RETRY THEN CONTINUE REPORT STATUS AS relationshipStatus
1085+
RETURN nodeStatus.transactionId as nodeTransaction,
1086+
nodeStatus.committed AS successfulNodeTransaction,
1087+
relationshipStatus.transactionId as relationshipTransaction,
1088+
relationshipStatus.committed AS successfulRelationshipTransaction
1089+
----
1090+
// end::subqueries_in_transactions_deadlock_example_2[]
1091+
1092+
.Click to see an example of failed transactions being retried without using `ON ERROR RETRY`
1093+
[%collapsible]
1094+
====
1095+
1096+
.Query retrying failed transactions
1097+
[source, cypher]
1098+
----
1099+
LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/movies.csv' AS row
1100+
CALL (row) {
1101+
MERGE (m:Movie {movieId: row.movieId})
1102+
MERGE (y:Year {year: row.year})
1103+
MERGE (m)-[r:RELEASED_IN]->(y)
1104+
} IN 2 CONCURRENT TRANSACTIONS OF 10 ROWS ON ERROR CONTINUE REPORT STATUS as status
1105+
WITH *
1106+
WHERE status.committed = false
1107+
CALL (row) {
1108+
MERGE (m:Movie {movieId: row.movieId})
1109+
MERGE (y:Year {year: row.year})
1110+
MERGE (m)-[r:RELEASED_IN]->(y)
1111+
} IN 2 CONCURRENT TRANSACTIONS OF 10 ROWS ON ERROR FAIL
1112+
----
1113+
====
10671114
=====
10681115

10691116
[[restrictions]]

0 commit comments

Comments
 (0)