Thread: Duplicate key existant/index visibility bug in 9.3.3

Duplicate key existant/index visibility bug in 9.3.3

From
Erik Jones
Date:
Greetings,

Today I had a client report an issue restoring a dump made from their =
production db on a testing server wherein there existed two rows for a =
table with identical primary key values.  Upon investigation I found =
this to be true, but neither is visible via index usage:

(Server version: 9.3.3)

db=3D# explain select xmin, xmax, cmin, cmax, ctid, id, created_at from =
tags where id =3D 42982;
                               QUERY PLAN                               =20=

=
-------------------------------------------------------------------------
 Index Scan using groups_pkey on tags  (cost=3D0.29..8.31 rows=3D1 =
width=3D34)
   Index Cond: (id =3D 42982)
(2 rows)

db=3D# select xmin, xmax, cmin, cmax, ctid, id, created_at from tags =
where id =3D 42982;
 xmin | xmax | cmin | cmax | ctid | id | created_at=20
------+------+------+------+------+----+------------
(0 rows)

db=3D# set enable_bitmapscan =3D off;
SET
db=3D# set enable_indexscan =3D off;
SET
db=3D# explain select xmin, xmax, cmin, cmax, ctid, id, created_at from =
tags where id =3D 42982;
                       QUERY PLAN                      =20
--------------------------------------------------------
 Seq Scan on tags  (cost=3D0.00..1541.94 rows=3D1 width=3D34)
   Filter: (id =3D 42982)
(2 rows)

db=3D# select xmin, xmax, cmin, cmax, ctid, id, created_at from tags =
where id =3D 42982;
  xmin   |  xmax   | cmin | cmax |   ctid   |  id   |         created_at =
       =20
=
---------+---------+------+------+----------+-------+---------------------=
-------
 1195647 | 1195647 |    2 |    2 | (677,51) | 42982 | 2015-01-23 =
00:12:19.498942
 1195648 | 1195647 |    1 |    1 | (677,52) | 42982 | 2015-01-23 =
00:12:19.498942
(2 rows)

There are other columns on the table and all values in the two entries =
are identical.  Note that another table has a column that reference this =
table's primary key via a foreign key and there are multiple referencing =
rows there.  The last even has the same xmin as the first above:

db=3D# select xmin, xmax, cmin, cmax, ctid, id, created_at, tag_id from =
tagged_items where tag_id =3D 42982 order by xmin::text::bigint desc;
  xmin   | xmax | cmin | cmax |   ctid    |   id   |         created_at  =
       | tag_id=20
=
---------+------+------+------+-----------+--------+----------------------=
------+--------
 1195647 |    0 |    0 |    0 | (361,52)  | 130562 | 2015-01-23 =
01:14:55.809218 |  42982
 1195628 |    0 |    0 |    0 | (360,89)  | 130557 | 2015-01-23 =
01:14:55.391223 |  42982
 1195619 |    0 |    0 |    0 | (361,44)  | 130548 | 2015-01-23 =
01:14:55.252926 |  42982
 1195575 |    0 |    0 |    0 | (360,72)  | 130529 | 2015-01-23 =
01:14:54.66755  |  42982
 1195536 |    0 |    0 |    0 | (360,60)  | 130505 | 2015-01-23 =
01:14:53.841223 |  42982
 1195528 |    0 |    0 |    0 | (361,22)  | 130497 | 2015-01-23 =
01:14:53.725746 |  42982
 1195490 |    0 |    0 |    0 | (361,16)  | 130487 | 2015-01-23 =
01:14:53.21153  |  42982
 1195489 |    0 |    0 |    0 | (360,50)  | 130486 | 2015-01-23 =
01:14:53.197715 |  42982
 1195470 |    0 |    0 |    0 | (361,10)  | 130477 | 2015-01-23 =
01:14:52.896855 |  42982
 1195402 |    0 |    0 |    0 | (360,28)  | 130444 | 2015-01-23 =
