On 1/31/07, Tom Lane <[EMAIL PROTECTED]> wrote:
"Pavan Deolasee" <[EMAIL PROTECTED]> writes:
> Btw, I noticed that the toast_insert_or_update() is re-entrant.
> toast_save_datum() calls simple_heap_insert() which somewhere down the
> line calls toast_insert_or_update() again.
The toast code takes pains to ensure that the tuples it creates won't be
subject to re-toasting. Else it'd be an infinite recursion.
I think I found it. The toast_insert_or_update() function gets into an
recursion because of alignment issues. It thus toasts already toasted data.
IMHO might be causing unnecessary overheads for each toast operation.
The default value of TOAST_TUPLE_THRESHOLD is 2034 (assuming 8K block size)
TOAST_MAX_CHUNK_SIZE is defined as below:
#define TOAST_MAX_CHUNK_SIZE (TOAST_TUPLE_THRESHOLD - \
MAXALIGN(offsetof(HeapTupleHeaderData, t_bits)) + \
sizeof(Oid) + \
sizeof(int32) + \
So the default value of TOAST_MAX_CHUNK_SIZE is set to 1994.
When toast_insert_or_update() returns a tuple for the first chunk, t_len
is set to 2034 (TOAST_MAX_CHUNK_SIZE + tuple header + chunk_id
+ chunk_seqno + VARHDRSZ)
In heap_insert(), we MAXALIGN(tup->t_len) before comparing it with
TOAST_TUPLE_THRESHOLD to decide whether to invoke TOAST or not.
In this corner case, MAXALIGN(2034) = 2036 > TOAST_TUPLE_THRESHOLD
and so TOAST is invoked again.
Fortunately, we don't get into infinite recursion because reltoastrelid is
InvalidOid for toast tables and hence TOASTing is not invoked in the second
Attached is a patch which would print the recursion depth for
toast_insert_or_update() before PANICing the server to help us
examine the core.
Let me know if this sounds like an issue and I can work out a patch.