X-Original-To: pgsql-sql-postgresql.org@localhost.postgresql.org Received: from localhost (av.hub.org [200.46.204.144]) by postgresql.org (Postfix) with ESMTP id E14B19DCC2D for ; Sat, 11 Mar 2006 02:33:55 -0400 (AST) Received: from postgresql.org ([200.46.204.71]) by localhost (av.hub.org [200.46.204.144]) (amavisd-new, port 10024) with ESMTP id 50866-04 for ; Sat, 11 Mar 2006 02:33:54 -0400 (AST) X-Greylist: from auto-whitelisted by SQLgrey- Received: from tigger.fuhr.org (tigger.fuhr.org [63.214.45.158]) by postgresql.org (Postfix) with ESMTP id D9D579DCC04 for ; Sat, 11 Mar 2006 02:33:52 -0400 (AST) Received: from winnie.fuhr.org (winnie.fuhr.org [10.1.0.1]) by tigger.fuhr.org (8.13.3/8.13.3) with ESMTP id k2B6X9p9091356 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 10 Mar 2006 23:33:12 -0700 (MST) (envelope-from mfuhr@winnie.fuhr.org) Received: from winnie.fuhr.org (localhost [127.0.0.1]) by winnie.fuhr.org (8.13.4/8.13.4) with ESMTP id k2B6X9h8000439; Fri, 10 Mar 2006 23:33:09 -0700 (MST) (envelope-from mfuhr@winnie.fuhr.org) Received: (from mfuhr@localhost) by winnie.fuhr.org (8.13.4/8.13.4/Submit) id k2B6X9qS000438; Fri, 10 Mar 2006 23:33:09 -0700 (MST) (envelope-from mfuhr) Date: Fri, 10 Mar 2006 23:33:08 -0700 From: Michael Fuhr To: Larry Rosenman Cc: "'Flavio Suguimoto'" , pgsql-sql@postgresql.org Subject: Re: Locking row Message-ID: <20060311063308.GA98138@winnie.fuhr.org> References: <023e01c64485$4be7f630$0a0a0a0a@aus.pervasive.com> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <023e01c64485$4be7f630$0a0a0a0a@aus.pervasive.com> X-Virus-Scanned: by amavisd-new at hub.org X-Spam-Status: No, score=0.121 required=5 tests=[AWL=0.121] X-Spam-Score: 0.121 X-Spam-Level: X-Archive-Number: 200603/157 X-Sequence-Number: 24503 On Fri, Mar 10, 2006 at 02:57:51PM -0600, Larry Rosenman wrote: > Flavio Suguimoto wrote: > > I need to mark a row with a value in a column, but first i need to > > select the first row without this mark. But in some concurrents cases > > i mark the row twice. How can i lock the row to avoid others session > > get it? > > > > TABLE TICKET > > TICKET_NUMBER | MARK > > 00001 | 1 > > 00002 | 0 > > > > I need to select the first row with 0 in MARK column and then mark it > > with 1. > > look at the FOR UPDATE in the select docs. If you use FOR UPDATE with LIMIT then see the following in the SELECT documentation: It is possible for a SELECT command using both LIMIT and FOR UPDATE/SHARE clauses to return fewer rows than specified by LIMIT. This is because LIMIT is applied first. The command selects the specified number of rows, but might then block trying to obtain lock on one or more of them. Once the SELECT unblocks, the row might have been deleted or updated so that it does not meet the query WHERE condition anymore, in which case it will not be returned. For example, suppose you have the following data: ticket_number | mark ---------------+------ 00001 | 1 00002 | 0 00003 | 0 (3 rows) Two concurrent transactions, T1 and T2, both run the following query: SELECT * FROM ticket WHERE mark = 0 LIMIT 1 FOR UPDATE; One transaction, say T1, will get the following row: ticket_number | mark ---------------+------ 00002 | 0 (1 row) T2 will block until T1 ends. If T1 rolls back or doesn't update the row then T2 will get the above row. But if T1 updates the row so that mark = 1 and then commits, then T2 will get an empty result set instead of getting the next row with mark = 0. The queries could use LIMIT 2 instead of LIMIT 1 and update only the first row that came back, but then you'd have the same problem with a third concurrent transaction (and with LIMIT 3 and a fourth transaction, and so on). -- Michael Fuhr