Re: [HACKERS] Bogus "Non-functional update" notices - Mailing list pgsql-hackers

From Tom Lane
Subject Re: [HACKERS] Bogus "Non-functional update" notices
Date
Msg-id 2011.901584613@sss.pgh.pa.us
Whole thread Raw
In response to Re: [HACKERS] Bogus "Non-functional update" notices  ("Thomas G. Lockhart" <lockhart@alumni.caltech.edu>)
List pgsql-hackers
I wrote:
>> With fairly current sources (last cvs update on 7/20), I am seeing
>> occasional occurrences of
>>    NOTICE:  Non-functional update, only first update is performed

I have been digging into this some more, and I am getting more and more
convinced that there is a significant underlying bug.

What I've discovered is that in the cases where this message appears
(which, again, is only once every few hundred tries) the update scan
is *finding the same tuple twice*.  The second time through, the tuple
has already been marked as deleted by the current command, and it is
this marking that causes heap_replace to emit the "Non-functional
update" warning and return without processing the tuple.

An example trace is

QUERY: BEGIN TRANSACTION; LOCK marketorderhistory
RESULT: DELETE 0
QUERY: UPDATE marketorderhistory SET completionTime = '1998-05-11 20:00:00 GMT' WHERE oid = 34900::oid AND
completionTimeIS NULL 
NOTICE:  heap_replace OID 34900  t_xmin 20270 t_xmax 0  t_cmin 6 t_cmax 0
NOTICE:  heap_replace OID 34900  t_xmin 20270 t_xmax 20496  t_cmin 6 t_cmax 3
NOTICE:  Non-functional update, only first update is performed
NOTICE:  current trans ID 20496  cmd id 3 scan id 3
RESULT: UPDATE 1

(The "NOTICE:  heap_replace" lines are from debug code I added to print
ID info about the tuple found by heap_replace.  This is printed every
time through the routine, just before the non-functional-update test.
The "NOTICE: current trans" line is printed only if the test triggers.)

In this particular situation, the only bad consequence is the display
of a bogus notice message, but it seems to me that having a scan find
the same tuple multiple times is a Very Bad Thing.  (If the test in
heap_replace really is intended to clean up after this condition,
then it ought not be emitting a message.)

I have only seen this happen when the UPDATE was using an index scan to
find the tuples to update (the table in this example has a btree index
on oid).  So, somehow the index is returning the same tuple more than
once.

I have managed to construct a simple, if not quick, test case that
repeatably causes an instance of the bogus message --- it's attached in
the form of a pgTcl script.  The trace (from my backend with extra
printout) looks like

...
NOTICE:  heap_replace OID 87736  t_xmin 113200 t_xmax 0  t_cmin 0 t_cmax 0
NOTICE:  heap_replace OID 87735  t_xmin 113199 t_xmax 0  t_cmin 0 t_cmax 0
NOTICE:  heap_replace OID 87734  t_xmin 113198 t_xmax 0  t_cmin 0 t_cmax 0
NOTICE:  heap_replace OID 87734  t_xmin 113198 t_xmax 113601  t_cmin 0 t_cmax 0
NOTICE:  Non-functional update, only first update is performed
NOTICE:  current trans ID 113601  cmd id 0 scan id 0
NOTICE:  heap_replace OID 87733  t_xmin 113197 t_xmax 0  t_cmin 0 t_cmax 0
NOTICE:  heap_replace OID 87732  t_xmin 113196 t_xmax 0  t_cmin 0 t_cmax 0
...
where the failure occurs at the 200th UPDATE command.

            regards, tom lane

#!/usr/local/pgsql/bin/pgtclsh

set pgconn [pg_connect play]

set res [pg_exec $pgconn \
    "DROP TABLE updatebug"]
pg_result $res -clear

set res [pg_exec $pgconn \
    "CREATE TABLE updatebug (key int4 not null, val int4)"]
pg_result $res -clear

set res [pg_exec $pgconn \
    "CREATE UNIQUE INDEX updatebug_i ON updatebug USING btree(key)"]
pg_result $res -clear

for {set i 0} {$i <= 10000} {incr i} {
    set res [pg_exec $pgconn "INSERT INTO updatebug VALUES($i, NULL)"]
    pg_result $res -clear
}

# Vacuum to ensure that optimizer will decide to use index for updates...
set res [pg_exec $pgconn \
    "VACUUM VERBOSE ANALYZE updatebug"]
pg_result $res -clear

puts "table built..."

for {set i 10000} {$i >= 0} {incr i -1} {
    set res [pg_exec $pgconn \
        "UPDATE updatebug SET val = 1 WHERE key = $i"]
    pg_result $res -clear
}

pgsql-hackers by date:

Previous
From: Vadim Mikheev
Date:
Subject: Re: [HACKERS] Q about read committed in Oracle...
Next
From: t-ishii@sra.co.jp
Date:
Subject: Re: [HACKERS] current snapshot