Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdd58194

Browse files
pg_amcheck: avoid unhelpful verification attempts.
Avoid calling contrib/amcheck functions with relations that areunsuitable for checking. Specifically, don't attempt verification oftemporary relations, or indexes whose pg_index entry indicates that theindex is invalid, or not ready.These relations are not supported by any of the contrib/amcheckfunctions, for reasons that are pretty fundamental. For example, theimplementation of REINDEX CONCURRENTLY can add its own "transient"pg_index entries, which has rather unclear implications for the B-Treeverification functions, at least in the general case -- so they justtreat it as an error. It falls to the amcheck caller (in this casepg_amcheck) to deal with the situation at a higher level.pg_amcheck now simply treats these conditions as additional "visibilityconcerns" when it queries system catalogs. This is a little arbitrary.It seems to have the least problems among any of the availablealternatives.Author: Mark Dilger <mark.dilger@enterprisedb.com>Reported-By: Alexander Lakhin <exclusion@gmail.com>Reviewed-By: Peter Geoghegan <pg@bowt.ie>Reviewed-By: Robert Haas <robertmhaas@gmail.com>Bug: #17212Discussion:https://postgr.es/m/17212-34dd4a1d6bba98bf@postgresql.orgBackpatch: 14-, where pg_amcheck was introduced.
1 parent419d27b commitdd58194

File tree

3 files changed

+299
-29
lines changed

3 files changed

+299
-29
lines changed

‎doc/src/sgml/ref/pg_amcheck.sgml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,18 @@ PostgreSQL documentation
432432
</variablelist>
433433
</para>
434434

435+
<warning>
436+
<para>
437+
The extra checks performed against B-tree indexes when the
438+
<option>--parent-check</option> option or the
439+
<option>--rootdescend</option> option is specified require
440+
relatively strong relation-level locks. These checks are the only
441+
checks that will block concurrent data modification from
442+
<command>INSERT</command>, <command>UPDATE</command>, and
443+
<command>DELETE</command> commands.
444+
</para>
445+
</warning>
446+
435447
<para>
436448
The following command-line options control the connection to the server:
437449

‎src/bin/pg_amcheck/pg_amcheck.c

Lines changed: 54 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,9 @@ main(int argc, char *argv[])
818818
* names matching the expectations of verify_heap_slot_handler, which will
819819
* receive and handle each row returned from the verify_heapam() function.
820820
*
821+
* The constructed SQL command will silently skip temporary tables, as checking
822+
* them would needlessly draw errors from the underlying amcheck function.
823+
*
821824
* sql: buffer into which the heap table checking command will be written
822825
* rel: relation information for the heap table to be checked
823826
* conn: the connection to be used, for string escaping purposes
@@ -827,10 +830,10 @@ prepare_heap_command(PQExpBuffer sql, RelationInfo *rel, PGconn *conn)
827830
{
828831
resetPQExpBuffer(sql);
829832
appendPQExpBuffer(sql,
830-
"SELECT blkno, offnum, attnum, msg FROM %s.verify_heapam("
831-
"\nrelation := %u, on_error_stop := %s, check_toast := %s, skip := '%s'",
833+
"SELECT v.blkno, v.offnum, v.attnum, v.msg "
834+
"FROM pg_catalog.pg_class c, %s.verify_heapam("
835+
"\nrelation := c.oid, on_error_stop := %s, check_toast := %s, skip := '%s'",
832836
rel->datinfo->amcheck_schema,
833-
rel->reloid,
834837
opts.on_error_stop ?"true" :"false",
835838
opts.reconcile_toast ?"true" :"false",
836839
opts.skip);
@@ -840,7 +843,10 @@ prepare_heap_command(PQExpBuffer sql, RelationInfo *rel, PGconn *conn)
840843
if (opts.endblock >=0)
841844
appendPQExpBuffer(sql,", endblock := "INT64_FORMAT,opts.endblock);
842845

843-
appendPQExpBufferChar(sql,')');
846+
appendPQExpBuffer(sql,
847+
"\n) v WHERE c.oid = %u "
848+
"AND c.relpersistence != 't'",
849+
rel->reloid);
844850
}
845851

846852
/*
@@ -851,6 +857,10 @@ prepare_heap_command(PQExpBuffer sql, RelationInfo *rel, PGconn *conn)
851857
* functions do not return any, but rather return corruption information by
852858
* raising errors, which verify_btree_slot_handler expects.
853859
*
860+
* The constructed SQL command will silently skip temporary indexes, and
861+
* indexes being reindexed concurrently, as checking them would needlessly draw
862+
* errors from the underlying amcheck functions.
863+
*
854864
* sql: buffer into which the heap table checking command will be written
855865
* rel: relation information for the index to be checked
856866
* conn: the connection to be used, for string escaping purposes
@@ -860,27 +870,31 @@ prepare_btree_command(PQExpBuffer sql, RelationInfo *rel, PGconn *conn)
860870
{
861871
resetPQExpBuffer(sql);
862872

863-
/*
864-
* Embed the database, schema, and relation name in the query, so if the
865-
* check throws an error, the user knows which relation the error came
866-
* from.
867-
*/
868873
if (opts.parent_check)
869874
appendPQExpBuffer(sql,
870-
"SELECT * FROM %s.bt_index_parent_check("
871-
"index := '%u'::regclass, heapallindexed := %s, "
872-
"rootdescend := %s)",
875+
"SELECT %s.bt_index_parent_check("
876+
"index := c.oid, heapallindexed := %s, rootdescend := %s)"
877+
"\nFROM pg_catalog.pg_class c, pg_catalog.pg_index i "
878+
"WHERE c.oid = %u "
879+
"AND c.oid = i.indexrelid "
880+
"AND c.relpersistence != 't' "
881+
"AND i.indisready AND i.indisvalid AND i.indislive",
873882
rel->datinfo->amcheck_schema,
874-
rel->reloid,
875883
(opts.heapallindexed ?"true" :"false"),
876-
(opts.rootdescend ?"true" :"false"));
884+
(opts.rootdescend ?"true" :"false"),
885+
rel->reloid);
877886
else
878887
appendPQExpBuffer(sql,
879-
"SELECT * FROM %s.bt_index_check("
880-
"index := '%u'::regclass, heapallindexed := %s)",
888+
"SELECT %s.bt_index_check("
889+
"index := c.oid, heapallindexed := %s)"
890+
"\nFROM pg_catalog.pg_class c, pg_catalog.pg_index i "
891+
"WHERE c.oid = %u "
892+
"AND c.oid = i.indexrelid "
893+
"AND c.relpersistence != 't' "
894+
"AND i.indisready AND i.indisvalid AND i.indislive",
881895
rel->datinfo->amcheck_schema,
882-
rel->reloid,
883-
(opts.heapallindexed ?"true" :"false"));
896+
(opts.heapallindexed ?"true" :"false"),
897+
rel->reloid);
884898
}
885899

