Re: ERROR: missing chunk number 0 for toast value - Mailing list pgsql-hackers

From Heikki Linnakangas
Subject Re: ERROR: missing chunk number 0 for toast value
Date
Msg-id 52C5BC2B.1000604@vmware.com
Whole thread Raw
In response to ERROR: missing chunk number 0 for toast value  (Rushabh Lathia <rushabh.lathia@gmail.com>)
Responses Re: ERROR: missing chunk number 0 for toast value
Re: ERROR: missing chunk number 0 for toast value
Re: ERROR: missing chunk number 0 for toast value
List pgsql-hackers
On 01/02/2014 02:24 PM, Rushabh Lathia wrote:
> Hi All,
>
> Test case:
>
> drop table if exists t;
> create table t(c text);
> insert into t values ('x'), (repeat(md5('abcdefghijklmnop'), 10000));
> select pg_column_size(c), pg_column_size(c || '') FROM t;
>
> CREATE OR REPLACE FUNCTION copy_toast_out() RETURNS VOID AS $$
> declare
>          v text;
> BEGIN
>          SELECT c INTO v FROM t WHERE c <> 'x';
>      Select 1/0;
> Exception
>          When Others Then
>          PERFORM pg_sleep(30); -- go run "TRUNCATE t" in a 2nd session
>
>
>          raise notice 'length :%', length(v || ''); -- force detoast
>
>
> END;
> $$ language plpgsql;
>
> postgres=# select copy_toast_out();
> ERROR:  missing chunk number 0 for toast value 16390 in pg_toast_16384
> CONTEXT:  PL/pgSQL function copy_toast_out() line 10 at RAISE
>
> Analysis:
>
> The basic problem here is that if the lock is released on table before
> extracting toasted value, and in meantime someone truncates the table,
> this error can occur.  Here error coming with PL block contains an Exception
> block (as incase there is an exception block, it calls
> RollbackAndReleaseCurrentSubTransaction).

This is another variant of the bug discussed here: 
http://www.postgresql.org/message-id/0C41674C-FA02-4768-9E1B-548E568875BD@quarantainenet.nl.

> Do you think we should detoast the local variable before
>   RollbackAndReleaseCurrentSubTransaction ? Or any other options ?

Hmm, that would fix this particular test case, but not the other case 
where you DROP or TRUNCATE the table in the same transaction.

The simplest fix would be to just detoast everything on assignment but 
that was rejected on performance grounds in that previous thread. I 
don't see any other realistic way to fix this, however, so maybe we 
should just bite the bullet and do it anyway. For simple variables like, 
in your test case, it's a good bet to detoast the value immediately; 
it'll be detoasted as soon as you try to do anything with it anyway. But 
it's not a good bet for record or row variables, because you often fetch 
the whole row into a variable but only access a field or two. Then 
again, if you run into that, at least you can work around it by changing 
your plpgsql code to only fetch the fields you need.

- Heikki



pgsql-hackers by date:

Previous
From: Andres Freund
Date:
Subject: Re: proposal: multiple read-write masters in a cluster with wal-streaming synchronization
Next
From: Andres Freund
Date:
Subject: Re: preserving forensic information when we freeze