Received: from localhost (mx1.hub.org [200.46.208.251]) by postgresql.org (Postfix) with ESMTP id 195EF9FA103 for ; Mon, 6 Nov 2006 15:21:58 -0400 (AST) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.208.251]) (amavisd-new, port 10024) with ESMTP id 22973-04 for ; Mon, 6 Nov 2006 15:21:50 -0400 (AST) X-Greylist: from auto-whitelisted by SQLgrey- Received: from exchange.g2switchworks.com (mail.g2switchworks.com [63.87.162.25]) by postgresql.org (Postfix) with ESMTP id 244409FA372 for ; Mon, 6 Nov 2006 15:21:50 -0400 (AST) Received: from 10.10.1.37 ([10.10.1.37]) by exchange.g2switchworks.com ([10.10.1.2]) with Microsoft Exchange Server HTTP-DAV ; Mon, 6 Nov 2006 19:21:43 +0000 Received: from state.g2switchworks.com by mail.g2switchworks.com; 06 Nov 2006 13:21:43 -0600 Subject: Re: fetching unique pins in a high-transaction environment... From: Scott Marlowe To: Bobus Cc: pgsql-sql@postgresql.org In-Reply-To: <1162139808.031657.23340@f16g2000cwb.googlegroups.com> References: <1162139808.031657.23340@f16g2000cwb.googlegroups.com> Content-Type: text/plain Content-Transfer-Encoding: 7bit Message-Id: <1162840903.5195.5.camel@state.g2switchworks.com> Mime-Version: 1.0 X-Mailer: Ximian Evolution 1.4.6 (1.4.6-2) Date: Mon, 06 Nov 2006 13:21:43 -0600 X-Virus-Scanned: Maia Mailguard 1.0.1 X-Archive-Number: 200611/78 X-Sequence-Number: 26730 On Sun, 2006-10-29 at 10:36, Bobus wrote: > Hi, > > I posted this question to the "general" forum, but then discovered this > one which I think is more appropriate. Apologies for the cross-post. > > We are in the process of porting an application from SQL Server to > PostgresQL. > > We have a table which contains a bunch of prepaid PINs. What is the > best way to fetch the next available unique pin from the table in a > high-traffic environment with lots of concurrent requests? > > For example, our PINs table might look like this and contain thousands > of records. (FYI, the PIN numbers are generated by a third party and > loaded into the table): > > ID PIN USED_BY DATE_USED > .... > 100 1864678198 > 101 7862517189 > 102 6356178381 > .... > > 10 users request a pin at the same time. What is the easiest/best way > to ensure that the 10 users will get 10 unique pins, while eliminating > any waiting? Best practice, to me, is to do a couple things. One, create a sequence and set it to the first available pin number. Let's say you have pins available from the number 1 to 9999. Create a default sequence, it'll start on 1. Then, select nextval('yourseqhere') and use that to fetch the pin like so: begin; select nextval('yourseqhere'); -- store in a var update pin set date_used=now() where id=$var and date_used IS NULL If date_used is not null, then someone grabbed it from you. Given that we're grabbing them using a sequence, this is unlikely, but you never know when things might go south. Otherwise you just reserved it. Then grab it: select pin from table where id=$var; commit; if a transaction fails, you might not use a pin, no big loss. Better than accidentally giving it out twice. I'd wrap what I just wrote in a simple pl/pgsql script using security definer and set the perms so ONLY the user defined function can get you a new pin.