fix
Offering: openGaussDev More detail: fixed the instantaneous inconsistency of data between index scan and table scan in interval partition table Signed-off-by: <jiang.yu@huawei.com> Match-id-a83cf32c48755b34a0443892b4875cf99e80e00c
This commit is contained in:
@ -6245,14 +6245,21 @@ Oid AddNewIntervalPartition(Relation rel, void* insertTuple)
|
||||
CacheInvalidateRelcache(rel);
|
||||
}
|
||||
|
||||
/*
|
||||
* to avoid dead lock, we should release AccessShareLock on ADD_PARTITION_ACTION
|
||||
* locked by the transaction before aquire AccessExclusiveLock.
|
||||
*/
|
||||
UnlockRelationForAccessIntervalPartTabIfHeld(rel);
|
||||
/* it will accept invalidation messages generated by other sessions in lockRelationForAddIntervalPartition. */
|
||||
lockRelationForAddIntervalPartition(rel);
|
||||
LockRelationForAddIntervalPartition(rel);
|
||||
partitionRoutingForTuple(rel, insertTuple, u_sess->catalog_cxt.route);
|
||||
|
||||
/* if the partition exists, return partition's oid */
|
||||
if (u_sess->catalog_cxt.route->fileExist) {
|
||||
Assert(OidIsValid(u_sess->catalog_cxt.route->partitionId));
|
||||
unLockRelationForAddIntervalPartition(rel);
|
||||
/* we should take AccessShareLock again before release AccessExclusiveLock for consistency. */
|
||||
LockRelationForAccessIntervalPartitionTab(rel);
|
||||
UnlockRelationForAddIntervalPartition(rel);
|
||||
return u_sess->catalog_cxt.route->partitionId;
|
||||
}
|
||||
|
||||
|
||||
@ -1425,3 +1425,41 @@ Oid GetBaseRelOidOfParition(Relation relation)
|
||||
return relation->parentId;
|
||||
}
|
||||
|
||||
/* NB: all operations on ADD_PARTITION_ACTION sequence lock must use TopTransactionResourceOwner. */
|
||||
void LockRelationForAddIntervalPartition(Relation rel)
|
||||
{
|
||||
ResourceOwner currentOwner = t_thrd.utils_cxt.CurrentResourceOwner;
|
||||
t_thrd.utils_cxt.CurrentResourceOwner = t_thrd.utils_cxt.TopTransactionResourceOwner;
|
||||
LockPartition(RelationGetRelid(rel), ADD_PARTITION_ACTION,
|
||||
AccessExclusiveLock, PARTITION_SEQUENCE_LOCK);
|
||||
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
|
||||
}
|
||||
|
||||
void LockRelationForAccessIntervalPartitionTab(Relation rel)
|
||||
{
|
||||
ResourceOwner currentOwner = t_thrd.utils_cxt.CurrentResourceOwner;
|
||||
t_thrd.utils_cxt.CurrentResourceOwner = t_thrd.utils_cxt.TopTransactionResourceOwner;
|
||||
LockPartition(RelationGetRelid(rel), ADD_PARTITION_ACTION,
|
||||
AccessShareLock, PARTITION_SEQUENCE_LOCK);
|
||||
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
|
||||
}
|
||||
|
||||
void UnlockRelationForAccessIntervalPartTabIfHeld(Relation rel)
|
||||
{
|
||||
ResourceOwner currentOwner = t_thrd.utils_cxt.CurrentResourceOwner;
|
||||
t_thrd.utils_cxt.CurrentResourceOwner = t_thrd.utils_cxt.TopTransactionResourceOwner;
|
||||
|
||||
UnlockPartitionSeqIfHeld(RelationGetRelid(rel), ADD_PARTITION_ACTION, AccessShareLock);
|
||||
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
|
||||
}
|
||||
|
||||
void UnlockRelationForAddIntervalPartition(Relation rel)
|
||||
{
|
||||
ResourceOwner currentOwner = t_thrd.utils_cxt.CurrentResourceOwner;
|
||||
t_thrd.utils_cxt.CurrentResourceOwner = t_thrd.utils_cxt.TopTransactionResourceOwner;
|
||||
|
||||
UnlockPartition(RelationGetRelid(rel), ADD_PARTITION_ACTION,
|
||||
AccessExclusiveLock, PARTITION_SEQUENCE_LOCK);
|
||||
t_thrd.utils_cxt.CurrentResourceOwner = currentOwner;
|
||||
}
|
||||
|
||||
|
||||
@ -1134,6 +1134,11 @@ Relation parserOpenTable(ParseState *pstate, const RangeVar *relation, int lockm
|
||||
TryUnlockAllAccounts();
|
||||
}
|
||||
|
||||
if (rel->partMap && rel->partMap->type == PART_TYPE_INTERVAL) {
|
||||
/* take AccessShareLock on ADD_PARTITION_ACTION to avoid concurrency with new partition operations. */
|
||||
LockRelationForAccessIntervalPartitionTab(rel);
|
||||
}
|
||||
|
||||
if (IS_PGXC_COORDINATOR && !IsConnFromCoord()) {
|
||||
if (u_sess->attr.attr_sql.enable_parallel_ddl && !isFirstNode && isCreateView) {
|
||||
UnlockRelation(rel, lockmode);
|
||||
|
||||
@ -1148,6 +1148,15 @@ void UnlockPartitionSeq(Oid relid, uint32 seq, LOCKMODE lockmode)
|
||||
(void)LockRelease(&tag, lockmode, false);
|
||||
}
|
||||
|
||||
void UnlockPartitionSeqIfHeld(Oid relid, uint32 seq, LOCKMODE lockmode)
|
||||
{
|
||||
LOCKTAG tag;
|
||||
|
||||
SetLocktagPartitionSeq(&tag, relid, seq);
|
||||
|
||||
ReleaseLockIfHeld(&tag, lockmode, false);
|
||||
}
|
||||
|
||||
void LockPartitionVacuum(Relation prel, Oid partId, LOCKMODE lockmode)
|
||||
{
|
||||
PartitionIdentifier* partIdentifier = NULL;
|
||||
|
||||
@ -2303,6 +2303,41 @@ void LockReleaseCurrentOwner(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* clear all info of CurrentResourceOwner in locallock and release the lock if no other owners. */
|
||||
void ReleaseLockIfHeld(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock)
|
||||
{
|
||||
LOCKMETHODID lockmethodid = locktag->locktag_lockmethodid;
|
||||
LockMethod lockMethodTable;
|
||||
LOCALLOCKTAG localtag;
|
||||
LOCALLOCK *locallock = NULL;
|
||||
|
||||
CHECK_LOCKMETHODID(lockmethodid);
|
||||
lockMethodTable = LockMethods[lockmethodid];
|
||||
CHECK_LOCKMODE(lockmode, lockMethodTable);
|
||||
|
||||
#ifdef LOCK_DEBUG
|
||||
if (LOCK_DEBUG_ENABLED(locktag))
|
||||
ereport(LOG, (errmsg("ReleaseLockIfHeld: lock [%u,%u] %s", locktag->locktag_field1, locktag->locktag_field2,
|
||||
lockMethodTable->lockModeNames[lockmode])));
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Find the LOCALLOCK entry for this lock and lockmode
|
||||
*/
|
||||
errno_t rc = memset_s(&localtag, sizeof(localtag), 0, sizeof(localtag)); /* must clear padding */
|
||||
securec_check(rc, "", "");
|
||||
localtag.lock = *locktag;
|
||||
localtag.mode = lockmode;
|
||||
|
||||
locallock = (LOCALLOCK *)hash_search(t_thrd.storage_cxt.LockMethodLocalHash, (void *)&localtag, HASH_FIND, NULL);
|
||||
if ((locallock == NULL) || locallock->nLocks <= 0) {
|
||||
ereport(LOG, (errmsg("you don't own a lock of type %s", lockMethodTable->lockModeNames[lockmode])));
|
||||
return;
|
||||
}
|
||||
|
||||
ReleaseLockIfHeld(locallock, sessionLock);
|
||||
}
|
||||
|
||||
/*
|
||||
* ReleaseLockIfHeld
|
||||
* Release any session-level locks on this lockable object if sessionLock
|
||||
|
||||
@ -40,6 +40,7 @@
|
||||
#include "access/htup.h"
|
||||
#include "storage/lock/lock.h"
|
||||
#include "access/heapam.h"
|
||||
#include "storage/lmgr.h"
|
||||
|
||||
#define MAX_PARTITIONKEY_NUM 4
|
||||
#define MAX_PARTITION_NUM 1048575 /* update LEN_PARTITION_PREFIX as well ! */
|
||||
@ -62,16 +63,12 @@
|
||||
#define ADD_PARTITION_ACTION (MAX_PARTITION_NUM + 1)
|
||||
|
||||
/*
|
||||
* We acquire a AccessExclusiveLock on ADD_PARTITION_ACTION before we decide
|
||||
* to add an interval partition to prevent parallel complaints.
|
||||
* We add ADD_PARTITION_ACTION sequence lock to prevent parallel complaints.
|
||||
*/
|
||||
#define lockRelationForAddIntervalPartition(relation) \
|
||||
LockPartition(RelationGetRelid(relation), ADD_PARTITION_ACTION, \
|
||||
AccessExclusiveLock, PARTITION_SEQUENCE_LOCK);
|
||||
|
||||
#define unLockRelationForAddIntervalPartition(relation) \
|
||||
UnlockPartition(RelationGetRelid(relation), ADD_PARTITION_ACTION, \
|
||||
AccessExclusiveLock, PARTITION_SEQUENCE_LOCK);
|
||||
extern void LockRelationForAddIntervalPartition(Relation rel);
|
||||
extern void LockRelationForAccessIntervalPartitionTab(Relation rel);
|
||||
extern void UnlockRelationForAccessIntervalPartTabIfHeld(Relation rel);
|
||||
extern void UnlockRelationForAddIntervalPartition(Relation rel);
|
||||
|
||||
typedef void (*PartitionNameGetPartidCallback) (Oid partitioned_relation, const char *partition_name, Oid partId,
|
||||
Oid oldPartId, char partition_type, void *callback_arg, LOCKMODE callbackobj_lockMode);
|
||||
|
||||
@ -98,6 +98,7 @@ extern void UnlockPartitionOid(Oid relid, uint32 seq, LOCKMODE lockmode);
|
||||
extern void LockPartitionSeq(Oid relid, uint32 seq, LOCKMODE lockmode);
|
||||
extern bool ConditionalLockPartitionSeq(Oid relid, uint32 seq, LOCKMODE lockmode);
|
||||
extern void UnlockPartitionSeq(Oid relid, uint32 seq, LOCKMODE lockmode);
|
||||
extern void UnlockPartitionSeqIfHeld(Oid relid, uint32 seq, LOCKMODE lockmode);
|
||||
|
||||
extern bool ConditionalLockPartitionWithRetry(Relation relation, Oid partitionId, LOCKMODE lockmode);
|
||||
|
||||
|
||||
@ -660,6 +660,7 @@ extern LockAcquireResult LockAcquireExtended(const LOCKTAG *locktag, LOCKMODE lo
|
||||
bool report_memory_error, bool allow_con_update = false, int waitSec = 0);
|
||||
extern void AbortStrongLockAcquire(void);
|
||||
extern bool LockRelease(const LOCKTAG* locktag, LOCKMODE lockmode, bool sessionLock);
|
||||
extern void ReleaseLockIfHeld(const LOCKTAG *locktag, LOCKMODE lockmode, bool sessionLock);
|
||||
extern void LockReleaseAll(LOCKMETHODID lockmethodid, bool allLocks);
|
||||
extern void Check_FastpathBit();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user