PostgreSQL Concurrency Issues 32
How do I manufacture unique row numbers?
If you want to assign a serial number to each row in a table, you might try
INSERT INTO mytable (id, ...)
VALUES( (SELECT MAX(id) + 1 FROM mytable), ...);
This will not work safely unless you take an explicit lock on the whole table,
which will prevent concurrent insertions. (It’ll also be quite slow, because
MAX
scans the whole table in PostgreSQL.) A variant is to use a single-row
table to hold the next ID number to assign:
SELECT next FROM mytable counter FOR UPDATE;
UPDATE mytable
counter SET next = $next + 1;
INSERT INTO mytable (id, ...) VALUES($next, ...);
This works (as long as you use FOR UPDATE), but you still have the
problem that only one insertion transaction can proceed at a time. The
implicit write lock on the counter row is the bottleneck.
Tom Lane O’Reilly Open Source Convention, July 2002