Re: Best approach for a "gap-less" sequence

From: "Dawid Kuroczko" <qnex42(at)gmail(dot)com>
To: "Jorge Godoy" <jgodoy(at)gmail(dot)com>
Cc: "PostgreSQL General ML" <pgsql-general(at)postgresql(dot)org>
Subject: Re: Best approach for a "gap-less" sequence
Date: 2006-08-16 20:47:36
Message-ID: 758d5e7f0608161347m76a8c461s834246709eb51d63@mail.gmail.com
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

On 8/12/06, Jorge Godoy <jgodoy(at)gmail(dot)com> wrote:
> I was trying to solve a problem on an old system and realized that there might
> be some better approach for doing what I need.
>
> We have some documents that need to be ordered sequentially and without gaps.
> I could use a sequence, but if the transaction fails then when I rollback the
> sequence will already have been incremented.
>
> So, today I have a control table and I acquire a SHARE ROW EXCLUSIVE lock to
> it, read the value, increase it, do what I need and then I COMMIT the
> transaction, ensuring that the sequence has no gaps.
>
> Is there a better way to guarantee that there will be no gaps in my sequence
> if something goes wrong with my transaction?

Hmm, I would do it this way:

-- First prepare a table for keeping gapless sequence, say:
CREATE TABLE gapless_seq (
gseq_name varchar(256) PRIMARY KEY,
gseq_value integer NOT NULL
);
-- ...and populate it:
INSERT INTO gapless_seq VALUES('tax_id', '1');

-- then create a function to retrieve the values:
CREATE FUNCTION gseq_nextval(t text) RETURNS integer AS $$
DECLARE
n integer;
BEGIN
SELECT INTO n gseq_value+1 FROM gapless_seq WHERE gseq_name = t
FOR UPDATE;
UPDATE gapless_seq SET gapless_value = n WHERE gseq_name = t;
RETURN n;
END;
$$ STABLE LANGUAGE PLpgsql;

-- ...and use it as default in table definiton
CREATE TABLE taxdata (
tax_id integer PRIMARY KEY DEFAULT gseq_nextval('tax_id'),
customer text,
when timestamptz
);

...etc. SELECT ... FOR UPDATE woud ensure a row lock on "gapless sequence",
a PLpgsql function would make a nice wrapper for it (so it would be usable more
or less similar to real sequences), and it should work.

I did not test the code right now, but I've written something similar to
it some time ago, and it worked fine. Remember to vacuum gapless_seq
table frequently and don't expect stellar performance from it.

Regards,
Dawid

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Dawid Kuroczko 2006-08-16 20:53:25 Re: Best approach for a "gap-less" sequence
Previous Message Michael Fuhr 2006-08-16 20:42:27 Re: [NOVICE] DB insert Error