886900
/*
@@ -1088,15 +1102,17 @@ verify_btree_slot_handler(PGresult *res, PGconn *conn, void *context)
10881102

10891103
if (PQresultStatus(res)==PGRES_TUPLES_OK)
10901104
{
1091-
intntups=PQntuples(res);
1105+
intntups=PQntuples(res);
10921106

1093-
if (ntups!=1)
1107+
if (ntups>1)
10941108
{
10951109
/*
10961110
* We expect the btree checking functions to return one void row
1097-
* each, so we should output some sort of warning if we get
1098-
* anything else, not because it indicates corruption, but because
1099-
* it suggests a mismatch between amcheck and pg_amcheck versions.
1111+
* each, or zero rows if the check was skipped due to the object
1112+
* being in the wrong state to be checked, so we should output some
1113+
* sort of warning if we get anything more, not because it
1114+
* indicates corruption, but because it suggests a mismatch between
1115+
* amcheck and pg_amcheck versions.
11001116
*
11011117
* In conjunction with --progress, anything written to stderr at
11021118
* this time would present strangely to the user without an extra
@@ -1896,10 +1912,16 @@ compile_relation_list_one_db(PGconn *conn, SimplePtrList *relations,
18961912
"\nAND (c.relam = %u OR NOT ep.btree_only OR ep.rel_regex IS NULL)",
18971913
HEAP_TABLE_AM_OID,BTREE_AM_OID);
18981914

1915+
/*
1916+
* Exclude temporary tables and indexes, which must necessarily belong to
1917+
* other sessions. (We don't create any ourselves.) We must ultimately
1918+
* exclude indexes marked invalid or not ready, but we delay that decision
1919+
* until firing off the amcheck command, as the state of an index may
1920+
* change by then.
1921+
*/
1922+
appendPQExpBufferStr(&sql,"\nWHERE c.relpersistence != 't'");
18991923
if (opts.excludetbl||opts.excludeidx||opts.excludensp)
1900-
appendPQExpBufferStr(&sql,"\nWHERE ep.pattern_id IS NULL");
1901-
else
1902-
appendPQExpBufferStr(&sql,"\nWHERE true");
1924+
appendPQExpBufferStr(&sql,"\nAND ep.pattern_id IS NULL");
19031925

19041926
/*
19051927
* We need to be careful not to break the --no-dependent-toast and
@@ -1951,7 +1973,8 @@ compile_relation_list_one_db(PGconn *conn, SimplePtrList *relations,
19511973
"\nON ('pg_toast' ~ ep.nsp_regex OR ep.nsp_regex IS NULL)"
19521974
"\nAND (t.relname ~ ep.rel_regex OR ep.rel_regex IS NULL)"
19531975
"\nAND ep.heap_only"
1954-
"\nWHERE ep.pattern_id IS NULL");
1976+
"\nWHERE ep.pattern_id IS NULL"
1977+
"\nAND t.relpersistence != 't'");
19551978
appendPQExpBufferStr(&sql,
19561979
"\n)");
19571980
}
@@ -1969,7 +1992,8 @@ compile_relation_list_one_db(PGconn *conn, SimplePtrList *relations,
19691992
"\nINNER JOIN pg_catalog.pg_index i "
19701993
"ON r.oid = i.indrelid "
19711994
"INNER JOIN pg_catalog.pg_class c "
1972-
"ON i.indexrelid = c.oid");
1995+
"ON i.indexrelid = c.oid "
1996+
"AND c.relpersistence != 't'");
19731997
if (opts.excludeidx||opts.excludensp)
19741998
appendPQExpBufferStr(&sql,
19751999
"\nINNER JOIN pg_catalog.pg_namespace n "
@@ -2007,7 +2031,8 @@ compile_relation_list_one_db(PGconn *conn, SimplePtrList *relations,
20072031
"INNER JOIN pg_catalog.pg_index i "
20082032
"ON t.oid = i.indrelid"
20092033
"\nINNER JOIN pg_catalog.pg_class c "
2010-
"ON i.indexrelid = c.oid");
2034+
"ON i.indexrelid = c.oid "
2035+
"AND c.relpersistence != 't'");
20112036
if (opts.excludeidx)
20122037
appendPQExpBufferStr(&sql,
20132038
"\nLEFT OUTER JOIN exclude_pat ep "

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp