Merge pull request #5480 from citusdata/velioglu/make_object_lock_explicit

Make object locking explicit while adding dependencies
change_order_master
Burak Velioglu 2021-11-22 15:56:09 +03:00 committed by GitHub
commit 8d7c497d68
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 65 additions and 0 deletions

View File

@ -28,6 +28,7 @@
typedef bool (*AddressPredicate)(const ObjectAddress *);
static int ObjectAddressComparator(const void *a, const void *b);
static List * GetDependencyCreateDDLCommands(const ObjectAddress *dependency);
static List * FilterObjectAddressListByPredicate(List *objectAddressList,
AddressPredicate predicate);
@ -88,6 +89,21 @@ EnsureDependenciesExistOnAllNodes(const ObjectAddress *target)
*/
List *workerNodeList = ActivePrimaryNonCoordinatorNodeList(RowShareLock);
/*
* Lock dependent objects explicitly to make sure same DDL command won't be sent
* multiple times from parallel sessions.
*
* Sort dependencies that will be created on workers to not to have any deadlock
* issue if different sessions are creating different objects.
*/
List *addressSortedDependencies = SortList(dependenciesWithCommands,
ObjectAddressComparator);
foreach_ptr(dependency, addressSortedDependencies)
{
LockDatabaseObject(dependency->classId, dependency->objectId,
dependency->objectSubId, ExclusiveLock);
}
/*
* right after we acquired the lock we mark our objects as distributed, these changes
* will not become visible before we have successfully created all the objects on our
@ -126,6 +142,55 @@ EnsureDependenciesExistOnAllNodes(const ObjectAddress *target)
}
/*
* Copied from PG object_address_comparator function to compare ObjectAddresses.
*/
static int
ObjectAddressComparator(const void *a, const void *b)
{
const ObjectAddress *obja = (const ObjectAddress *) a;
const ObjectAddress *objb = (const ObjectAddress *) b;
/*
* Primary sort key is OID descending.
*/
if (obja->objectId > objb->objectId)
{
return -1;
}
if (obja->objectId < objb->objectId)
{
return 1;
}
/*
* Next sort on catalog ID, in case identical OIDs appear in different
* catalogs. Sort direction is pretty arbitrary here.
*/
if (obja->classId < objb->classId)
{
return -1;
}
if (obja->classId > objb->classId)
{
return 1;
}
/*
* Last, sort on object subId.
*/
if ((unsigned int) obja->objectSubId < (unsigned int) objb->objectSubId)
{
return -1;
}
if ((unsigned int) obja->objectSubId > (unsigned int) objb->objectSubId)
{
return 1;
}
return 0;
}
/*
* GetDistributableDependenciesForObject finds all the dependencies that Citus
* can distribute and returns those dependencies regardless of their existency