Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Lock in update

-- psql 1
select pg_backend_pid(); -- 4840

-- psql 2
select * from pg_locks where pid = 4840;

pg_locks

-- psql 1
update tb set a = 1;

0. exec_simple_query

exec_simple_query
	start_xact_command
	pg_analyze_and_rewrite_fixedparams
	PortalRun | PortalRunMulti | ProcessQuery
	finish_xact_command

1. vxid lock

start_xact_command
	StartTransaction
		GetNextLocalTransactionId
		VirtualXactLockTableInsert /* Take vxid lock via the fast-path */

2. RowExclusiveLock

pg_analyze_and_rewrite_fixedparams
	parse_analyze_fixedparams | transformTopLevelStmt | transformOptionalSelectInto
		transformStmt | transformUpdateStmt
			setTargetTable | parserOpenTable(pstate, relation, RowExclusiveLock)
				table_openrv_extended | relation_openrv_extended | RangeVarGetRelidExtended
					LockRelationOid /* lmgr.c */
						LockAcquireExtended /* lock.c */

3. transactionid lock

PortalRun | PortalRunMulti | ProcessQuery
	ExecutorRun | standard_ExecutorRun | ExecutePlan | ...
		heap_update
			GetCurrentTransactionId | AssignTransactionId
				XactLockTableInsert
					LockAcquire /* sleep if conflict found, set lock if/when no conflicts.*/
						LockAcquireExtended
							partitionLock = LockHashPartitionLock(hashcode);
							LWLockAcquire(partitionLock, LW_EXCLUSIVE);
							proclock = SetupLockInTable
							LockCheckConflicts
							GrantLock(lock, proclock, lockmode);
							GrantLockLocal(locallock, owner);
							LWLockRelease(partitionLock);
							return LOCKACQUIRE_OK;

4. tuple lock

heap_update
	GetCurrentTransactionId | AssignTransactionId
		XactLockTableInsert
	HeapTupleSatisfiesUpdate
	compute_new_xmax_infomask
	CheckForSerializableConflictIn

	START_CRIT_SECTION();

	PageSetPrunable(page, xid);
	HeapTupleSetHotUpdated(&oldtup); /* Mark the old tuple as HOT-updated */
	HeapTupleSetHeapOnly(heaptup); /* And mark the new tuple as heap-only */
	HeapTupleSetHeapOnly(newtup); /* Mark the caller's copy too, in case different from heaptup */
	RelationPutHeapTuple

	oldtup.t_data->t_ctid = heaptup->t_self; /* record address of new tuple in t_ctid of old one */
	MarkBufferDirty(buffer);

	/* XLOG stuff */
	log_heap_update
	PageSetLSN

	END_CRIT_SECTION();

	return TM_Ok;

5. finish_xact_command

finish_xact_command
	CommitTransactionCommand
		CommitTransaction
			ResourceOwnerRelease
				ResourceOwnerReleaseInternal
					ProcReleaseLocks
						LockReleaseAll
							VirtualXactLockTableCleanup

完整过程

exec_simple_query
	start_xact_command
	    StartTransaction
		    GetNextLocalTransactionId
			VirtualXactLockTableInsert /* Take vxid lock via the fast-path */
	pg_analyze_and_rewrite_fixedparams
	    parse_analyze_fixedparams | transformTopLevelStmt | transformOptionalSelectInto
	        transformStmt | transformUpdateStmt
	            setTargetTable | parserOpenTable(pstate, relation, RowExclusiveLock)
	                table_openrv_extended | relation_openrv_extended | RangeVarGetRelidExtended
	                    LockRelationOid /* Lock a relation given only its OID */
	PortalRun | PortalRunMulti | ProcessQuery
		ExecutorRun | standard_ExecutorRun | ExecutePlan | ...
			heap_update
				GetCurrentTransactionId | AssignTransactionId
					XactLockTableInsert
						LockAcquire /* sleep if conflict found, set lock if/when no conflicts.*/
							LockAcquireExtended
								partitionLock = LockHashPartitionLock(hashcode);
								LWLockAcquire(partitionLock, LW_EXCLUSIVE);
								proclock = SetupLockInTable
								LockCheckConflicts
								GrantLock(lock, proclock, lockmode);
								GrantLockLocal(locallock, owner);
								LWLockRelease(partitionLock);
								return LOCKACQUIRE_OK;
				HeapTupleSatisfiesUpdate
				compute_new_xmax_infomask
				CheckForSerializableConflictIn

				START_CRIT_SECTION();

				PageSetPrunable(page, xid);
				HeapTupleSetHotUpdated(&oldtup); /* Mark the old tuple as HOT-updated */
				HeapTupleSetHeapOnly(heaptup); /* And mark the new tuple as heap-only */
				HeapTupleSetHeapOnly(newtup); /* Mark the caller's copy too, in case different from heaptup */
				RelationPutHeapTuple

				oldtup.t_data->t_ctid = heaptup->t_self; /* record address of new tuple in t_ctid of old one */
				MarkBufferDirty(buffer);

				/* XLOG stuff */
				log_heap_update
				PageSetLSN

				END_CRIT_SECTION();

				return TM_Ok;
	finish_xact_command
		CommitTransactionCommand
			CommitTransaction
				ResourceOwnerRelease
					ResourceOwnerReleaseInternal
						ProcReleaseLocks
							LockReleaseAll
								VirtualXactLockTableCleanup