Re: duplicate key violates unique constraint

From: Carol Walter <walterc(at)indiana(dot)edu>
To: "Spiegelberg, Greg" <gspiegelberg(at)isodxsolutions(dot)com>
Cc: <pgsql-admin(at)postgresql(dot)org>
Subject: Re: duplicate key violates unique constraint
Date: 2007-05-10 14:01:16
Message-ID: 3368550B-3BE3-4754-8F72-BD36AE4EDF5F@indiana.edu
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-admin

Greg,

Since Postgres allows you to insert a value into a field that is
designated as a sequence number, is it possible that one was entered
that the sequence tried to recreate?

And this is more than a question than an answer, but I thought that
sequences had to designated as data type "serial."

Carol Walter

On May 10, 2007, at 9:38 AM, Spiegelberg, Greg wrote:

> List,
>
> We're using 8.2.1 in RedHat ES 4 here and I have a simple two
> column table: data_keys1.
>
> Table "public.data_keys1"
> Column | Type | Modifiers
> --------+--------
> +---------------------------------------------------------
> id | bigint | not null default nextval
> ('data_keys1_id_seq'::regclass)
> key1 | text |
> Indexes:
> "data_keys1_pkey" PRIMARY KEY, btree (id)
> I also have a C program using libpq that populates this table via a
> PREPARE'd statement within a transaction. Recently, while this
> table was being loaded, it encountered an error I hadn't seen
> before and is a bit confusing.
>
> 2007-05-09 09:27:07 EDT [22853] : LOG: statement: EXECUTE
> insertKey1('vgdisplay');
> 2007-05-09 09:27:07 EDT [22853] : DETAIL: prepare: PREPARE
> insertKey1(text) AS INSERT INTO public.data_keys1 (key1) values ($1);
> 2007-05-09 09:27:07 EDT [22853] : ERROR: duplicate key violates
> unique constraint "data_keys1_pkey"
> 2007-05-09 09:27:07 EDT [22853] : STATEMENT: EXECUTE insertKey1
> ('vgdisplay');
>
> As you can see, it's only providing the key1 column and the
> sequence is providing the value for the column with the
> constraint. How can this be happening? There were no other
> transactions, commits, individual inserts happenning at the same
> time or within several seconds of this one.
>
> I'd like to explore sequences a bit more b/c as they are
> implemented in PostgreSQL is a little confusing. Normally, I'd
> start another thread but it may have some bearing here.
>
>
> Sequences...
>
> Now, I don't know if this just hasn't been tested or is a
> documented feature (a.k.a. bug) but something does not seem right
> here. In this test case I'm able to get the same sequence ID's via
> two psql connections to the same database on the same sequence.
>
> Connect to "db" in two different psql sessions (I'll prefix them
> below with 1: and 2:) and in one create the table
>
> 1: db=# CREATE TABLE t1 ( s serial, i int);
> 1: db=# \d t1
> Table "public.t1"
> Column | Type | Modifiers
> --------+---------+------------------------------------------------
> s | integer | not null default nextval('t1_s_seq'::regclass)
> i | integer |
>
> 1: db=# SELECT * FROM t1_s_seq;
> sequence_name | last_value | increment_by | max_value |
> min_value | cache_value | log_cnt | is_cycled | is_called
> ---------------+------------+--------------+---------------------
> +-----------+-------------+---------+-----------+-----------
> t1_s_seq | 12 | 1 | 9223372036854775807
> | 1 | 1 | 32 | f | t
> (1 row)
>
> So, cache on t1_s_seq is set to 1. Not sure why the max_value is
> so high when the column was specified as a 'serial' not a 'serial8'
> but perhaps I should check the code out and submit a patch for
> that. I digress.
>
> Check out the value for t1_s_seq on connection #1.
>
> 1: db=# select nextval('t1_s_seq');
> nextval
> ---------
> 1
> (1 row)
>
> And check the value for t1_s_seq on connection #2.
>
> 2: db=# select nextval('t1_s_seq');
> nextval
> ---------
> 2
> (1 row)
>
> So far, so good. Now start a transaction on connection #1, advance
> t1_s_seq by 10 but don't commit;
>
> 1: db=# begin;
> BEGIN
> 1: db=# select setval('t1_s_seq', currval('t1_s_seq')+10);
> setval
> --------
> 11
> (1 row)
>
> And check the current value for t1_s_seq on connection #2.
>
> 2: db=# select currval('t1_s_seq');
> nextval
> ---------
> 2
> (1 row)
>
>
> That's expected since the transaction on connection #1 hasn't been
> commited. Now commit the transaction on connection #1 and check
> it's current value.
>
> 1: db=# commit;
> COMMIT
> 1: db=# select currval('t1_s_seq');
> currval
> ---------
> 11
> (1 row)
>
> Again, expected. Now let's check the current value on connection
> #2 again.
>
> 2: db=# select currval('t1_s_seq');
> currval
> ---------
> 2
> (1 row)
>
> This is where I take issue with the output. I'm not sure what
> benefit cache value has as the client should, in this case,
> consulted with the backend as too the value of the sequence.
>
> Sequences are suppose to be unique but in this case it seems that
> may not always be the case. Sequences have some kind of odd
> relationship (no pun intended) with transactions in that they are
> in some cases in sync regardless of the connection or query and in
> other situations, such as above, are out of sync.
>
> Just for fun, select on connection #2 the nextval of the sequence.
>
> 2: db=# select nextval('t1_s_seq');
> nextval
> ---------
> 12
> (1 row)
>
> *boogle*
>
> What have I done wrong here? Does it have any bearing on my unique
> constraint error? I wouldn't think so but I haven't found any
> other possible explanation.
>
> TIA,
> Greg
>
> --
> Greg Spiegelberg
> Manager, Product Development
> ISOdx Solutions, a division of Cranel, Inc.
> gspiegelberg(at)isodxsolutions(dot)com
> 614.318.4314, office
> 614.431.8388, fax
>
>
>

In response to

Responses

Browse pgsql-admin by date

  From Date Subject
Next Message Kris Deugau 2007-05-10 14:31:15 Re: Issue with upgrade
Previous Message Cédric Villemain 2007-05-10 13:43:42 Re: Copying schemas between databases