SERIAL behaviour

Started by Eugeneover 23 years ago8 messagesgeneral
Jump to latest
#1Eugene
foo@bar.com

Hi everyone,

I am new to PostgreSQL and I am using it in PHP application. For the most
part, I like it a lot. However, I am quite dismayed by the behavior of the
SERIAL type, or, more specifically, the PostgreSQL sequences.

I have three tables where table1 has its primary key of type SERIAL. Two
other tables use that same id (of type integer) as a foreign key (and also
part of the compound primary key). When inserting a new record, I have the
code that essentially looks like this:

BEGIN
id = nextval('sequence');
insert_in_table1(id, data1);
insert_in_table2(id, data2);
insert_in_table3(id, data3);

if( success ) {
COMMIT
} else {
ROLLBACK
}

The problem is that on a rollback, the value of the sequence does not go
back to its previous value! I know that I can use setval() to adjust the
value of the sequence, but that's not a solution I like. I expect ROLLBACK
to bring the database to the state it was before BEGIN, but that's not what
happens! What is the proper way to handle this? Also, how can I ensure
consistency when multiple clients are changing the same tables? (sequence
doesn't seem to be part of the transaction...)

thanks in advance,

Eugene

-------------------------------------------------------------------
eestrulyov at uwaterloo dot ca

#2Steve Brett
SBrett@e-mis.com
In reply to: Eugene (#1)
Re: SERIAL behaviour

i use php and postgresql a lot.

the behaviour of the sequence is ok as they are there to generate sequences
of values mainly to be used as keys.

point 1.

it's not really reasonable to expect a sequence to rollback as in a multi
user system it would be practicly impossible to 'track' all users and
sessions and transactions etc so that the values were consecutive or indeed
in a consistent state after a rollback as you mention.

the database itself will be in a consistent state when you rollback a
transaction and if fresh values are generated for your sequence then i don't
understand what the problem would be.

point 2.

as far as i am aware sequence values are safe within transactions. the app i
developed at work hold calendar information, bookings, appointments, reports
etc for 500 people and has been running for 18 motnhs with no problems. it
uses sequence values for all appointment inserts (over 100k so far) and i
have never had a problem with a duplicate value being given to 2 users. i
think i read somewhere that sequences are safe for multiple users but can't
remember where ...

i would suggest that the proper way to handle it is to not bother worrying.

Steve

Show quoted text

-----Original Message-----
From: Eugene [mailto:foo@bar.com]
Sent: 14 July 2002 02:59
To: pgsql-general@postgresql.org
Subject: [GENERAL] SERIAL behaviour

Hi everyone,

I am new to PostgreSQL and I am using it in PHP application.
For the most
part, I like it a lot. However, I am quite dismayed by the
behavior of the
SERIAL type, or, more specifically, the PostgreSQL sequences.

I have three tables where table1 has its primary key of type
SERIAL. Two
other tables use that same id (of type integer) as a foreign
key (and also
part of the compound primary key). When inserting a new
record, I have the
code that essentially looks like this:

BEGIN
id = nextval('sequence');
insert_in_table1(id, data1);
insert_in_table2(id, data2);
insert_in_table3(id, data3);

if( success ) {
COMMIT
} else {
ROLLBACK
}

The problem is that on a rollback, the value of the sequence
does not go
back to its previous value! I know that I can use setval() to
adjust the
value of the sequence, but that's not a solution I like. I
expect ROLLBACK
to bring the database to the state it was before BEGIN, but
that's not what
happens! What is the proper way to handle this? Also, how can
I ensure
consistency when multiple clients are changing the same
tables? (sequence
doesn't seem to be part of the transaction...)

thanks in advance,

Eugene

-------------------------------------------------------------------
eestrulyov at uwaterloo dot ca

---------------------------(end of
broadcast)---------------------------
TIP 2: you can get off all lists at once with the unregister command
(send "unregister YourEmailAddressHere" to
majordomo@postgresql.org)

#3Christoph Dalitz
christoph.dalitz@hs-niederrhein.de
In reply to: Steve Brett (#2)
Re: SERIAL behaviour

However, I am quite dismayed by the behavior of the
SERIAL type, or, more specifically, the PostgreSQL sequences.

The problem is that on a rollback, the value of the sequence does not go
back to its previous value!

If I understand SEQUENCEs right, that should be the expected behaviour:
Sequences generate values that are unique both in space (ie. other users/transactions)
and time. Thus they must not be rescrewed in case of ROLLBACK.

Also, how can I ensure
consistency when multiple clients are changing the same tables? (sequence
doesn't seem to be part of the transaction...)

That sequences are not "part of the transaction" actually guarantees
consistency among multiple clients.

Christoph Dalitz

#4Curt Sampson
cjs@cynic.net
In reply to: Eugene (#1)
Re: SERIAL behaviour

On Sat, 13 Jul 2002, Eugene wrote:

The problem is that on a rollback, the value of the sequence does not go
back to its previous value!

And this is a big efficiency win. Say you get sequence number 100.
You start your work, and while you're chugging along, three other
transactions also start, and also request sequence numbers, getting
101, 102 and 103. If you then rollback your transaction, you can't put
the sequence number back to 100 unless you force the following three
transactions also to abort.

Alternatively, you could lock the sequence while the transaction is
running, but then numbers 101, 102 and 103 would have to wait for your
number 100 transaction to commit or roll back before they could even
start to work, thus slowing down the system.

cjs
--
Curt Sampson <cjs@cynic.net> +81 90 7737 2974 http://www.netbsd.org
Don't you know, in this new Dark Age, we're all light. --XTC

#5Adrian von Bidder
avbidder@fortytwo.ch
In reply to: Eugene (#1)
Re: SERIAL behaviour

On Sun, 2002-07-14 at 03:59, Eugene wrote:
[ SERIAL type / SEQUENCEs and transactions ]

Closely related: what's the official/preferred way if I'm inserting rows
into a table with a auto assigned id (SERIAL), to get the newly created
id? asking the sequence obviously will not work - as the sequence will
advance when the next value is inserted from another transaction.

cheers
-- vbi

--
secure email with gpg http://fortytwo.ch/gpg

#6Steve Brett
SBrett@e-mis.com
In reply to: Adrian von Bidder (#5)
Re: SERIAL behaviour

you can use currval() to get the current value of a sequence.

however if your key value is set to serial and it's default is the nextval
then don't reference it in your insert i.e.

insert into foo(forename,surname) values ('Steve','Brett');

where the key for foo is an id of type serial.

currval() 'should' be safe for use within transactions.

Steve

Show quoted text

-----Original Message-----
From: Adrian 'Dagurashibanipal' von Bidder
[mailto:avbidder@fortytwo.ch]
Sent: 15 July 2002 14:47
To: pgsql-general@postgresql.org
Subject: Re: [GENERAL] SERIAL behaviour

On Sun, 2002-07-14 at 03:59, Eugene wrote:
[ SERIAL type / SEQUENCEs and transactions ]

Closely related: what's the official/preferred way if I'm
inserting rows
into a table with a auto assigned id (SERIAL), to get the
newly created
id? asking the sequence obviously will not work - as the sequence will
advance when the next value is inserted from another transaction.

cheers
-- vbi

--
secure email with gpg http://fortytwo.ch/gpg

#7Martijn van Oosterhout
kleptog@svana.org
In reply to: Adrian von Bidder (#5)
Re: SERIAL behaviour

On Mon, Jul 15, 2002 at 03:47:28PM +0200, Adrian 'Dagurashibanipal' von Bidder wrote:

On Sun, 2002-07-14 at 03:59, Eugene wrote:
[ SERIAL type / SEQUENCEs and transactions ]

Closely related: what's the official/preferred way if I'm inserting rows
into a table with a auto assigned id (SERIAL), to get the newly created
id? asking the sequence obviously will not work - as the sequence will
advance when the next value is inserted from another transaction.

You read the documentation and notice that currval() is not affected by
nextval()s executed upon other connections. In other words, it's a complete
non-issue and works exectly the way that is useful.
--
Martijn van Oosterhout <kleptog@svana.org> http://svana.org/kleptog/

Show quoted text

There are 10 kinds of people in the world, those that can do binary
arithmetic and those that can't.

#8Adrian von Bidder
avbidder@fortytwo.ch
In reply to: Martijn van Oosterhout (#7)
Re: SERIAL behaviour

On Mon, 2002-07-15 at 16:07, Martijn van Oosterhout wrote:

On Mon, Jul 15, 2002 at 03:47:28PM +0200, Adrian 'Dagurashibanipal' von Bidder wrote:

On Sun, 2002-07-14 at 03:59, Eugene wrote:
[ SERIAL type / SEQUENCEs and transactions ]

Closely related: what's the official/preferred way if I'm inserting rows
into a table with a auto assigned id (SERIAL), to get the newly created
id? asking the sequence obviously will not work - as the sequence will
advance when the next value is inserted from another transaction.

You read the documentation and notice that currval() is not affected by
nextval()s executed upon other connections. In other words, it's a complete
non-issue and works exectly the way that is useful.

Ok, thanks (and sorry for not rtfm in this case). Unexpected, but, yes,
useful.

cheers
-- vbi

--
secure email with gpg http://fortytwo.ch/gpg