diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c
index dc3d8d9817..e9aaf27460 100644
--- a/src/backend/storage/lmgr/lock.c
+++ b/src/backend/storage/lmgr/lock.c
@@ -53,6 +53,8 @@
 /* This configuration variable is used to set the lock table size */
 int			max_locks_per_xact; /* set by guc.c */
 
+bool        xact_lock_chaining;
+
 #define NLOCKENTS() \
 	mul_size(max_locks_per_xact, add_size(MaxBackends, max_prepared_xacts))
 
@@ -919,6 +921,7 @@ LockAcquireExtended(const LOCKTAG *locktag,
 		else
 			return LOCKACQUIRE_NOT_AVAIL;
 	}
+
 	locallock->proclock = proclock;
 	lock = proclock->tag.myLock;
 	locallock->lock = lock;
@@ -949,7 +952,10 @@ LockAcquireExtended(const LOCKTAG *locktag,
 		 * blocking, remove useless table entries and return NOT_AVAIL without
 		 * waiting.
 		 */
-		if (dontWait)
+		if (dontWait || (xact_lock_chaining
+				         && locktag->locktag_type == LOCKTAG_TRANSACTION
+						 && lockmode == ShareLock
+						 && TransactionIdIsValid(lock->lastWaitingXid)))
 		{
 			AbortStrongLockAcquire();
 			if (proclock->holdMask == 0)
@@ -973,12 +979,23 @@ LockAcquireExtended(const LOCKTAG *locktag,
 			LOCK_PRINT("LockAcquire: conditional lock failed", lock, lockmode);
 			Assert((lock->nRequested > 0) && (lock->requested[lockmode] >= 0));
 			Assert(lock->nGranted <= lock->nRequested);
+			if (!dontWait)
+			{
+				SET_LOCKTAG_TRANSACTION(*(LOCKTAG *)locktag, lock->lastWaitingXid);
+				lock->lastWaitingXid = GetCurrentTransactionIdIfAny();
+				LWLockRelease(partitionLock);
+				if (locallock->nLocks == 0)
+					RemoveLocalLock(locallock);
+				return LockAcquire(locktag,
+								   lockmode,
+								   sessionLock,
+								   dontWait);
+			}
 			LWLockRelease(partitionLock);
 			if (locallock->nLocks == 0)
 				RemoveLocalLock(locallock);
 			return LOCKACQUIRE_NOT_AVAIL;
 		}
-
 		/*
 		 * Set bitmask of locks this process already holds on this object.
 		 */
@@ -995,6 +1012,12 @@ LockAcquireExtended(const LOCKTAG *locktag,
 										 locktag->locktag_type,
 										 lockmode);
 
+		if (xact_lock_chaining
+			&& locktag->locktag_type == LOCKTAG_TRANSACTION
+			&& lockmode == ShareLock)
+		{
+			lock->lastWaitingXid = GetCurrentTransactionIdIfAny();
+		}
 		WaitOnLock(locallock, owner);
 
 		TRACE_POSTGRESQL_LOCK_WAIT_DONE(locktag->locktag_field1,
@@ -1098,6 +1121,7 @@ SetupLockInTable(LockMethod lockMethodTable, PGPROC *proc,
 		MemSet(lock->requested, 0, sizeof(int) * MAX_LOCKMODES);
 		MemSet(lock->granted, 0, sizeof(int) * MAX_LOCKMODES);
 		LOCK_PRINT("LockAcquire: new", lock, lockmode);
+		lock->lastWaitingXid = InvalidTransactionId;
 	}
 	else
 	{
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index 87ba67661a..f62909fda3 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -804,7 +804,7 @@ static const unit_conversion time_unit_conversion_table[] =
 /******** option records follow ********/
 
 static struct config_bool ConfigureNamesBool[] =
-{
+{	
 	{
 		{"enable_seqscan", PGC_USERSET, QUERY_TUNING_METHOD,
 			gettext_noop("Enables the planner's use of sequential-scan plans."),
@@ -1705,6 +1705,17 @@ static struct config_bool ConfigureNamesBool[] =
 		NULL, NULL, NULL
 	},
 
+	{
+		{"xact_lock_chaining", PGC_SIGHUP, LOCK_MANAGEMENT,
+			gettext_noop("Minimize lock contention by chaining xact locks"),
+			NULL
+		},
+		&xact_lock_chaining,
+		true,
+		NULL, NULL, NULL
+	},
+
+	
 	/* End-of-list marker */
 	{
 		{NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL, NULL
diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h
index 777da71679..51ad120180 100644
--- a/src/include/storage/lock.h
+++ b/src/include/storage/lock.h
@@ -35,6 +35,7 @@ typedef struct PROC_QUEUE
 
 /* GUC variables */
 extern int	max_locks_per_xact;
+extern bool xact_lock_chaining;
 
 #ifdef LOCK_DEBUG
 extern int	Trace_lock_oidmin;
@@ -295,6 +296,7 @@ typedef struct LOCK
 	int			nRequested;		/* total of requested[] array */
 	int			granted[MAX_LOCKMODES]; /* counts of granted locks */
 	int			nGranted;		/* total of granted[] array */
+	TransactionId lastWaitingXid;
 } LOCK;
 
 #define LOCK_LOCKMETHOD(lock) ((LOCKMETHODID) (lock).tag.locktag_lockmethodid)
