mirror of
https://github.com/postgres/postgres.git
synced 2025-05-17 00:03:56 -04:00
Rework redundant code in subtrans.c
When this code was written the duplicity didn't matter, but with all the SLRU-bank stuff we just added, it has become excessive. Turn it into a simpler loop with no code duplication. Also add a test so that this code becomes covered. Discussion: https://postgr.es/m/202403041517.3a35jw53os65@alvherre.pgsql
This commit is contained in:
parent
030e10ff1a
commit
1a2654b32b
@ -311,7 +311,7 @@ StartupSUBTRANS(TransactionId oldestActiveXID)
|
|||||||
FullTransactionId nextXid;
|
FullTransactionId nextXid;
|
||||||
int64 startPage;
|
int64 startPage;
|
||||||
int64 endPage;
|
int64 endPage;
|
||||||
LWLock *prevlock;
|
LWLock *prevlock = NULL;
|
||||||
LWLock *lock;
|
LWLock *lock;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -324,42 +324,27 @@ StartupSUBTRANS(TransactionId oldestActiveXID)
|
|||||||
nextXid = TransamVariables->nextXid;
|
nextXid = TransamVariables->nextXid;
|
||||||
endPage = TransactionIdToPage(XidFromFullTransactionId(nextXid));
|
endPage = TransactionIdToPage(XidFromFullTransactionId(nextXid));
|
||||||
|
|
||||||
prevlock = SimpleLruGetBankLock(SubTransCtl, startPage);
|
for (;;)
|
||||||
LWLockAcquire(prevlock, LW_EXCLUSIVE);
|
|
||||||
while (startPage != endPage)
|
|
||||||
{
|
{
|
||||||
lock = SimpleLruGetBankLock(SubTransCtl, startPage);
|
lock = SimpleLruGetBankLock(SubTransCtl, startPage);
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if we need to acquire the lock on the new bank then release
|
|
||||||
* the lock on the old bank and acquire on the new bank.
|
|
||||||
*/
|
|
||||||
if (prevlock != lock)
|
if (prevlock != lock)
|
||||||
{
|
{
|
||||||
LWLockRelease(prevlock);
|
if (prevlock)
|
||||||
|
LWLockRelease(prevlock);
|
||||||
LWLockAcquire(lock, LW_EXCLUSIVE);
|
LWLockAcquire(lock, LW_EXCLUSIVE);
|
||||||
prevlock = lock;
|
prevlock = lock;
|
||||||
}
|
}
|
||||||
|
|
||||||
(void) ZeroSUBTRANSPage(startPage);
|
(void) ZeroSUBTRANSPage(startPage);
|
||||||
|
if (startPage == endPage)
|
||||||
|
break;
|
||||||
|
|
||||||
startPage++;
|
startPage++;
|
||||||
/* must account for wraparound */
|
/* must account for wraparound */
|
||||||
if (startPage > TransactionIdToPage(MaxTransactionId))
|
if (startPage > TransactionIdToPage(MaxTransactionId))
|
||||||
startPage = 0;
|
startPage = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock = SimpleLruGetBankLock(SubTransCtl, startPage);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if we need to acquire the lock on the new bank then release the
|
|
||||||
* lock on the old bank and acquire on the new bank.
|
|
||||||
*/
|
|
||||||
if (prevlock != lock)
|
|
||||||
{
|
|
||||||
LWLockRelease(prevlock);
|
|
||||||
LWLockAcquire(lock, LW_EXCLUSIVE);
|
|
||||||
}
|
|
||||||
(void) ZeroSUBTRANSPage(startPage);
|
|
||||||
LWLockRelease(lock);
|
LWLockRelease(lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,6 +45,10 @@ $node_london->backup('london_backup');
|
|||||||
my $node_paris = PostgreSQL::Test::Cluster->new('paris');
|
my $node_paris = PostgreSQL::Test::Cluster->new('paris');
|
||||||
$node_paris->init_from_backup($node_london, 'london_backup',
|
$node_paris->init_from_backup($node_london, 'london_backup',
|
||||||
has_streaming => 1);
|
has_streaming => 1);
|
||||||
|
$node_paris->append_conf(
|
||||||
|
'postgresql.conf', qq(
|
||||||
|
subtransaction_buffers = 32
|
||||||
|
));
|
||||||
$node_paris->start;
|
$node_paris->start;
|
||||||
|
|
||||||
# Switch to synchronous replication in both directions
|
# Switch to synchronous replication in both directions
|
||||||
@ -481,4 +485,42 @@ is( $psql_out,
|
|||||||
qq{27|issued to paris},
|
qq{27|issued to paris},
|
||||||
"Check expected t_009_tbl2 data on standby");
|
"Check expected t_009_tbl2 data on standby");
|
||||||
|
|
||||||
|
|
||||||
|
# Exercise the 2PC recovery code in StartupSUBTRANS, which is concerned with
|
||||||
|
# ensuring that enough pg_subtrans pages exist on disk to cover the range of
|
||||||
|
# prepared transactions at server start time. There's not much we can verify
|
||||||
|
# directly, but let's at least get the code to run.
|
||||||
|
$cur_standby->stop();
|
||||||
|
configure_and_reload($cur_primary, "synchronous_standby_names = ''");
|
||||||
|
|
||||||
|
$cur_primary->safe_psql('postgres', "CHECKPOINT");
|
||||||
|
|
||||||
|
my $start_lsn =
|
||||||
|
$cur_primary->safe_psql('postgres', 'select pg_current_wal_insert_lsn()');
|
||||||
|
$cur_primary->safe_psql('postgres',
|
||||||
|
"CREATE TABLE test(); BEGIN; CREATE TABLE test1(); PREPARE TRANSACTION 'foo';"
|
||||||
|
);
|
||||||
|
my $osubtrans = $cur_primary->safe_psql('postgres',
|
||||||
|
"select 'pg_subtrans/'||f, s.size from pg_ls_dir('pg_subtrans') f, pg_stat_file('pg_subtrans/'||f) s"
|
||||||
|
);
|
||||||
|
$cur_primary->pgbench(
|
||||||
|
'--no-vacuum --client=5 --transactions=1000',
|
||||||
|
0,
|
||||||
|
[],
|
||||||
|
[],
|
||||||
|
'pgbench run to cause pg_subtrans traffic',
|
||||||
|
{
|
||||||
|
'009_twophase.pgb' => 'insert into test default values'
|
||||||
|
});
|
||||||
|
# StartupSUBTRANS is exercised with a wide range of visible XIDs in this
|
||||||
|
# stop/start sequence, because we left a prepared transaction open above.
|
||||||
|
# Also, setting subtransaction_buffers to 32 above causes to switch SLRU
|
||||||
|
# bank, for additional code coverage.
|
||||||
|
$cur_primary->stop;
|
||||||
|
$cur_primary->start;
|
||||||
|
my $nsubtrans = $cur_primary->safe_psql('postgres',
|
||||||
|
"select 'pg_subtrans/'||f, s.size from pg_ls_dir('pg_subtrans') f, pg_stat_file('pg_subtrans/'||f) s"
|
||||||
|
);
|
||||||
|
isnt($osubtrans, $nsubtrans, "contents of pg_subtrans/ have changed");
|
||||||
|
|
||||||
done_testing();
|
done_testing();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user