Skip to content

Commit cfab37d

Browse files
committed
Add advisory lock before creating label in merge operation
1 parent 7ae3081 commit cfab37d

1 file changed

Lines changed: 45 additions & 18 deletions

File tree

src/backend/parser/cypher_clause.c

Lines changed: 45 additions & 18 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"
@@ -7222,19 +7224,36 @@ transform_merge_cypher_edge(cypher_parsestate *cpstate, List **target_list,
72227224
/* check to see if the label exists, create the label entry if it does not. */
72237225
if (edge->label && !label_exists(edge->label, cpstate->graph_oid))
72247226
{
7227+
LOCKTAG tag;
7228+
uint32 key;
72257229
List *parent;
7230+
72267231
/*
7227-
* setup the default edge table as the parent table, that we
7228-
* will inherit from.
7232+
* When merging nodes or edges concurrently, there is label with the same
7233+
* name created by different transactions. Advisory lock is acquired before
7234+
* creating label, and then check if label already exists. Note, the lock is
7235+
* not released until current transaction is over. This can ensure that the
7236+
* new tuple inserted in ag_label catalog table will be sent out, so other
7237+
* transactions can receive it when checking label exists after acquiring lock.
72297238
*/
7230-
rv = get_label_range_var(cpstate->graph_name, cpstate->graph_oid,
7231-
AG_DEFAULT_LABEL_EDGE);
7239+
key = hash_bytes((const unsigned char *)edge->label, strlen(edge->label));
7240+
SET_LOCKTAG_ADVISORY(tag, MyDatabaseId, key, cpstate->graph_oid, 3);
7241+
(void) LockAcquire(&tag, ExclusiveLock, false, false);
7242+
if (!label_exists(edge->label, cpstate->graph_oid))
7243+
{
7244+
/*
7245+
* setup the default edge table as the parent table, that we
7246+
* will inherit from.
7247+
*/
7248+
rv = get_label_range_var(cpstate->graph_name, cpstate->graph_oid,
7249+
AG_DEFAULT_LABEL_EDGE);
72327250

7233-
parent = list_make1(rv);
7251+
parent = list_make1(rv);
72347252

7235-
/* create the label */
7236-
create_label(cpstate->graph_name, edge->label, LABEL_TYPE_EDGE,
7237-
parent);
7253+
/* create the label */
7254+
create_label(cpstate->graph_name, edge->label, LABEL_TYPE_EDGE,
7255+
parent);
7256+
}
72387257
}
72397258

72407259
/* lock the relation of the label */
@@ -7357,20 +7376,28 @@ transform_merge_cypher_node(cypher_parsestate *cpstate, List **target_list,
73577376
/* check to see if the label exists, create the label entry if it does not. */
73587377
if (node->label && !label_exists(node->label, cpstate->graph_oid))
73597378
{
7379+
LOCKTAG tag;
7380+
uint32 key;
73607381
List *parent;
73617382

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);
7383+
key = hash_bytes((const unsigned char *)node->label, strlen(node->label));
7384+
SET_LOCKTAG_ADVISORY(tag, MyDatabaseId, key, cpstate->graph_oid, 3);
7385+
(void) LockAcquire(&tag, ExclusiveLock, false, false);
7386+
if (!label_exists(node->label, cpstate->graph_oid))
7387+
{
7388+
/*
7389+
* setup the default vertex table as the parent table, that we
7390+
* will inherit from.
7391+
*/
7392+
rv = get_label_range_var(cpstate->graph_name, cpstate->graph_oid,
7393+
AG_DEFAULT_LABEL_VERTEX);
73687394

7369-
parent = list_make1(rv);
7395+
parent = list_make1(rv);
73707396

7371-
/* create the label */
7372-
create_label(cpstate->graph_name, node->label, LABEL_TYPE_VERTEX,
7373-
parent);
7397+
/* create the label */
7398+
create_label(cpstate->graph_name, node->label, LABEL_TYPE_VERTEX,
7399+
parent);
7400+
}
73747401
}
73757402

73767403
rel->flags |= CYPHER_TARGET_NODE_FLAG_INSERT;

0 commit comments

Comments
 (0)