01:14:52.020715 |  42982
<snip>

I'm assuming that the fact that the xmin values of the rest of the rows =
are from before those in the original table is indicative of update =
traffic since the original tags row was added and that the source of the =
problem is perhaps an update gone wrong, but let me know if I'm way off =
there.=20

So, a few questions:

1. Is there an existing bug that's been fixed by 9.3.5 that would =
account for this.  I scanned the 9.3.4 and 9.3.5 release notes and while =
the first fix listed in the release notes for 9.3.4 =
(http://www.postgresql.org/docs/9.3/static/release-9-3-4.html) was what =
gave me the idea to disable index usage to see the rows this server has =
been up and running as a master since September so neither the standby =
nor the crash recovery setup from that bug's description applies.

2. Is there any other info that I can dig up that could be helpful here?

3. Would manually deleting one of those rows (likely using the ctid to =
specify which) be safe and make the remaining one visible?  If so, I'm =
assuming I should delete the second given the xmin of the first =
referencing row in the other table?

Note that I've already confirmed that there are no other duplicate rows =
in this or other tables, at least with no clausing unique ids, via =
restore tests on a test server.  So, I know I can fix this case with a =
dump/restore but if I can get away with simply deleting one of the =
offending tuples that would be ideal (i.e. no downtime for the client).=

Re: Duplicate key existant/index visibility bug in 9.3.3

From
Tom Lane
Date:
Erik Jones <ejones@engineyard.com> writes:
> Today I had a client report an issue restoring a dump made from their
production db on a testing server wherein there existed two rows for a
table with identical primary key values.

FWIW, the simplest explanation for this situation is corruption in your
primary key index.  That's necessary to explain the rows not being visible
through an indexscan, and it's probably sufficient to explain how two rows
with the same pkey managed to get in without a unique-index failure.

So what I'd suggest is getting rid of whichever row you don't want (DELETE
WHERE ctid = something is the best way) and then doing a REINDEX on that
index.  Now, the REINDEX is going to lock out updates on the table, so
it's not a zero-downtime solution ... but it's surely better than a dump
and reload.

You should definitely also update to 9.3.5 (or next week, 9.3.6) ASAP.
Even if this specific problem isn't fixed, there's a bunch of things
that *are* fixed and will eventually bite you.  9.3.X has not been
one of our most stable release branches :-(

            regards, tom lane

Re: Duplicate key existant/index visibility bug in 9.3.3

From
Peter Geoghegan
Date:
On Mon, Jan 26, 2015 at 2:19 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
> You should definitely also update to 9.3.5 (or next week, 9.3.6) ASAP.
> Even if this specific problem isn't fixed, there's a bunch of things
> that *are* fixed and will eventually bite you.  9.3.X has not been
> one of our most stable release branches :-(

I didn't consider the bug report in detail, but I think it's likely
that this was in fact the bug fixed by
6bfa88acd3df830a5f7e8677c13512b1b50ae813.


--
Peter Geoghegan

Re: Duplicate key existant/index visibility bug in 9.3.3

From
Erik Jones
Date:
Thanks for the info, guys!

> On Jan 26, 2015, at 2:31 PM, Peter Geoghegan <pg@heroku.com> wrote:
>
> On Mon, Jan 26, 2015 at 2:19 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> You should definitely also update to 9.3.5 (or next week, 9.3.6) ASAP.
>> Even if this specific problem isn't fixed, there's a bunch of things
>> that *are* fixed and will eventually bite you.  9.3.X has not been
>> one of our most stable release branches :-(
>
> I didn't consider the bug report in detail, but I think it's likely
> that this was in fact the bug fixed by
> 6bfa88acd3df830a5f7e8677c13512b1b50ae813.
>
>
> --
> Peter Geoghegan

Re: Duplicate key existant/index visibility bug in 9.3.3

From
Tom Lane
Date:
Peter Geoghegan <pg@heroku.com> writes:
> On Mon, Jan 26, 2015 at 2:19 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> You should definitely also update to 9.3.5 (or next week, 9.3.6) ASAP.
>> Even if this specific problem isn't fixed, there's a bunch of things
>> that *are* fixed and will eventually bite you.  9.3.X has not been
>> one of our most stable release branches :-(

> I didn't consider the bug report in detail, but I think it's likely
> that this was in fact the bug fixed by
> 6bfa88acd3df830a5f7e8677c13512b1b50ae813.

Maybe.  That would require at least one crash recovery to have happened on
the server, which Erik seemed to be claiming had not happened.  But
if there were any crashes then it would possibly fit.

            regards, tom lane

Re: Duplicate key existant/index visibility bug in 9.3.3

From
Erik Jones
Date:
On Jan 26, 2015, at 2:43 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>=20
> Peter Geoghegan <pg@heroku.com> writes:
>> On Mon, Jan 26, 2015 at 2:19 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>>> You should definitely also update to 9.3.5 (or next week, 9.3.6) =
ASAP.
>>> Even if this specific problem isn't fixed, there's a bunch of things
>>> that *are* fixed and will eventually bite you.  9.3.X has not been
>>> one of our most stable release branches :-(
>=20
>> I didn't consider the bug report in detail, but I think it's likely
>> that this was in fact the bug fixed by
>> 6bfa88acd3df830a5f7e8677c13512b1b50ae813.
>=20
> Maybe.  That would require at least one crash recovery to have =
happened on
> the server, which Erik seemed to be claiming had not happened.  But
> if there were any crashes then it would possibly fit.

Definitely nothing recent crash/recovery-wise but digging further back =
in the logs it looks like there was a crash recovery run startup back on =
2014-09-30, which was about a week after this server was created.  I =
suppose it=E2=80=99s possible that the index has been corrupt since then =
but only now showing something visible?=

Re: Duplicate key existant/index visibility bug in 9.3.3

From
Tom Lane
Date:
Erik Jones <ejones@engineyard.com> writes:
> On Jan 26, 2015, at 2:43 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:
>> Maybe.  That would require at least one crash recovery to have happened on
>> the server, which Erik seemed to be claiming had not happened.  But
>> if there were any crashes then it would possibly fit.

> Definitely nothing recent crash/recovery-wise but digging further back in the logs it looks like there was a crash
recoveryrun startup back on 2014-09-30, which was about a week after this server was created.  I suppose it’s
possiblethat the index has been corrupt since then but only now showing something visible? 

Doesn't fit this specific bug fix --- the case it addresses would cause
already-existing rows to become unreachable from the index during crash
recovery.  AFAICS that could not create a latent problem for rows inserted
later.  Still, this isn't the only bug fixed in 9.3.4/9.3.5.  Personally
I'm wondering about c0bd128c81c2b23a1cbc53305180fca51b3b61c3.

I'll try to refrain from asking why a server initdb'd in September wasn't
running 9.3.5 from inception.

            regards, tom lane

Re: Duplicate key existant/index visibility bug in 9.3.3

From
Andres Freund
Date:
On 2015-01-26 18:04:31 -0500, Tom Lane wrote:
> Doesn't fit this specific bug fix --- the case it addresses would cause
> already-existing rows to become unreachable from the index during crash
> recovery.  AFAICS that could not create a latent problem for rows inserted
> later.

I think there were cases where it could essentially do that due to hot
pruning ending up doing strange things due to the corrupted chains. But
I don't think that's the most likely explanation.

> Still, this isn't the only bug fixed in 9.3.4/9.3.5.  Personally I'm
> wondering about c0bd128c81c2b23a1cbc53305180fca51b3b61c3.

Yes, imo that bug would explain the symptoms perfectly - the cases that
lead to the discovery of that bug pretty much looked that way IIRC.

Greetings,

Andres Freund

--
 Andres Freund                       http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services