Thread: please help me recover from duplicate key in unique index

please help me recover from duplicate key in unique index

From
Charles Martin
Date:
Please help me recover our database from what I think
is a duplicate key in unique index problem.

We have a table of the following form:

    create table foo (id serial primary key, x
integer)

in our code we had, outside of any BEGIN/COMMIT block:

    insert into foo (x) values (...)

Without the transaction block, I believe we have had
duplicate keys inserted.  I've fixed the bug in the
code, but now I need to fix the database!

When I try to vacuum, I get this:

> vacuum;
NOTICE:  Rel sessions: TID 5/2: OID IS INVALID.
TUPGONE 1.
NOTICE:  Rel sessions: TID 5/6: OID IS INVALID.
TUPGONE 1.
NOTICE:  Rel sessions: TID 13/2: OID IS INVALID.
TUPGONE 1.
NOTICE:  Rel sessions: TID 13/6: OID IS INVALID.
TUPGONE 1.
ERROR:  Cannot insert a duplicate key into a unique
index

When I try to dump it out (to manually repair it), I
get this:

$ pg_dump gtmd000103 > gtmd.1
pqWait() -- connection not open
PQendcopy: resetting connection
SQL query to dump the contents of Table 'content' did
not execute correctly.  After we read all the table
contents from the backend, PQendcopy() failed.
Explanation from backend: 'pqWait() -- connection not
open
'.
The query was: 'COPY "content" TO stdout;
'.

Can anybody help me?  I am desperate.  Thanks.

Charles

__________________________________________________
Do You Yahoo!?
Talk to your friends online with Yahoo! Messenger.
http://messenger.yahoo.com

Re: [GENERAL] please help me recover from duplicate key in unique index

From
Bruce Momjian
Date:
Try:

SELECT oid, *
FROM table
GROUP BY oid
HAVING count(*) > 1

that should show your duplicates, and you can remove them using
table.oid = _bad_number_.

> Please help me recover our database from what I think
> is a duplicate key in unique index problem.
>
> We have a table of the following form:
>
>     create table foo (id serial primary key, x
> integer)
>
> in our code we had, outside of any BEGIN/COMMIT block:
>
>     insert into foo (x) values (...)
>
> Without the transaction block, I believe we have had
> duplicate keys inserted.  I've fixed the bug in the
> code, but now I need to fix the database!
>
> When I try to vacuum, I get this:
>
> > vacuum;
> NOTICE:  Rel sessions: TID 5/2: OID IS INVALID.
> TUPGONE 1.
> NOTICE:  Rel sessions: TID 5/6: OID IS INVALID.
> TUPGONE 1.
> NOTICE:  Rel sessions: TID 13/2: OID IS INVALID.
> TUPGONE 1.
> NOTICE:  Rel sessions: TID 13/6: OID IS INVALID.
> TUPGONE 1.
> ERROR:  Cannot insert a duplicate key into a unique
> index
>
> When I try to dump it out (to manually repair it), I
> get this:
>
> $ pg_dump gtmd000103 > gtmd.1
> pqWait() -- connection not open
> PQendcopy: resetting connection
> SQL query to dump the contents of Table 'content' did
> not execute correctly.  After we read all the table
> contents from the backend, PQendcopy() failed.
> Explanation from backend: 'pqWait() -- connection not
> open
> '.
> The query was: 'COPY "content" TO stdout;
> '.
>
> Can anybody help me?  I am desperate.  Thanks.
>
> Charles
>
> __________________________________________________
> Do You Yahoo!?
> Talk to your friends online with Yahoo! Messenger.
> http://messenger.yahoo.com
>
> ************
>
>


--
  Bruce Momjian                        |  http://www.op.net/~candle
  maillist@candle.pha.pa.us            |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: [GENERAL] please help me recover from duplicate key in unique index

From
Jim Mercer
Date:
On Tue, Jan 04, 2000 at 06:47:39PM -0500, Bruce Momjian wrote:
> Try:
>
> SELECT oid, *
> FROM table
> GROUP BY oid
> HAVING count(*) > 1
>
> that should show your duplicates, and you can remove them using
> table.oid = _bad_number_.

ah, i thought each row had a unique oid, and thus, that query wouldn't show the
duplicate content.

i would do something like:

SELECT keyfield FROM tablename GROUP BY keyfield HAVING COUNT(*) > 1;

this will produce a list of rows where keyfield is not unique in tablename.

