Re: [BUGS] vacuum analyze corrupts db with larger tuples (< 8k)

Tom Lane <tgl@sss.pgh.pa.us>

From: Tom Lane <tgl@sss.pgh.pa.us>
To: Dirk Lutzebaeck <lutzeb@aeccom.com>
Cc: pgsql-bugs@postgreSQL.org
Date: 2000-01-04T17:30:54Z
Lists: pgsql-bugs
I wrote:
> Ohhh ... I know what's going on.  The oversize tuple is the one that
> VACUUM is attempting to store in pg_statistic, containing the min and
> max values for your varchar column.  In this example, both the min and
> max are just shy of 5K characters, so the pg_statistic tuple is too
> big to fit on a page.

I have applied the attached patch to the REL6_5 branch.  (There is
already similar code in the current branch.)  I'm afraid it won't
help you recover from an already-corrupted pg_statistic table, though.

			regards, tom lane

*** src/backend/commands/vacuum.c.orig	Wed Aug 25 08:01:45 1999
--- src/backend/commands/vacuum.c	Tue Jan  4 12:15:17 2000
***************
*** 2405,2414 ****
  					stup = heap_formtuple(sd->rd_att, values, nulls);
  
  					/* ----------------
! 					 *	insert the tuple in the relation and get the tuple's oid.
  					 * ----------------
  					 */
! 					heap_insert(sd, stup);
  					pfree(DatumGetPointer(values[3]));
  					pfree(DatumGetPointer(values[4]));
  					pfree(stup);
--- 2405,2425 ----
  					stup = heap_formtuple(sd->rd_att, values, nulls);
  
  					/* ----------------
! 					 *	Watch out for oversize tuple, which can happen if
! 					 *	both of the saved data values are long.
! 					 *	Our fallback strategy is just to not store the
! 					 *	pg_statistic tuple at all in that case.  (We could
! 					 *	replace the values by NULLs and still store the
! 					 *	numeric stats, but presently selfuncs.c couldn't
! 					 *	do anything useful with that case anyway.)
  					 * ----------------
  					 */
! 					if (MAXALIGN(stup->t_len) <= MaxTupleSize)
! 					{
! 						/* OK to store tuple */
! 						heap_insert(sd, stup);
! 					}
! 
  					pfree(DatumGetPointer(values[3]));
  					pfree(DatumGetPointer(values[4]));
  					pfree(stup);