mirror of
https://github.com/postgres/postgres.git
synced 2025-05-12 16:21:30 +03:00
Change a whole-database VACUUM into doing just pg_attribute, which is the portion that verifies what we want it to do. The original formulation wastes a lot of CPU time, which leads the test to fail when runtime exceeds isolationtester timeout when it's super-slow, such as under CLOBBER_CACHE_ALWAYS. Per buildfarm member friarbird. It turns out that the previous shape of the test doesn't always detect the condition it is supposed to detect (on unpatched reorderbuffer code): the reason is that there is a good chance of encountering a xl_running_xacts record (logged every 15 seconds) before the checkpoint -- and because we advance the xmin when we receive that WAL record, and we *don't* advance the xmin twice consecutively without receiving a client message in between, that means the xmin is not advanced enough for the tuple to be pruned from pg_attribute by VACUUM. So the test would spuriously pass. The reason this test deficiency wasn't detected earlier is that HOT pruning removes the tuple anyway, even if vacuum leaves it in place, so the test correctly fails (detecting the coding mistake), but for the wrong reason. To fix this mess, run the s0_get_changes step twice before vacuum instead of once: this seems to cause the xmin to be advanced reliably, wreaking havoc with more certainty. Author: Arseny Sher Discussion: https://postgr.es/m/87h8lkuxoa.fsf@ars-thinkpad
41 lines
1.7 KiB
Ruby
41 lines
1.7 KiB
Ruby
# Test advancement of the slot's oldest xmin
|
|
|
|
setup
|
|
{
|
|
SELECT 'init' FROM pg_create_logical_replication_slot('isolation_slot', 'test_decoding'); -- must be first write in xact
|
|
DROP TYPE IF EXISTS basket;
|
|
CREATE TYPE basket AS (apples integer, pears integer, mangos integer);
|
|
DROP TABLE IF EXISTS harvest;
|
|
CREATE TABLE harvest(fruits basket);
|
|
}
|
|
|
|
teardown
|
|
{
|
|
DROP TABLE IF EXISTS harvest;
|
|
DROP TYPE IF EXISTS basket;
|
|
SELECT 'stop' FROM pg_drop_replication_slot('isolation_slot');
|
|
}
|
|
|
|
session "s0"
|
|
step "s0_begin" { BEGIN; }
|
|
step "s0_getxid" { SELECT txid_current() IS NULL; }
|
|
step "s0_alter" { ALTER TYPE basket DROP ATTRIBUTE mangos; }
|
|
step "s0_commit" { COMMIT; }
|
|
step "s0_checkpoint" { CHECKPOINT; }
|
|
step "s0_vacuum" { VACUUM pg_attribute; }
|
|
step "s0_get_changes" { SELECT data FROM pg_logical_slot_get_changes('isolation_slot', NULL, NULL, 'include-xids', '0', 'skip-empty-xacts', '1'); }
|
|
|
|
session "s1"
|
|
step "s1_begin" { BEGIN; }
|
|
step "s1_insert" { INSERT INTO harvest VALUES ((1, 2, 3)); }
|
|
step "s1_commit" { COMMIT; }
|
|
|
|
# Checkpoint with following get_changes forces xmin advancement. We do
|
|
# get_changes twice because if one more xl_running_xacts record had slipped
|
|
# before our CHECKPOINT, xmin will be advanced only on this record, thus not
|
|
# reaching value needed for vacuuming corresponding pg_attribute entry. ALTER of
|
|
# composite type is a rare form of DDL which allows T1 to see the tuple which
|
|
# will be removed (xmax set) before T1 commits. That is, interlocking doesn't
|
|
# forbid modifying catalog after someone read it (and didn't commit yet).
|
|
permutation "s0_begin" "s0_getxid" "s1_begin" "s1_insert" "s0_alter" "s0_commit" "s0_checkpoint" "s0_get_changes" "s0_get_changes""s1_commit" "s0_vacuum" "s0_get_changes"
|