复制冲突发生
备库起事务在读,主库truncate表,备库复制冲突发生:
代码语言:javascript复制-- 发生前, 5833是startup,7444是持锁的后台进程。后台进程拿表的读锁和虚拟事务ID的ex锁。
postgres=# select * from pg_locks where pid != pg_backend_pid();
locktype | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction | pid | mode | granted | fastpath
------------ ---------- ---------- ------ ------- ------------ --------------- --------- ------- ---------- -------------------- ------ ----------------- --------- ----------
relation | 13212 | 102189 | | | | | | | | 2/8 | 7444 | AccessShareLock | t | t
virtualxid | | | | | 2/8 | | | | | 2/8 | 7444 | ExclusiveLock | t | t
virtualxid | | | | | 1/1 | | | | | 1/0 | 5833 | ExclusiveLock | t | t
-- 发生后,stantup进程需要拿8锁AccessExclusiveLock,拿不到开始等锁。
postgres=# select * from pg_locks where pid != pg_backend_pid();
locktype | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction | pid | mode | granted | fastpath
------------ ---------- ---------- ------ ------- ------------ --------------- --------- ------- ---------- -------------------- ------ --------------------- --------- ----------
virtualxid | | | | | 2/8 | | | | | 2/8 | 7444 | ExclusiveLock | t | t
virtualxid | | | | | 1/1 | | | | | 1/0 | 5833 | ExclusiveLock | t | t
relation | 13212 | 102189 | | | | | | | | 2/8 | 7444 | AccessShareLock | t | f
relation | 13212 | 102189 | | | | | | | | 1/0 | 5833 | AccessExclusiveLock | f | f
startup等待堆栈
代码语言:javascript复制StartupProcessMain
StartupXLOG
standby_redo
StandbyAcquireAccessExclusiveLock
LockAcquire
LockAcquireExtended
WaitOnLock
ProcSleep
ResolveRecoveryConflictWithLock
ProcWaitForSignal
startup超时唤醒堆栈
等待时间超过max_standby_streaming_delay后,跳出ProcWaitForSignal重新进入ResolveRecoveryConflictWithLock,走第一个分支
代码语言:javascript复制ProcSleep
ResolveRecoveryConflictWithLock
if (GetCurrentTimestamp() >= ltime && ltime != 0)
VirtualTransactionId *backends;
backends = GetLockConflicts(&locktag, AccessExclusiveLock);
ResolveRecoveryConflictWithVirtualXIDs(backends, PROCSIG_RECOVERY_CONFLICT_LOCK, false)
VirtualTransactionId是什么?
代码语言:javascript复制typedef struct
{
BackendId backendId; /* backendId from PGPROC */
LocalTransactionId localTransactionId; /* lxid from PGPROC */
} VirtualTransactionId;
backendid和当前会话私有的一个事务ID(类似事务ID自增,从0开始,当前会话结束后清空)
GetLockConflicts怎么拿到和传入locktag冲突的vxid?
代码语言:javascript复制VirtualTransactionId *
GetLockConflicts(const LOCKTAG *locktag, LOCKMODE lockmode)
{ ... }
(gdb) p *locktag //其中 13212 是库oid 102189 是表oid
$5 = {locktag_field1 = 13212, locktag_field2 = 102189, locktag_field3 = 0, locktag_field4 = 0, locktag_type = 0 '