In this posting I would like to describe some important aspects of PostgreSQL sequences. In our daily work we have noticed that some people are not fully aware of those implications described in this section.

Database sequences are database objects from which multiple users can generate unique numbers. Unique means that there are no duplicates – it does not mean that you cannot have gaps.

Creating and using sequences

Before we dive head on into transactions we can simply create a sequence:

test=# CREATE SEQUENCE seq_a;
CREATE SEQUENCE

In the next step we can simply increment the sequence and fetch values:

test=# SELECT nextval('seq_a');
 nextval
---------
 1
(1 row)

PostgreSQL will return one value after the other from the sequence:

test=# SELECT nextval('seq_a');
 nextval
--------- 
 2
(1 row)

 

Taking care of PostgreSQL transactions

The most important thing you have to keep in mind when using sequences is that they provide ascending numbers, BUT those numbers are in no way uninterrupted. Here is an example:

test=# BEGIN;
BEGIN

test=# SELECT nextval('seq_a');
 nextval
---------
 3
(1 row)

test=# ROLLBACK;
ROLLBACK

We start a transaction and perform a ROLLBACK. Now, most people would simply assume that the sequence will also do a rollback and continue with 3. This is not the case:

test=# SELECT nextval('seq_a');
 nextval
--------- 
 4
(1 row)

Why is it that way? While a transaction is running, there is no way for the database to know whether the transaction is actually going to commit or not. Just imagine a thousand long running transactions – some of them doing a COMMIT and some of them failing. How would you ever be able to track holes and gaps? This is totally impossible. Therefore it is essential to keep in mind that sequences can indeed produce gaps.

When you are dealing with invoices and accounting, avoiding gaps is especially important. Sequences are no suitable tool to achieving what is needed in this area.

———-
We welcome your feedback on our brand new Facebook page: www.fb.com/cybertec.postgresql