then, for each of those entries, you want to do a:

SELECT oid, keyfield, other fields FROM tablename WHERE keyfield = <value>;

then you can select which duplicate you want to nuke, and do:

DELETE FROM tablename WHERE OID = 999999;

(i've found that creating an index, non-unique for performance sake) on oid will
improve the preformance of duplicate nukes on really big tables)

mind you, the above process, on a large table is gonna be slow anyways.

--
[ Jim Mercer                 jim@reptiles.org              +1 416 506-0654 ]
[          Reptilian Research -- Longer Life through Colder Blood          ]
[  Don't be fooled by cheap Finnish imitations; BSD is the One True Code.  ]

Re: [GENERAL] please help me recover from duplicate key in unique index

From
Bruce Momjian
Date:
> On Tue, Jan 04, 2000 at 06:47:39PM -0500, Bruce Momjian wrote:
> > Try:
> >
> > SELECT oid, *
> > FROM table
> > GROUP BY oid
> > HAVING count(*) > 1
> >
> > that should show your duplicates, and you can remove them using
> > table.oid = _bad_number_.
>
> ah, i thought each row had a unique oid, and thus, that query wouldn't show the
> duplicate content.
>

Oh, I thought they were using oid's for keys.  I see now.  Yes, you are
correct.


--
  Bruce Momjian                        |  http://www.op.net/~candle
  maillist@candle.pha.pa.us            |  (610) 853-3000
  +  If your life is a hard drive,     |  830 Blythe Avenue
  +  Christ can be your backup.        |  Drexel Hill, Pennsylvania 19026

Re: [GENERAL] please help me recover from duplicate key in unique index

From
Ed Loehr
Date:
With a SERIAL type, which translates to a unique index, I'm still wondering how
this duplication could occur in the first place...

Is this a known failure scenario?  A bug?

Cheers,
Ed Loehr




Re: [GENERAL] please help me recover from duplicate key in unique index

From
Ed Loehr
Date:
Charles Martin wrote:

> Please help me recover our database from what I think
> is a duplicate key in unique index problem.

This may not help, and forgive my asking the obvious, but have
you done a SELECT on the table and actually *seen* duplicate 'id'
values in the SERIAL column?  That would surprise me because I
didn't think it was possible to create duplicates in the scenario
you describe.  The SERIAL type is really just a sequence, and its
values are unique across all transactions (I hope!).  IIRC there
is some opportunity for wierdness if the sequence cache setting
has been "adjusted" incorrectly
(http://www.postgresql.org/docs/postgres/sql-createsequence.htm).



> When I try to vacuum, I get this:
>
> ERROR:  Cannot insert a duplicate key into a unique
> index
>

I didn't realize vacuum tried to insert anything.  Maybe a system
table insert?

Cheers,
Ed Loehr



Re: [GENERAL] please help me recover from duplicate key in unique index

From
Adriaan Joubert
Date:
> > Please help me recover our database from what I think
> > is a duplicate key in unique index problem.
>
> This may not help, and forgive my asking the obvious, but have
> you done a SELECT on the table and actually *seen* duplicate 'id'
> values in the SERIAL column?  That would surprise me because I
> didn't think it was possible to create duplicates in the scenario
> you describe.  The SERIAL type is really just a sequence, and its
> values are unique across all transactions (I hope!).  IIRC there
> is some opportunity for wierdness if the sequence cache setting
> has been "adjusted" incorrectly
> (http://www.postgresql.org/docs/postgres/sql-createsequence.htm).
>
> > When I try to vacuum, I get this:
> >
> > ERROR:  Cannot insert a duplicate key into a unique
> > index
> >

Try dropping all indexes on the table, do a vacuum (if it will let you).
Dump the table out with pg_dump -t <t_name> if it will let you, sort it
in emacs or with perl. Easiest thing would then be to write a little
perl script that puts all duplicate rows into a separate file. Dropt the
table and re-create it. Load the first lot up (with given sequence
number!), fix your sequences (drop, create ..start <max-seq>) and then
handle the duplicate rows (i.e. insert them with perl/DBI or something
so that they get new sequence numbers assigned).

I think you should be able to dump once you have dropped all indexes
(probably one of them is <tab-name>_pkey). Your sequence may be called
<tab-name>_<col-name>_seq if memeory serves me right. It is still a
normal sequences and you can drop and recreate it safely.

Good luck,

Adriaan