mirror of https://github.com/postgres/postgres
We've measured 5% performance improvement, and this arranges to benefit automatically from future optimizations to the read_stream subsystem. The area lacked test coverage, so close that gap. Nazir Bilal Yavuz Discussion: https://postgr.es/m/CAN55FZ1_Ru3XpMgTwsU67FTH2fs_FrRROmb7x6zs+F44QBEiww@mail.gmail.com Discussion: https://postgr.es/m/CAEudQAozv3wTY5TV2t29JcwPydbmKbiWQkZD42S2OgzdixPMDQ@mail.gmail.compull/177/head
parent
52c707483c
commit
65c310b310
@ -0,0 +1,109 @@ |
||||
# Copyright (c) 2021-2024, PostgreSQL Global Development Group |
||||
|
||||
# Check that pg_check_visible() and pg_check_frozen() report correct TIDs for |
||||
# corruption. |
||||
use strict; |
||||
use warnings FATAL => 'all'; |
||||
use File::Copy; |
||||
use PostgreSQL::Test::Cluster; |
||||
use PostgreSQL::Test::Utils; |
||||
use Test::More; |
||||
|
||||
my $node = PostgreSQL::Test::Cluster->new('main'); |
||||
$node->init; |
||||
# Anything holding a snapshot, including auto-analyze of pg_proc, could stop |
||||
# VACUUM from updating the visibility map. |
||||
$node->append_conf('postgresql.conf', 'autovacuum=off'); |
||||
$node->start; |
||||
|
||||
my $blck_size = $node->safe_psql("postgres", "SHOW block_size;"); |
||||
|
||||
# Create a sample table with at least 10 pages and then run VACUUM. 10 is |
||||
# selected manually as it is big enough to select 5 random tuples from the |
||||
# relation. |
||||
$node->safe_psql( |
||||
'postgres', qq( |
||||
CREATE EXTENSION pg_visibility; |
||||
CREATE TABLE corruption_test |
||||
WITH (autovacuum_enabled = false) AS |
||||
SELECT |
||||
i, |
||||
repeat('a', 10) AS data |
||||
FROM |
||||
generate_series(1, $blck_size) i; |
||||
VACUUM (FREEZE, DISABLE_PAGE_SKIPPING) corruption_test; |
||||
)); |
||||
|
||||
# VACUUM is run, it is safe to get the number of pages. |
||||
my $npages = $node->safe_psql( |
||||
"postgres", |
||||
"SELECT relpages FROM pg_class |
||||
WHERE relname = 'corruption_test';" |
||||
); |
||||
ok($npages >= 10, 'table has at least 10 pages'); |
||||
|
||||
my $file = $node->safe_psql("postgres", |
||||
"SELECT pg_relation_filepath('corruption_test');"); |
||||
|
||||
# Delete the first block to make sure that it will be skipped as it is |
||||
# not visible nor frozen. |
||||
$node->safe_psql( |
||||
"postgres", |
||||
"DELETE FROM corruption_test |
||||
WHERE (ctid::text::point)[0] = 0;" |
||||
); |
||||
|
||||
# Copy visibility map. |
||||
$node->stop; |
||||
my $vm_file = $node->data_dir . '/' . $file . '_vm'; |
||||
copy("$vm_file", "${vm_file}_temp"); |
||||
$node->start; |
||||
|
||||
# Select 5 random tuples that are starting from the second block of the |
||||
# relation. The first block is skipped because it is deleted above. |
||||
my $tuples = $node->safe_psql( |
||||
"postgres", |
||||
"SELECT ctid FROM ( |
||||
SELECT ctid FROM corruption_test |
||||
WHERE (ctid::text::point)[0] != 0 |
||||
ORDER BY random() LIMIT 5) |
||||
ORDER BY ctid ASC;" |
||||
); |
||||
|
||||
# Do the changes below to use tuples in the query. |
||||
# "\n" -> "," |
||||
# "(" -> "'(" |
||||
# ")" -> ")'" |
||||
(my $tuples_query = $tuples) =~ s/\n/,/g; |
||||
$tuples_query =~ s/\(/\'\(/g; |
||||
$tuples_query =~ s/\)/\)\'/g; |
||||
|
||||
$node->safe_psql( |
||||
"postgres", |
||||
"DELETE FROM corruption_test |
||||
WHERE ctid in ($tuples_query);" |
||||
); |
||||
|
||||
# Overwrite visibility map with the old one. |
||||
$node->stop; |
||||
move("${vm_file}_temp", "$vm_file"); |
||||
$node->start; |
||||
|
||||
my $result = $node->safe_psql( |
||||
"postgres", |
||||
"SELECT DISTINCT t_ctid |
||||
FROM pg_check_visible('corruption_test') |
||||
ORDER BY t_ctid ASC;" |
||||
); |
||||
is($result, $tuples, 'pg_check_visible must report tuples as corrupted'); |
||||
|
||||
$result = $node->safe_psql( |
||||
"postgres", |
||||
"SELECT DISTINCT t_ctid |
||||
FROM pg_check_frozen('corruption_test') |
||||
ORDER BY t_ctid ASC;" |
||||
); |
||||
is($result, $tuples, 'pg_check_frozen must report tuples as corrupted'); |
||||
|
||||
$node->stop; |
||||
done_testing(); |
Loading…
Reference in new issue