Skip to content

Commit 76895cc

Browse files
committed
Add advisory lock before creating label in merge/create operation
1 parent 7ae3081 commit 76895cc

File tree

1 file changed

+71
-28
lines changed

1 file changed

+71
-28
lines changed

src/backend/parser/cypher_clause.c

Lines changed: 71 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,14 @@
4242
#include "catalog/ag_graph.h"
4343
#include "catalog/ag_label.h"
4444
#include "commands/label_commands.h"
45+
#include "common/hashfn.h"
4546
#include "parser/cypher_analyze.h"
4647
#include "parser/cypher_clause.h"
4748
#include "parser/cypher_expr.h"
4849
#include "parser/cypher_item.h"
4950
#include "parser/cypher_parse_agg.h"
5051
#include "parser/cypher_transform_entity.h"
52+
#include "storage/lock.h"
5153
#include "utils/ag_cache.h"
5254
#include "utils/ag_func.h"
5355
#include "utils/ag_guc.h"
@@ -5872,15 +5874,23 @@ transform_create_cypher_edge(cypher_parsestate *cpstate, List **target_list,
58725874
/* create the label entry if it does not exist */
58735875
if (!label_exists(edge->label, cpstate->graph_oid))
58745876
{
5877+
LOCKTAG tag;
5878+
uint32 key;
58755879
List *parent;
58765880

5877-
rv = get_label_range_var(cpstate->graph_name, cpstate->graph_oid,
5878-
AG_DEFAULT_LABEL_EDGE);
5881+
key = hash_bytes((const unsigned char *)edge->label, strlen(edge->label));
5882+
SET_LOCKTAG_ADVISORY(tag, MyDatabaseId, key, cpstate->graph_oid, 3);
5883+
(void) LockAcquire(&tag, ExclusiveLock, false, false);
5884+
if (!label_exists(edge->label, cpstate->graph_oid))
5885+
{
5886+
rv = get_label_range_var(cpstate->graph_name, cpstate->graph_oid,
5887+
AG_DEFAULT_LABEL_EDGE);
58795888

5880-
parent = list_make1(rv);
5889+
parent = list_make1(rv);
58815890

5882-
create_label(cpstate->graph_name, edge->label, LABEL_TYPE_EDGE,
5883-
parent);
5891+
create_label(cpstate->graph_name, edge->label, LABEL_TYPE_EDGE,
5892+
parent);
5893+
}
58845894
}
58855895

58865896
/* lock the relation of the label */
@@ -6149,15 +6159,23 @@ transform_create_cypher_new_node(cypher_parsestate *cpstate,
61496159
/* create the label entry if it does not exist */
61506160
if (!label_exists(node->label, cpstate->graph_oid))
61516161
{
6162+
LOCKTAG tag;
6163+
uint32 key;
61526164
List *parent;
61536165

6154-
rv = get_label_range_var(cpstate->graph_name, cpstate->graph_oid,
6155-
AG_DEFAULT_LABEL_VERTEX);
6166+
key = hash_bytes((const unsigned char *)node->label, strlen(node->label));
6167+
SET_LOCKTAG_ADVISORY(tag, MyDatabaseId, key, cpstate->graph_oid, 3);
6168+
(void) LockAcquire(&tag, ExclusiveLock, false, false);
6169+
if (!label_exists(node->label, cpstate->graph_oid))
6170+
{
6171+
rv = get_label_range_var(cpstate->graph_name, cpstate->graph_oid,
6172+
AG_DEFAULT_LABEL_VERTEX);
61566173

6157-
parent = list_make1(rv);
6174+
parent = list_make1(rv);
61586175

6159-
create_label(cpstate->graph_name, node->label, LABEL_TYPE_VERTEX,
6160-
parent);
6176+
create_label(cpstate->graph_name, node->label, LABEL_TYPE_VERTEX,
6177+
parent);
6178+
}
61616179
}
61626180

61636181
rel->flags = CYPHER_TARGET_NODE_FLAG_INSERT;
@@ -7222,19 +7240,36 @@ transform_merge_cypher_edge(cypher_parsestate *cpstate, List **target_list,
72227240
/* check to see if the label exists, create the label entry if it does not. */
72237241
if (edge->label && !label_exists(edge->label, cpstate->graph_oid))
72247242
{
7243+
LOCKTAG tag;
7244+
uint32 key;
72257245
List *parent;
7246+
72267247
/*
7227-
* setup the default edge table as the parent table, that we
7228-
* will inherit from.
7248+
* When merging nodes or edges concurrently, there is label with the same
7249+
* name created by different transactions. Advisory lock is acquired before
7250+
* creating label, and then check if label already exists. Note, the lock is
7251+
* not released until current transaction is over. This can ensure that the
7252+
* new tuple inserted in ag_label catalog table will be sent out, so other
7253+
* transactions can receive it when checking label exists after acquiring lock.
72297254
*/
7230-
rv = get_label_range_var(cpstate->graph_name, cpstate->graph_oid,
7231-
AG_DEFAULT_LABEL_EDGE);
7255+
key = hash_bytes((const unsigned char *)edge->label, strlen(edge->label));
7256+
SET_LOCKTAG_ADVISORY(tag, MyDatabaseId, key, cpstate->graph_oid, 3);
7257+
(void) LockAcquire(&tag, ExclusiveLock, false, false);
7258+
if (!label_exists(edge->label, cpstate->graph_oid))
7259+
{
7260+
/*
7261+
* setup the default edge table as the parent table, that we
7262+
* will inherit from.
7263+
*/
7264+
rv = get_label_range_var(cpstate->graph_name, cpstate->graph_oid,
7265+
AG_DEFAULT_LABEL_EDGE);
72327266

7233-
parent = list_make1(rv);
7267+
parent = list_make1(rv);
72347268

7235-
/* create the label */
7236-
create_label(cpstate->graph_name, edge->label, LABEL_TYPE_EDGE,
7237-
parent);
7269+
/* create the label */
7270+
create_label(cpstate->graph_name, edge->label, LABEL_TYPE_EDGE,
7271+
parent);
7272+
}
72387273
}
72397274

72407275
/* lock the relation of the label */
@@ -7357,20 +7392,28 @@ transform_merge_cypher_node(cypher_parsestate *cpstate, List **target_list,
73577392
/* check to see if the label exists, create the label entry if it does not. */
73587393
if (node->label && !label_exists(node->label, cpstate->graph_oid))
73597394
{
7395+
LOCKTAG tag;
7396+
uint32 key;
73607397
List *parent;
73617398

7362-
/*
7363-
* setup the default vertex table as the parent table, that we
7364-
* will inherit from.
7365-
*/
7366-
rv = get_label_range_var(cpstate->graph_name, cpstate->graph_oid,
7367-
AG_DEFAULT_LABEL_VERTEX);
7399+
key = hash_bytes((const unsigned char *)node->label, strlen(node->label));
7400+
SET_LOCKTAG_ADVISORY(tag, MyDatabaseId, key, cpstate->graph_oid, 3);
7401+
(void) LockAcquire(&tag, ExclusiveLock, false, false);
7402+
if (!label_exists(node->label, cpstate->graph_oid))
7403+
{
7404+
/*
7405+
* setup the default vertex table as the parent table, that we
7406+
* will inherit from.
7407+
*/
7408+
rv = get_label_range_var(cpstate->graph_name, cpstate->graph_oid,
7409+
AG_DEFAULT_LABEL_VERTEX);
73687410

7369-
parent = list_make1(rv);
7411+
parent = list_make1(rv);
73707412

7371-
/* create the label */
7372-
create_label(cpstate->graph_name, node->label, LABEL_TYPE_VERTEX,
7373-
parent);
7413+
/* create the label */
7414+
create_label(cpstate->graph_name, node->label, LABEL_TYPE_VERTEX,
7415+
parent);
7416+
}
73747417
}
73757418

73767419
rel->flags |= CYPHER_TARGET_NODE_FLAG_INSERT;

0 commit comments

Comments
 (0)