Re: INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0

Поиск
Список
Период
Сортировка
От Heikki Linnakangas
Тема Re: INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0
Дата
Msg-id 552E7CAE.6070309@iki.fi
обсуждение исходный текст
Ответ на Re: INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0  (Peter Geoghegan <pg@heroku.com>)
Ответы Re: INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0  (Andres Freund <andres@anarazel.de>)
Re: INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0  (Andres Freund <andres@anarazel.de>)
Список pgsql-hackers
On 04/15/2015 07:51 AM, Peter Geoghegan wrote:
> +heap_finish_speculative(Relation relation, HeapTuple tuple, bool conflict)
> +{
> +    if (!conflict)
> +    {
> +        /*
> +         * Update the tuple in-place, in the common case where no conflict was
> +         * detected during speculative insertion.
> +         *
> +         * When heap_insert is called in respect of a speculative tuple, the
> +         * page will actually have a tuple inserted.  However, during recovery
> +         * replay will add an all-zero tuple to the page instead, which is the
> +         * same length as the original (but the tuple header is still WAL
> +         * logged and will still be restored at that point).  If and when the
> +         * in-place update record corresponding to releasing a value lock is
> +         * replayed, crash recovery takes the final tuple value from there.
> +         * Thus, speculative heap records require two WAL records.
> +         *
> +         * Logical decoding interprets an in-place update associated with a
> +         * speculative insertion as a regular insert change.  In other words,
> +         * the in-place record generated affirms that a speculative insertion
> +         * completed successfully.
> +         */
> +        heap_inplace_update(relation, tuple);
> +    }
> +    else
> +    {

That's a bizarre solution. May I suggest a much simpler one:

Make the heap-insert record the same for normal and speculative 
insertions, except for a flag that's set if it's a speculative one. 
Replay as usual.

When the speculative insertion is finished, write a new kind of a WAL 
record for that. The record only needs to contain the ctid of the tuple. 
Replaying that record will clear the flag on the heap tuple that said 
that it was a speculative insertion.

In logical decoding, decode speculative insertions like any other 
insertion. To decode a super-deletion record, scan the reorder buffer 
for the transaction to find the corresponding speculative insertion 
record for the tuple, and remove it.

BTW, that'd work just as well without the new WAL record to finish a 
speculative insertion. Am I missing something?

> --- a/src/include/storage/off.h
> +++ b/src/include/storage/off.h
> @@ -26,6 +26,7 @@ typedef uint16 OffsetNumber;
>  #define InvalidOffsetNumber        ((OffsetNumber) 0)
>  #define FirstOffsetNumber        ((OffsetNumber) 1)
>  #define MaxOffsetNumber            ((OffsetNumber) (BLCKSZ / sizeof(ItemIdData)))
> +#define MagicOffsetNumber        (MaxOffsetNumber + 1)
>  #define OffsetNumberMask        (0xffff)        /* valid uint16 bits */

IMHO it would be nicer if the magic value was more constant, e.g. 0xffff 
or 0xfffe, instead of basing it on MaxOffsetNumber which depends on 
block size. I would rather not include MaxOffsetNumber of anything 
derived from it in the on-disk dormat.

- Heikki




В списке pgsql-hackers по дате отправления:

Предыдущее
От: Andrew Dunstan
Дата:
Сообщение: Re: [COMMITTERS] pgsql: Move pg_upgrade from contrib/ to src/bin/
Следующее
От: Andres Freund
Дата:
Сообщение: Re: INSERT ... ON CONFLICT IGNORE (and UPDATE) 3.0