<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: Obtaining a block of ids from a sequence in PostgreSQL</title>
	<atom:link href="http://www.misuse.org/science/2007/08/07/obtaining-a-block-of-ids-from-a-sequence-in-postgresql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.misuse.org/science/2007/08/07/obtaining-a-block-of-ids-from-a-sequence-in-postgresql/</link>
	<description>It would be a good idea.</description>
	<pubDate>Fri, 08 Aug 2008 00:31:33 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
		<item>
		<title>By: Adam Tomjack</title>
		<link>http://www.misuse.org/science/2007/08/07/obtaining-a-block-of-ids-from-a-sequence-in-postgresql/#comment-3175</link>
		<dc:creator>Adam Tomjack</dc:creator>
		<pubDate>Wed, 21 May 2008 19:05:12 +0000</pubDate>
		<guid isPermaLink="false">http://www.misuse.org/science/2007/08/07/obtaining-a-block-of-ids-from-a-sequence-in-postgresql/#comment-3175</guid>
		<description>Here's the best way I've found:
SELECT nextval('propery_id_seq') FROM generate_series(1, n)

It's simple, relatively fast, and it works, guaranteed.  No wastage either.

If you need tens of thousands of values instantly, then your method would work if you had a mutex:
&lt;pre&gt;&lt;code&gt;-- One time only:
CREATE TABLE alter_seq_cache_lock();
-- To allocate ids:
BEGIN;
LOCK TABLE alter_seq_cache_lock IN EXCLUSIVE MODE;
ALTER SEQUENCE ... 500
SELECT nextval...
ALTER SEQUENCE ... 1
COMMIT;
&lt;/code&gt;&lt;/pre&gt;
Then you only need to make sure that you don't change the sequence cache number without taking the lock.  For multiple sequences, insert rows into the lock table and use ROW EXCLUSIVE locking.

There's a similar trick with setval() that still wouldn't work
&lt;code&gt;&lt;pre&gt;BEGIN;
LOCK TABLE ...
id_range_min := nextval('seq');
id_range_max := setval('seq', id_range_min+n) ;
max_id := SELECT max(id) FROM table WHERE id&#60;id_range_max;
id_range_min := max(max_id, id_range_min)
COMMIT;
&lt;/code&gt;&lt;/pre&gt;
This avoids wastage. SELECT attempts to defeats interlopers who only want one id, but somebody could do a nextval() after yours, but before your setval(), then if you finish before they insert, your SELECT doesn't notice that they did anything, so you'd have a conflict.</description>
		<content:encoded><![CDATA[<p>Here&#8217;s the best way I&#8217;ve found:<br />
SELECT nextval(&#8217;propery_id_seq&#8217;) FROM generate_series(1, n)</p>
<p>It&#8217;s simple, relatively fast, and it works, guaranteed.  No wastage either.</p>
<p>If you need tens of thousands of values instantly, then your method would work if you had a mutex:</p>
<pre><code>-- One time only:
CREATE TABLE alter_seq_cache_lock();
-- To allocate ids:
BEGIN;
LOCK TABLE alter_seq_cache_lock IN EXCLUSIVE MODE;
ALTER SEQUENCE ... 500
SELECT nextval...
ALTER SEQUENCE ... 1
COMMIT;
</code></pre>
<p>Then you only need to make sure that you don&#8217;t change the sequence cache number without taking the lock.  For multiple sequences, insert rows into the lock table and use ROW EXCLUSIVE locking.</p>
<p>There&#8217;s a similar trick with setval() that still wouldn&#8217;t work<br />
<code>
<pre>BEGIN;
LOCK TABLE ...
id_range_min := nextval('seq');
id_range_max := setval('seq', id_range_min+n) ;
max_id := SELECT max(id) FROM table WHERE id&lt;id_range_max;
id_range_min := max(max_id, id_range_min)
COMMIT;
</pre>
<p></code><br />
This avoids wastage. SELECT attempts to defeats interlopers who only want one id, but somebody could do a nextval() after yours, but before your setval(), then if you finish before they insert, your SELECT doesn&#8217;t notice that they did anything, so you&#8217;d have a conflict.</p>
]]></content:encoded>
	</item>
</channel>
</rss>
