public inbox for [email protected]
help / color / mirror / Atom feedFrom: Yushi Ogiwara <[email protected]>
To: Masahiko Sawada <[email protected]>
Cc: Pgsql Hackers <[email protected]>
Subject: Re: Fix for consume_xids advancing XIDs incorrectly
Date: Wed, 16 Oct 2024 14:06:14 +0900
Message-ID: <[email protected]> (raw)
In-Reply-To: <CAD21AoATuDuqSr=V3vCSbHbOg6g9zKL61EEbe4ZPG3xOUa0Pcw@mail.gmail.com>
References: <[email protected]>
<CAD21AoATuDuqSr=V3vCSbHbOg6g9zKL61EEbe4ZPG3xOUa0Pcw@mail.gmail.com>
Hi,
Thank you for your comment.
Regarding the first patch, I believe it works correctly when
consume_xids(1) is called. This is because the lastxid variable in the
consume_xids_common function is initialized as lastxid =
ReadNextFullTransactionId(), where the ReadNextFullTransactionId
function returns the (current XID) + 1.
Separately, I found that consume_xids(0) does not behave as expected.
Below is an example:
postgres=# select txid_current();
txid_current
--------------
45496
(1 row)
postgres=# select consume_xids(0);
consume_xids
--------------
45497
(1 row)
postgres=# select consume_xids(0);
consume_xids
--------------
45497
(1 row)
In the example, the argument to consume_xids is 0, meaning it should not
consume any XIDs. However, the first invocation of consume_xids(0) looks
like unexpectedly consuming 1 XID though it's not consuming actually.
This happens because consume_xids(0) returns the value from
ReadNextFullTransactionId.
I have updated the patch (skip.diff, attached to this e-mail) to address
this issue. Now, when consume_xids(0) is called, it returns
ReadNextFullTransactionId().value - 1, ensuring no XID is consumed as
shown below:
postgres=# select txid_current();
txid_current
--------------
45498
(1 row)
postgres=# select consume_xids(0);
consume_xids
--------------
45498
(1 row)
Regards,
Yushi
On 2024-10-16 07:26, Masahiko Sawada wrote:
> Hi,
>
> Thank you for the report.
>
> On Mon, Oct 14, 2024 at 6:51 PM Yushi Ogiwara
> <[email protected]> wrote:
>>
>> Hi,
>>
>> I found that the consume_xids function incorrectly advances XIDs as
>> shown:
>>
>> postgres=# select txid_current();
>> txid_current
>> --------------
>> 746
>> (1 row)
>>
>> postgres=# select consume_xids('100');
>> consume_xids
>> --------------
>> 847
>> (1 row)
>>
>> In the example, the consume_xids function consumes 100 XIDs when XID =
>> 746, so the desired outcome from consume_xids should be 746 + 100 =
>> 846,
>> which differs from the actual outcome, 847.
>>
>> Behavior inside a transaction block:
>>
>> postgres=# select txid_current();
>> txid_current
>> --------------
>> 1410
>> (1 row)
>>
>> postgres=# begin;
>> BEGIN
>> postgres=*# select consume_xids('100');
>> consume_xids
>> --------------
>> 1511
>> (1 row)
>> postgres=*# select consume_xids('100');
>> consume_xids
>> --------------
>> 1521
>> (1 row)
>>
>> Here, the first call inside the transaction block consumes 100+1 XIDs
>> (incorrect), while the second call consumes exactly 100 XIDs (as
>> expected)
>>
>> Summary:
>>
>> The function performs incorrectly when:
>> - Outside of a transaction block
>> - The first call inside a transaction block
>> But works correctly when:
>> - After the second call inside a transaction block
>>
>> The issue arises because consume_xids does not correctly count the
>> consumed XIDs when it calls the GetTopTransactionId function, which
>> allocates a new XID when none has been assigned.
>
> I agree with your analysis.
>
> I have one comment on the patch:
>
> - (void) GetTopTransactionId();
> + if(!FullTransactionIdIsValid(GetTopFullTransactionIdIfAny()))
> + {
> + (void) GetTopTransactionId();
> + consumed++;
> + }
>
> If we count this case as consumed too, I think we need to set the
> returned value of GetTopTranasctionId() to lastxid. Because otherwise,
> the return value when passing 1 to the function would be the latest
> XID at the time but not the last XID consumed by the function. Passing
> 1 to this function is very unrealistic case, though.
>
> Regards,
Attachments:
[text/x-diff] skip.diff (946B, ../[email protected]/2-skip.diff)
download | inline diff:
diff --git a/src/test/modules/xid_wraparound/xid_wraparound.c b/src/test/modules/xid_wraparound/xid_wraparound.c
index dce81c0c6d..4b9788d2d9 100644
--- a/src/test/modules/xid_wraparound/xid_wraparound.c
+++ b/src/test/modules/xid_wraparound/xid_wraparound.c
@@ -38,7 +38,7 @@ consume_xids(PG_FUNCTION_ARGS)
elog(ERROR, "invalid nxids argument: %lld", (long long) nxids);
if (nxids == 0)
- lastxid = ReadNextFullTransactionId();
+ lastxid = FullTransactionIdFromU64(ReadNextFullTransactionId().value - 1);
else
lastxid = consume_xids_common(InvalidFullTransactionId, (uint64) nxids);
@@ -89,7 +89,11 @@ consume_xids_common(FullTransactionId untilxid, uint64 nxids)
* the cache overflows, but beyond that, we don't keep track of the
* consumed XIDs.
*/
- (void) GetTopTransactionId();
+ if(!FullTransactionIdIsValid(GetTopFullTransactionIdIfAny()))
+ {
+ (void) GetTopTransactionId();
+ consumed++;
+ }
for (;;)
{
view thread (4+ messages) latest in thread
reply
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: [email protected]
Cc: [email protected], [email protected]
Subject: Re: Fix for consume_xids advancing XIDs incorrectly
In-Reply-To: <[email protected]>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox