fix several bugs for enhance tuple lock

This commit is contained in:
chenxiaobin19 2022-01-20 19:48:15 +08:00
parent 23ddd1ca38
commit d183e96ae7
8 changed files with 63 additions and 32 deletions

View File

@ -4239,6 +4239,14 @@ static void transformLockingClause(ParseState* pstate, Query* qry, LockingClause
/* make a clause we can pass down to subqueries to select all rels */
allrels = makeNode(LockingClause);
allrels->lockedRels = NIL; /* indicates all rels */
/* The strength of lc is not set at old version and distribution. Set it according to forUpdate. */
if (t_thrd.proc->workingVersionNum < ENHANCED_TUPLE_LOCK_VERSION_NUM
#ifdef ENABLE_MULTIPLE_NODES
|| true
#endif
) {
lc->strength = lc->forUpdate ? LCS_FORUPDATE : LCS_FORSHARE;
}
allrels->strength = lc->strength;
allrels->noWait = lc->noWait;
@ -4404,6 +4412,7 @@ void applyLockingClause(Query* qry, Index rtindex, LockClauseStrength strength,
* And of course pushedDown becomes false if any clause is explicit.
*/
rc->strength = Max(rc->strength, strength);
rc->forUpdate = rc->strength == LCS_FORUPDATE;
rc->noWait = rc->noWait || noWait;
rc->pushedDown = rc->pushedDown && pushedDown;
return;
@ -4413,6 +4422,7 @@ void applyLockingClause(Query* qry, Index rtindex, LockClauseStrength strength,
rc = makeNode(RowMarkClause);
rc->rti = rtindex;
rc->strength = strength;
rc->forUpdate = strength == LCS_FORUPDATE;
rc->noWait = noWait;
rc->pushedDown = pushedDown;
qry->rowMarks = lappend(qry->rowMarks, rc);

View File

@ -212,6 +212,19 @@ Datum RI_FKey_noaction(PG_FUNCTION_ARGS);
template <bool is_del>
Datum RI_FKey_setdefault(PG_FUNCTION_ARGS);
/*
* Since tuple lock has been enhanced, KeyShareLock is needed instead
* of ShareLock for foreign key. But ustore table still acquires ShareLock.
*/
static inline bool IsShareLockForForeignKey(Relation relation)
{
#ifdef ENABLE_MULTIPLE_NODES
return true;
#else
return RelationIsUstoreFormat(relation);
#endif
}
/* ----------
* RI_FKey_check -
*
@ -321,13 +334,10 @@ static Datum RI_FKey_check(PG_FUNCTION_ARGS)
* ----------
*/
quoteRelationName(pkrelname, pk_rel);
#ifdef ENABLE_MULTIPLE_NODES
rc = snprintf_s(
querystr, sizeof(querystr), sizeof(querystr) - 1, "SELECT 1 FROM ONLY %s x FOR SHARE OF x", pkrelname);
#else
rc = snprintf_s(querystr, sizeof(querystr), sizeof(querystr) - 1,
IsShareLockForForeignKey(trigdata->tg_relation) ? "SELECT 1 FROM ONLY %s x FOR SHARE OF x" :
"SELECT 1 FROM ONLY %s x FOR KEY SHARE OF x", pkrelname);
#endif
securec_check_ss(rc, "\0", "\0");
/* Prepare and save the plan */
@ -465,11 +475,9 @@ static Datum RI_FKey_check(PG_FUNCTION_ARGS)
querysep = "AND";
queryoids[i] = fk_type;
}
#ifdef ENABLE_MULTIPLE_NODES
appendStringInfo(&querybuf, " FOR SHARE OF x");
#else
appendStringInfo(&querybuf, " FOR KEY SHARE OF x");
#endif
appendStringInfo(&querybuf, IsShareLockForForeignKey(trigdata->tg_relation) ? " FOR SHARE OF x" :
" FOR KEY SHARE OF x");
/* Prepare and save the plan */
qplan = ri_PlanCheck(querybuf.data, riinfo.nkeys, queryoids, &qkey, fk_rel, pk_rel, true);
@ -617,12 +625,8 @@ static bool ri_Check_Pk_Match(Relation pk_rel, Relation fk_rel, HeapTuple old_ro
querysep = "AND";
queryoids[i] = pk_type;
}
#ifdef ENABLE_MULTIPLE_NODES
appendStringInfo(&querybuf, " FOR SHARE OF x");
#else
appendStringInfo(&querybuf, " FOR KEY SHARE OF x");
#endif
appendStringInfo(&querybuf, IsShareLockForForeignKey(pk_rel) ? " FOR SHARE OF x" : " FOR KEY SHARE OF x");
/* Prepare and save the plan */
qplan = ri_PlanCheck(querybuf.data, riinfo->nkeys, queryoids, &qkey, fk_rel, pk_rel, true);
@ -793,11 +797,9 @@ Datum RI_FKey_noaction(PG_FUNCTION_ARGS)
querysep = "AND";
queryoids[i] = pk_type;
}
#ifdef ENABLE_MULTIPLE_NODES
appendStringInfo(&querybuf, " FOR SHARE OF x");
#else
appendStringInfo(&querybuf, " FOR KEY SHARE OF x");
#endif
appendStringInfo(&querybuf, IsShareLockForForeignKey(trigdata->tg_relation) ?
" FOR SHARE OF x" : " FOR KEY SHARE OF x");
/* Prepare and save the plan */
qplan = ri_PlanCheck(querybuf.data, riinfo.nkeys, queryoids, &qkey, fk_rel, pk_rel, true);
@ -1332,11 +1334,9 @@ Datum RI_FKey_restrict(PG_FUNCTION_ARGS)
querysep = "AND";
queryoids[i] = pk_type;
}
#ifdef ENABLE_MULTIPLE_NODES
appendStringInfo(&querybuf, " FOR SHARE OF x");
#else
appendStringInfo(&querybuf, " FOR KEY SHARE OF x");
#endif
appendStringInfo(&querybuf, IsShareLockForForeignKey(trigdata->tg_relation) ?
" FOR SHARE OF x" : " FOR KEY SHARE OF x");
/* Prepare and save the plan */
qplan = ri_PlanCheck(querybuf.data, riinfo.nkeys, queryoids, &qkey, fk_rel, pk_rel, true);

