Re: Unlogged tables cannot be truncated twice

From: Cédric Villemain <cedric(dot)villemain(dot)debian(at)gmail(dot)com>
To: Andres Freund <andres(at)anarazel(dot)de>
Cc: pgsql-bugs(at)postgresql(dot)org, Alvaro Herrera <alvherre(at)commandprompt(dot)com>, Greg Sabino Mullane <greg(at)endpoint(dot)com>
Subject: Re: Unlogged tables cannot be truncated twice
Date: 2011-05-30 23:56:05
Message-ID: BANLkTimj=TZEOz4Yffv+8e6KM-9Dkf4E_g@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-bugs

2011/5/31 Andres Freund <andres(at)anarazel(dot)de>:
> On Monday, May 30, 2011 11:18:20 PM Alvaro Herrera wrote:
>> Excerpts from Greg Sabino Mullane's message of lun may 30 12:00:43 -0400
> 2011:
>> > Wow, this one took a bit to narrow down. Here's the failing case:
>> >
>> > # create unlogged table foo (a text);
>> > CREATE TABLE
>> > # begin;
>> > BEGIN
>> > #* truncate table foo;
>> > TRUNCATE TABLE
>> > #* truncate table foo;
>> > ERROR:  could not create file "base/19131/19183_init": File exists
>> >
>> > Very reproducible. The column types matter: if the only column
>> > is an INT, for example, the problem does not occur.
>>
>> So 19183 is the toast table OID?
> Nope. Its any index.
>
> You can provoke it with:
> begin;create unlogged table foo (a int primary key);truncate foo;rollback;
> or
> begin;create unlogged table foo (a text);truncate foo;rollback;
>
>
> The problem is this tidbit from tablecmds.c's ExecuteTruncate:
>
>                /*
>                 * Normally, we need a transaction-safe truncation here.  However, if
>                 * the table was either created in the current (sub)transaction or has
>                 * a new relfilenode in the current (sub)transaction, then we can just
>                 * truncate it in-place, because a rollback would cause the whole
>                 * table or the current physical file to be thrown away anyway.
>                 */
>                if (rel->rd_createSubid == mySubid ||
>                        rel->rd_newRelfilenodeSubid == mySubid)
>                {
>                        /* Immediate, non-rollbackable truncation is OK */
>                        heap_truncate_one_rel(rel);
>                }
>
> in combination with index.c's index_build:
>
>
>        /*
>         * If this is an unlogged index, we need to write out an init fork for it.
>         */
>        if (heapRelation->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
>        {
>                RegProcedure ambuildempty = indexRelation->rd_am->ambuildempty;
>
>                RelationOpenSmgr(indexRelation);
>                smgrcreate(indexRelation->rd_smgr, INIT_FORKNUM, false);
>                OidFunctionCall1(ambuildempty, PointerGetDatum(indexRelation));
>        }
>

I remove my own explanations as we conclude on the same thing.
Attached is the fix by adding a (!reindex) in the index.c if().

It looks enough from early testing.

--
Cédric Villemain               2ndQuadrant
http://2ndQuadrant.fr/     PostgreSQL : Expertise, Formation et Support

Attachment Content-Type Size
fix_reindex_unlog.patch text/x-patch 543 bytes

In response to

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message Andres Freund 2011-05-31 00:14:00 Re: Unlogged tables cannot be truncated twice
Previous Message Andres Freund 2011-05-30 23:28:37 Re: Unlogged tables cannot be truncated twice