Re: pg_amcheck contrib application
Robert Haas <robertmhaas@gmail.com>
Most of these changes sound good. I'll go through the whole patch again today, or as much of it as I can. But before I do that, I want to comment on this point specifically. On Thu, Mar 4, 2021 at 1:25 AM Mark Dilger <mark.dilger@enterprisedb.com> wrote: > I think this is fixed up now. There is an interaction with amcheck's verify_heapam(), where that function raises an error if the startblock or endblock arguments are out of bounds for the relation in question. Rather than aborting the entire pg_amcheck run, it avoids passing inappropriate block ranges to verify_heapam() and outputs a warning, so: > > % pg_amcheck mark.dilger -t foo -t pg_class --progress -v --startblock=35 --endblock=77 > pg_amcheck: in database "mark.dilger": using amcheck version "1.3" in schema "public" > 0/6 relations (0%) 0/55 pages (0%) > pg_amcheck: checking table "mark.dilger"."public"."foo" (oid 16385) (10/45 pages) > pg_amcheck: warning: ignoring endblock option 77 beyond end of table "mark.dilger"."public"."foo" > pg_amcheck: checking btree index "mark.dilger"."public"."foo_idx" (oid 16388) (30/30 pages) > pg_amcheck: checking table "mark.dilger"."pg_catalog"."pg_class" (oid 1259) (0/13 pages) > pg_amcheck: warning: ignoring startblock option 35 beyond end of table "mark.dilger"."pg_catalog"."pg_class" > pg_amcheck: warning: ignoring endblock option 77 beyond end of table "mark.dilger"."pg_catalog"."pg_class" > pg_amcheck: checking btree index "mark.dilger"."pg_catalog"."pg_class_relname_nsp_index" (oid 2663) (6/6 pages) > pg_amcheck: checking btree index "mark.dilger"."pg_catalog"."pg_class_tblspc_relfilenode_index" (oid 3455) (5/5 pages) > pg_amcheck: checking btree index "mark.dilger"."pg_catalog"."pg_class_oid_index" (oid 2662) (4/4 pages) > 6/6 relations (100%) 55/55 pages (100%) > > The way the (x/y pages) is printed takes into account that the [startblock..endblock] range may reduce the number of pages to check (x) to something less than the number of pages in the relation (y), but the reporting is a bit of a lie when the startblock is beyond the end of the table, as it doesn't get passed to verify_heapam and so the number of blocks checked may be more than the zero blocks reported. I think I might need to fix this up tomorrow, but I want to get what I have in this patch set posted tonight, so it's not fixed here. Also, there are multiple ways of addressing this, and I'm having trouble deciding which way is best. I can exclude the relation from being checked at all, or realize earlier that I'm not going to honor the startblock argument and compute the blocks to check correctly. Thoughts? I think this whole approach is pretty suspect because the number of blocks in the relation can increase (by relation extension) or decrease (by VACUUM or TRUNCATE) between the time when we query for the list of target relations and the time we get around to executing any queries against them. I think it's OK to use the number of relation pages for progress reporting because progress reporting is only approximate anyway, but I wouldn't print them out in the progress messages, and I wouldn't try to fix up the startblock and endblock arguments on the basis of how long you think that relation is going to be. You seem to view the fact that the server reported the error as the reason for the problem, but I don't agree. I think having the server report the error here is right, and the problem is that the error reporting sucked because it was long-winded and didn't necessarily tell you which table had the problem. There are a LOT of things that can go wrong when we go try to run verify_heapam on a table. The table might have been dropped; in fact, on a busy production system, such cases are likely to occur routinely if DDL is common, which for many users it is. The system catalog entries might be screwed up, so that the relation can't be opened. There might be an unreadable page in the relation, either because the OS reports an I/O error or something like that, or because checksum verification fails. There are various other possibilities. We shouldn't view such errors as low-level things that occur only in fringe cases; this is a corruption-checking tool, and we should expect that running it against messed-up databases will be common. We shouldn't try to interpret the errors we get or make any big decisions about them, but we should have a clear way of reporting them so that the user can decide what to do. Just as an experiment, I suggest creating a database with 100 tables in it, each with 1 index, and then deleting a single pg_attribute entry for 10 of the tables, and then running pg_amcheck. I think you will get 20 errors - one for each messed-up table and one for the corresponding index. Maybe you'll get errors for the TOAST tables checks too, if the tables have TOAST tables, although that seems like it should be avoidable. Now, now matter what you do, the tool is going to produce a lot of output here, because you have a lot of problems, and that's OK. But how understandable is that output, and how concise is it? If it says something like: pg_amcheck: could not check "SCHEMA_NAME"."TABLE_NAME": ERROR: some attributes are missing or something ...and that line is repeated 20 times, maybe with a context or detail line for each one or something like that, then you have got a good UI. If it's not clear which tables have the problem, you have got a bad UI. If it dumps out 300 lines of output instead of 20 or 40, you have a UI that is so verbose that usability is going to be somewhat impaired, which is why I suggested only showing the query in verbose mode. BTW, another thing that might be interesting is to call PQsetErrorVerbosity(conn, PQERRORS_VERBOSE) in verbose mode. It's probably possible to contrive a case where the server error message is something generic like "cache lookup failed for relation %u" which occurs in a whole bunch of places in the source code, and being able get the file and line number information can be really useful when trying to track such things down. -- Robert Haas EDB: http://www.enterprisedb.com
Commits
-
amcheck: Improve some confusing reports about TOAST problems.
- 50529e5b4e39 14.0 landed
-
amcheck: Reword some messages and fix an alignment problem.
- 9acaf1a62197 14.0 landed
-
amcheck: fix multiple problems with TOAST pointer validation
- ec7ffb8096e8 14.0 landed
-
amcheck: Remove duplicate XID/MXID bounds checks.
- 4573f6a9af6e 14.0 landed
-
amcheck: Fix verify_heapam's tuple visibility checking rules.
- 3b6c1259f9ca 14.0 landed
-
nbtree VACUUM: Cope with buggy opclasses.
- 5b861baa550a 14.0 landed
-
Improve pg_amcheck's TAP test 003_check.pl.
- 87d90ac61fa1 14.0 landed
-
Fix a confusing amcheck corruption message.
- 4078ce65a0f7 14.0 landed
-
Doc: add note about how to run the pg_amcheck regression tests.
- 58f57490facd 14.0 cited
-
In pg_amcheck tests, don't depend on perl's Q/q pack code.
- 945d2cb7d025 14.0 landed
-
pg_amcheck: Keep trying to fix the tests.
- 9e294d0f34d6 14.0 landed
-
pg_amcheck: Try to fix still more test failures.
- 24189277f6ff 14.0 landed
-
Try to avoid apparent platform-dependency in IPC::Run
- f371a4cdba6d 14.0 landed
-
Fix portability issues in pg_amcheck's 004_verify_heapam.pl.
- 661125612706 14.0 landed
-
Try to fix compiler warnings.
- d60e61de4fb4 14.0 landed
-
Add pg_amcheck, a CLI for contrib/amcheck.
- 9706092839db 14.0 landed
-
Refactor and generalize the ParallelSlot machinery.
- f71519e545a3 14.0 landed
-
Remove old-style VACUUM FULL (which was known for a little while as
- 0a469c87692d 9.0.0 cited