diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 2f1d4af17a..02b157243e 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -793,8 +793,13 @@ ProcArrayApplyRecoveryInfo(RunningTransactions running) /* * Sort the array so that we can add them safely into * KnownAssignedXids. + * + * We have to sort them logically, because in KnownAssignedXidsAdd we + * call TransactionIdFollowsOrEquals and so on. But we know these XIDs + * come from RUNNING_XACTS, which means there are only normal XIDs from + * the same epoch, so this is safe. */ - qsort(xids, nxids, sizeof(TransactionId), xidComparator); + qsort(xids, nxids, sizeof(TransactionId), xidLogicalComparator); /* * Add the sorted snapshot into KnownAssignedXids. The running-xacts diff --git a/src/backend/utils/adt/xid.c b/src/backend/utils/adt/xid.c index 20389aff1d..5a083cecd4 100644 --- a/src/backend/utils/adt/xid.c +++ b/src/backend/utils/adt/xid.c @@ -148,6 +148,32 @@ xidComparator(const void *arg1, const void *arg2) return 0; } +/* + * xidLogicalComparator + * qsort comparison function for XIDs + * + * This is used to compare only XIDs from the same epoch (e.g. for backends + * running at the same time). So there must be only normal XIDs, so there's + * no issue with triangle inequality. + */ +int +xidLogicalComparator(const void *arg1, const void *arg2) +{ + TransactionId xid1 = *(const TransactionId *) arg1; + TransactionId xid2 = *(const TransactionId *) arg2; + + Assert(TransactionIdIsNormal(xid1)); + Assert(TransactionIdIsNormal(xid2)); + + if (TransactionIdPrecedes(xid1, xid2)) + return -1; + + if (TransactionIdPrecedes(xid2, xid1)) + return 1; + + return 0; +} + Datum xid8toxid(PG_FUNCTION_ARGS) { diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h index a5c8772e95..c6ad51d522 100644 --- a/src/include/utils/builtins.h +++ b/src/include/utils/builtins.h @@ -89,6 +89,7 @@ extern void text_to_cstring_buffer(const text *src, char *dst, size_t dst_len); /* xid.c */ extern int xidComparator(const void *arg1, const void *arg2); +extern int xidLogicalComparator(const void *arg1, const void *arg2); /* inet_cidr_ntop.c */ extern char *pg_inet_cidr_ntop(int af, const void *src, int bits,