SP-GiST bug and fix

Lists: pgsql-hackers
From: Teodor Sigaev <teodor(at)sigaev(dot)ru>
To: Pgsql Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: SP-GiST bug and fix
Date: 2013-10-31 15:07:42
Message-ID: 5272723E.8070308@sigaev.ru
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

SP-GiST has a bug during creation:
% create table ranges as select int4range( (random()*5)::int,
(random()*5)::int+5) as range
from generate_series(1,1000000) x;

% create index ranges_range_spgist_idx on ranges using spgist(range);
ERROR: unexpected spgdoinsert() failure

Bug is discovered by Jonathan S. Katz <jonathan(dot)katz(at)excoventures(dot)com>

When it was found deadlock possibility it was fixed by using
ConditionalLockBuffer() instead of LockBuffer(EXCLUSIVE) and retrying insertion
from the scratch. Build index method doesn't believe in concurrent access and
throws an error if ConditionalLockBuffer() fails. But I missed that
checkpointer process could take a share lock on buffer to write it on disk.

Attached patch just intoduces retrying during index creation.

--
Teodor Sigaev E-mail: teodor(at)sigaev(dot)ru
WWW: http://www.sigaev.ru/

Attachment Content-Type Size
spgist_build.patch.gz application/x-tar 482 bytes

From: Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us>
To: Teodor Sigaev <teodor(at)sigaev(dot)ru>
Cc: Pgsql Hackers <pgsql-hackers(at)postgresql(dot)org>
Subject: Re: SP-GiST bug and fix
Date: 2013-11-02 20:26:32
Message-ID: 13867.1383423992@sss.pgh.pa.us
Views: Raw Message | Whole Thread | Download mbox | Resend email
Lists: pgsql-hackers

Teodor Sigaev <teodor(at)sigaev(dot)ru> writes:
> SP-GiST has a bug during creation:
> % create table ranges as select int4range( (random()*5)::int,
> (random()*5)::int+5) as range
> from generate_series(1,1000000) x;

> % create index ranges_range_spgist_idx on ranges using spgist(range);
> ERROR: unexpected spgdoinsert() failure

> Bug is discovered by Jonathan S. Katz <jonathan(dot)katz(at)excoventures(dot)com>

> When it was found deadlock possibility it was fixed by using
> ConditionalLockBuffer() instead of LockBuffer(EXCLUSIVE) and retrying insertion
> from the scratch. Build index method doesn't believe in concurrent access and
> throws an error if ConditionalLockBuffer() fails. But I missed that
> checkpointer process could take a share lock on buffer to write it on disk.

> Attached patch just intoduces retrying during index creation.

The comments could use some work (both here and in spgdoinsert), but
I agree this is a real bug and the fix is sane. Will fix the comments
and commit.

regards, tom lane