| From: | Andres Freund <andres(at)2ndquadrant(dot)com> | 
|---|---|
| To: | Tom Lane <tgl(at)sss(dot)pgh(dot)pa(dot)us> | 
| Cc: | Oliver Seemann <oseemann(at)gmail(dot)com>, pgsql-bugs(at)postgresql(dot)org | 
| Subject: | Re: Update with subselect sometimes returns wrong result | 
| Date: | 2013-11-30 21:40:18 | 
| Message-ID: | 20131130214018.GJ31100@awork2.anarazel.de | 
| Views: | Whole Thread | Raw Message | Download mbox | Resend email | 
| Thread: | |
| Lists: | pgsql-bugs | 
On 2013-11-30 12:57:44 -0500, Tom Lane wrote:
> Oliver Seemann <oseemann(at)gmail(dot)com> writes:
> > Given the following table:
> 
> > CREATE TABLE t1 (id INTEGER);
> > INSERT INTO t1 VALUES (0), (1);
> 
> > Then the following UPDATE should return exactly one row:
> 
> > UPDATE t1 SET id = t1.id
> > FROM (SELECT id FROM t1 LIMIT 1 FOR UPDATE) AS subset
> > WHERE t1.id = subset.id
> > RETURNING t1.id
> 
> > And it does so, most of of the time. But when run repeatedly in a loop like
> > in the attached script, then it will occasionally return 2 rows with two
> > different id values, something the LIMIT 1 should prevent. In my tests it
> > took from anywhere between 0 to 10 minutes and on average 1 to 2 minutes to
> > trigger the problem.
> 
> I failed to reproduce the claimed misbehavior in git tip of any active
> branch.  I'd like to think this means we fixed the problem in the last
> two months, but I don't see anything that looks like a promising candidate
> in the commit logs.  Perhaps there is some important contributing factor
> you've not mentioned --- nondefault postgresql.conf settings, for
> instance.
Looks reproducable here as well, manually executing VACUUMs on the table
greatly speeds things up. Fails within seconds when doing so.
So, it looks like the limit returns more than one row, it's not updating
the same row twice.
Slightly hacked up (probably python 2 only) version of the test script
attached. I'll get to trying to write the release stuff rather then
playing with more interesting things ;)
new row at:  (0,4)
updated row from (0,2) to (0,1) iter 400 
deleted row at:  (0,1)
deleted row at:  (0,5)
new row at:  (0,1)
new row at:  (0,5)
updated row from (0,1) to (0,3) iter 401 
deleted row at:  (0,2)
deleted row at:  (0,3)
new row at:  (0,2)
new row at:  (0,3)
updated row from (0,1) to (0,3) iter 402 
deleted row at:  (0,2)
deleted row at:  (0,3)
new row at:  (0,2)
new row at:  (0,3)
updated row from (0,4) to (0,1) iter 403 
deleted row at:  (0,1)
deleted row at:  (0,5)
new row at:  (0,1)
new row at:  (0,5)
updated row from (0,1) to (0,3) iter 404 
deleted row at:  (0,2)
deleted row at:  (0,3)
new row at:  (0,2)
new row at:  (0,3)
updated row from (0,1) to (0,3) iter 405 
deleted row at:  (0,2)
deleted row at:  (0,3)
new row at:  (0,2)
new row at:  (0,3)
updated row from (0,4) to (0,6) iter 406 
...
deleted row at:  (0,2)
deleted row at:  (0,3)
new row at:  (0,2)
new row at:  (0,3)
updated row from (0,4) to (0,1) iter 447 
updated row from (0,5) to (0,2) iter 447 
Traceback (most recent call last):
  File "/tmp/pgbug.py", line 80, in <module>
    test_bug()
  File "/tmp/pgbug.py", line 51, in test_bug
    update(cur, i)
  File "/tmp/pgbug.py", line 76, in update
    assert(len(rows) == 1)
AssertionError
There's clearly something wrong. (0,4) has been updated several times,
but seems to still be visible.
Greetings,
Andres Freund
-- 
 Andres Freund	                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
| Attachment | Content-Type | Size | 
|---|---|---|
| pgbug.py | text/plain | 2.3 KB | 
| From | Date | Subject | |
|---|---|---|---|
| Next Message | David Johnston | 2013-12-01 03:00:01 | Re: Update with subselect sometimes returns wrong result | 
| Previous Message | Peter Eisentraut | 2013-11-30 21:07:11 | Re: Re: [BUGS] BUG #7873: pg_restore --clean tries to drop tables that don't exist |