未验证 提交 e246d777 编写于 作者: X xiong-gang 提交者: GitHub

Fix a bug when setting DistributedLogShared->oldestXmin

The shared oldestXmin (DistributedLogShared->oldestXmin) may be updated
concurrently. It should be set to a higher value, because a higher xmin
can belong to another distributed log segment, its older segments might
already be truncated.

For Example: txA and txB call DistributedLog_AdvanceOldestXmin concurrently.

```
txA and txB: both hold shared DistributedLogTruncateLock.

txA: set the DistributedLogShared->oldestXmin to XminA. TransactionIdToSegment(XminA) = 0009

txB: set the DistributedLogShared->oldestXmin to XminB. TransactionIdToSegment(XminB) = 0008

txA: truncate segment 0008, 0007...
```

After that, DistributedLogShared->oldestXmin == XminB, it is on removed
segment 0008. Subsequent GetSnapshotData() calls will be failed because SimpleLruReadPage will error out.
Co-authored-by: Ndh-cloud <60729713+dh-cloud@users.noreply.github.com>
上级 a006571b
......@@ -255,7 +255,27 @@ DistributedLog_AdvanceOldestXmin(TransactionId oldestLocalXmin,
LWLockRelease(DistributedLogControlLock);
}
pg_atomic_write_u32((pg_atomic_uint32 *)&DistributedLogShared->oldestXmin, oldestXmin);
/*
* The shared oldestXmin (DistributedLogShared->oldestXmin) may be updated
* concurrently. It should be set to a higher value, because a higher xmin
* can belong to another distributed log segment, its older segments might
* already be truncated.
*/
if (!TransactionIdEquals(oldOldestXmin, oldestXmin))
{
uint32 expected = (uint32)oldOldestXmin;
while (1)
{
if (pg_atomic_compare_exchange_u32((pg_atomic_uint32 *)&DistributedLogShared->oldestXmin,
&expected, (uint32)oldestXmin))
break;
if (TransactionIdPrecedesOrEquals(oldestXmin, expected))
break;
}
}
LWLockRelease(DistributedLogTruncateLock);
if (TransactionIdToSegment(oldOldestXmin) < TransactionIdToSegment(oldestXmin))
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册