View File

@ -4908,6 +4908,14 @@ static void preprocess_rowmarks(PlannerInfo* root)
newrc = makeNode(PlanRowMark);
newrc->rti = newrc->prti = rc->rti;
newrc->rowmarkId = ++(root->glob->lastRowMarkId);
/* The strength of lc is not set at old version and distribution. Set it according to forUpdate. */
if (t_thrd.proc->workingVersionNum < ENHANCED_TUPLE_LOCK_VERSION_NUM
#ifdef ENABLE_MULTIPLE_NODES
|| true
#endif
) {
rc->strength = rc->forUpdate ? LCS_FORUPDATE : LCS_FORSHARE;
}
switch (rc->strength) {
case LCS_FORUPDATE:
newrc->markType = ROW_MARK_EXCLUSIVE;

View File

@ -2892,7 +2892,7 @@ bool is_contain_crossbucket(List *defList)
bool is_cstore_option(char relkind, Datum reloptions)
{
StdRdOptions* std_opt = (StdRdOptions*)heap_reloptions(relkind, reloptions, false);
bool result = std_opt == NULL && pg_strcasecmp(ORIENTATION_COLUMN,
bool result = std_opt != NULL && pg_strcasecmp(ORIENTATION_COLUMN,
StdRdOptionsGetStringData(std_opt, orientation, ORIENTATION_ROW)) == 0;
pfree_ext(std_opt);
return result;

View File

@ -5174,8 +5174,14 @@ l2:
* If the tuple we're updating is locked, we need to preserve the locking
* info in the old tuple's Xmax. Prepare a new Xmax value for this.
*/
ComputeNewXmaxInfomask(HeapTupleGetRawXmax(&oldtup), oldtup.t_data->t_infomask, oldtup.t_data->t_infomask2,
xid, mode, true, &xmax_old_tuple, &infomask_old_tuple, &infomask2_old_tuple);
if (t_thrd.proc->workingVersionNum >= ENHANCED_TUPLE_LOCK_VERSION_NUM) {
ComputeNewXmaxInfomask(HeapTupleGetRawXmax(&oldtup), oldtup.t_data->t_infomask, oldtup.t_data->t_infomask2,
xid, mode, true, &xmax_old_tuple, &infomask_old_tuple, &infomask2_old_tuple);
} else {
xmax_old_tuple = xid;
infomask_old_tuple = 0;
infomask2_old_tuple = HEAP_KEYS_UPDATED;
}
/* And also prepare an Xmax value for the new copy of the tuple */
if ((oldtup.t_data->t_infomask & HEAP_XMAX_INVALID) || (checked_lockers && !locker_remains)) {
@ -5199,7 +5205,7 @@ l2:
if (t_thrd.proc->workingVersionNum < ENHANCED_TUPLE_LOCK_VERSION_NUM) {
/* if the only locker of old tuple is ourselves, xmax_new_tuple may be xid and it would be valid */
if (TransactionIdIsValid(xmax_new_tuple) || !TransactionIdEquals(xmax_old_tuple, xid)) {
ereport(WARNING, (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
ereport(DEBUG2, (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
errmsg("New MultiXact feature isn't support in this version. Please upgrade to version: %d",
ENHANCED_TUPLE_LOCK_VERSION_NUM)));
}

View File

@ -1606,6 +1606,10 @@ TM_Result UHeapamTupleUpdate(Relation relation, Relation parentRelation, ItemPoi
TM_Result result = UHeapUpdate(relation, parentRelation, otid, (UHeapTuple)newtup, cid, crosscheck, snapshot, wait,
oldslot, tmfd, update_indexes, modifiedIdxAttrs, allow_inplace_update);
/* the LockTupleMode of ustore-updating must be LockTupleExclusive now */
if (mode != NULL) {
*mode = LockTupleExclusive;
}
return result;
}

View File

@ -680,9 +680,8 @@ static MultiXactId CreateMultiXactId(int nmembers, MultiXactMember *members)
for (int i = 0; i < nmembers; ++i) {
if (members[i].status != MultiXactStatusForShare) {
ereport(ERROR, (errcode(ERRCODE_INVALID_TRANSACTION_STATE),
errmsg("New MultiXact feature isn't support in this version. Please upgrade to version: %d"
"i: %d, members[i].status: %d",
ENHANCED_TUPLE_LOCK_VERSION_NUM, i, members[i].status)));
errmsg("New MultiXact feature isn't support in this version. Please upgrade to version: %d",
ENHANCED_TUPLE_LOCK_VERSION_NUM)));
}
}
}

View File

@ -1630,6 +1630,10 @@ static void UHeapExecuteLockTuple(Relation relation, Buffer buffer, UHeapTuple u
TransactionId xidOnTup = InvalidTransactionId;
TransactionId curxid = InvalidTransactionId;
if (mode == LockTupleKeyShare || mode == LockTupleNoKeyExclusive) {
ereport(ERROR, (errmsg("For Key Share and For No Key Update is not support for ustore.")));
}
if (mode == LockTupleExclusive) {
xid = GetCurrentTransactionId();
} else if (mode == LockTupleShared) {