From 51fdd906297071eb282b185ae6c15ad3ea63fb23 Mon Sep 17 00:00:00 2001 From: Henrik Nyman Date: Tue, 10 Jun 2025 14:22:52 +0200 Subject: [PATCH 1/7] Add best practice example to subqueries in transactions with deadlocks section --- .../subqueries-in-transactions.adoc | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc index 6d190c139..4bb6d16b5 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -1067,6 +1067,29 @@ The result shows that all transactions are now successful: +-------------------------------------------------+ ---- +However, deadlock resolution and retrying of transactions takes time, so the best practice is to avoid deadlocks in the first place. +This can be done by splitting up the subquery into a data-independent subquery that can be run in parallel with maximum concurrency, +and a data-dependent subquery that is run serially to avoid deadlocks. +In this example nodes and properties are created in a concurrent subquery, while the relationships are then created in a serial subquery. +This way we can benefit from the performance of concurrent transactions while avoiding the deadlocks that slow down the overall performance. + +.Query splitting up the transactional subquery in a data-independent concurrent subquery followed by a data-dependent serial subquery to avoid deadlocks +// tag::subqueries_in_transactions_deadlock_example_2[] +[source, cypher] +---- +LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/movies.csv' AS row +CALL (row) { + MERGE (m:Movie {movieId: row.movieId}) + MERGE (y:Year {year: row.year}) + RETURN m, y +} IN CONCURRENT TRANSACTIONS OF 10 ROWS ON ERROR RETRY FOR 3 SECONDS THEN CONTINUE REPORT STATUS AS nodeStatus +CALL (m, y) { + MERGE (m)-[r:RELEASED_IN]->(y) +} IN TRANSACTIONS OF 10 ROWS ON ERROR RETRY FOR 3 SECONDS THEN CONTINUE REPORT STATUS AS relationshipStatus +RETURN nodeStatus.transactionID as nodeTransaction, nodeStatus.committed AS successfulNodeTransaction, + relationshipStatus.transactionID as relationshipTransaction, relationshipStatus.committed AS successfulRelationshipTransaction +---- +// end::subqueries_in_transactions_deadlock_example_2[] .Click to see an example of failed transactions being retried without using `ON ERROR RETRY` [%collapsible] From 95fc6da205d1b2482385735ece71e7494ab4cbb0 Mon Sep 17 00:00:00 2001 From: Henrik Nyman Date: Wed, 11 Jun 2025 10:47:08 +0200 Subject: [PATCH 2/7] Update modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- .../ROOT/pages/subqueries/subqueries-in-transactions.adoc | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc index 4bb6d16b5..3a14e84e9 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -1067,9 +1067,8 @@ The result shows that all transactions are now successful: +-------------------------------------------------+ ---- -However, deadlock resolution and retrying of transactions takes time, so the best practice is to avoid deadlocks in the first place. -This can be done by splitting up the subquery into a data-independent subquery that can be run in parallel with maximum concurrency, -and a data-dependent subquery that is run serially to avoid deadlocks. +Deadlock resolution and transaction retries are time-consuming, making deadlock avoidance a preferred strategy. +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. In this example nodes and properties are created in a concurrent subquery, while the relationships are then created in a serial subquery. This way we can benefit from the performance of concurrent transactions while avoiding the deadlocks that slow down the overall performance. From da2af2c3eab6eb5631c64418978ab73640bf30af Mon Sep 17 00:00:00 2001 From: Henrik Nyman Date: Wed, 11 Jun 2025 10:47:21 +0200 Subject: [PATCH 3/7] Update modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc index 3a14e84e9..2e2fa78a9 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -1069,8 +1069,8 @@ The result shows that all transactions are now successful: Deadlock resolution and transaction retries are time-consuming, making deadlock avoidance a preferred strategy. 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. -In this example nodes and properties are created in a concurrent subquery, while the relationships are then created in a serial subquery. -This way we can benefit from the performance of concurrent transactions while avoiding the deadlocks that slow down the overall performance. +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. +This method benefits from the performance of concurrent transactions while avoiding deadlocks. .Query splitting up the transactional subquery in a data-independent concurrent subquery followed by a data-dependent serial subquery to avoid deadlocks // tag::subqueries_in_transactions_deadlock_example_2[] From 7974cb8822b5dd22b51ab469619642e30708a1ca Mon Sep 17 00:00:00 2001 From: Henrik Nyman Date: Wed, 11 Jun 2025 10:47:29 +0200 Subject: [PATCH 4/7] Update modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc index 2e2fa78a9..af5a5e1d7 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -1072,7 +1072,8 @@ This can be achieved by dividing a task into two distinct subqueries: a data-ind 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. This method benefits from the performance of concurrent transactions while avoiding deadlocks. -.Query splitting up the transactional subquery in a data-independent concurrent subquery followed by a data-dependent serial subquery to avoid deadlocks +.Avoiding deadlocks by dividing an import task into a data-independent concurrent subquery followed by a data-dependent serial subquery +// tag::subqueries_in_transactions_deadlock_example_2[] // tag::subqueries_in_transactions_deadlock_example_2[] [source, cypher] ---- From 0e513de8f9869a047d9a99d1408380e0842fb755 Mon Sep 17 00:00:00 2001 From: Henrik Nyman Date: Wed, 11 Jun 2025 10:49:23 +0200 Subject: [PATCH 5/7] Update modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Jens Pryce-Åklundh <112686610+JPryce-Aklundh@users.noreply.github.com> --- .../ROOT/pages/subqueries/subqueries-in-transactions.adoc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc index af5a5e1d7..aed1f97ab 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -1086,8 +1086,10 @@ CALL (row) { CALL (m, y) { MERGE (m)-[r:RELEASED_IN]->(y) } IN TRANSACTIONS OF 10 ROWS ON ERROR RETRY FOR 3 SECONDS THEN CONTINUE REPORT STATUS AS relationshipStatus -RETURN nodeStatus.transactionID as nodeTransaction, nodeStatus.committed AS successfulNodeTransaction, - relationshipStatus.transactionID as relationshipTransaction, relationshipStatus.committed AS successfulRelationshipTransaction +RETURN nodeStatus.transactionID as nodeTransaction, + nodeStatus.committed AS successfulNodeTransaction, + relationshipStatus.transactionID as relationshipTransaction, + relationshipStatus.committed AS successfulRelationshipTransaction ---- // end::subqueries_in_transactions_deadlock_example_2[] From 4ecf56ae62f77fc88c12257ca5a7ebc163d938ed Mon Sep 17 00:00:00 2001 From: Henrik Nyman Date: Wed, 11 Jun 2025 11:01:10 +0200 Subject: [PATCH 6/7] Fix typo in property name in example queries --- .../pages/subqueries/subqueries-in-transactions.adoc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc index aed1f97ab..5ebf047df 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -959,7 +959,7 @@ CALL (row) { MERGE (y:Year {year: row.year}) MERGE (m)-[r:RELEASED_IN]->(y) } IN 2 CONCURRENT TRANSACTIONS OF 10 ROWS ON ERROR RETRY FOR 3 SECONDS THEN CONTINUE REPORT STATUS AS status -RETURN status.transactionID as transaction, status.committed AS successfulTransaction +RETURN status.transactionId as transaction, status.committed AS successfulTransaction ---- // end::subqueries_in_transactions_deadlock_example[] @@ -1082,13 +1082,13 @@ CALL (row) { MERGE (m:Movie {movieId: row.movieId}) MERGE (y:Year {year: row.year}) RETURN m, y -} IN CONCURRENT TRANSACTIONS OF 10 ROWS ON ERROR RETRY FOR 3 SECONDS THEN CONTINUE REPORT STATUS AS nodeStatus +} IN CONCURRENT TRANSACTIONS OF 10 ROWS ON ERROR RETRY THEN CONTINUE REPORT STATUS AS nodeStatus CALL (m, y) { MERGE (m)-[r:RELEASED_IN]->(y) -} IN TRANSACTIONS OF 10 ROWS ON ERROR RETRY FOR 3 SECONDS THEN CONTINUE REPORT STATUS AS relationshipStatus -RETURN nodeStatus.transactionID as nodeTransaction, +} IN TRANSACTIONS OF 10 ROWS ON ERROR RETRY THEN CONTINUE REPORT STATUS AS relationshipStatus +RETURN nodeStatus.transactionId as nodeTransaction, nodeStatus.committed AS successfulNodeTransaction, - relationshipStatus.transactionID as relationshipTransaction, + relationshipStatus.transactionId as relationshipTransaction, relationshipStatus.committed AS successfulRelationshipTransaction ---- // end::subqueries_in_transactions_deadlock_example_2[] From 04907c0267cf8d38bf1a1dc1ce7df79d460820af Mon Sep 17 00:00:00 2001 From: Henrik Nyman Date: Wed, 11 Jun 2025 11:09:05 +0200 Subject: [PATCH 7/7] Remove duplicate tag --- modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc index 5ebf047df..d653f9ce5 100644 --- a/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc +++ b/modules/ROOT/pages/subqueries/subqueries-in-transactions.adoc @@ -1074,7 +1074,6 @@ This method benefits from the performance of concurrent transactions while avoid .Avoiding deadlocks by dividing an import task into a data-independent concurrent subquery followed by a data-dependent serial subquery // tag::subqueries_in_transactions_deadlock_example_2[] -// tag::subqueries_in_transactions_deadlock_example_2[] [source, cypher] ---- LOAD CSV WITH HEADERS FROM 'https://data.neo4j.com/importing-cypher/movies.csv' AS row