Received: from localhost (maia-2.hub.org [200.46.204.187]) by postgresql.org (Postfix) with ESMTP id 0773E9FA17F for ; Thu, 30 Nov 2006 18:06:22 -0400 (AST) Received: from postgresql.org ([200.46.204.71]) by localhost (mx1.hub.org [200.46.204.187]) (amavisd-new, port 10024) with ESMTP id 40314-05 for ; Thu, 30 Nov 2006 18:06:14 -0400 (AST) X-Greylist: from auto-whitelisted by SQLgrey-1.7.4 Received: from sss.pgh.pa.us (sss.pgh.pa.us [66.207.139.130]) by postgresql.org (Postfix) with ESMTP id A56C69F9C35 for ; Thu, 30 Nov 2006 18:06:17 -0400 (AST) Received: from sss2.sss.pgh.pa.us (tgl@localhost [127.0.0.1]) by sss.pgh.pa.us (8.13.6/8.13.6) with ESMTP id kAUM6D1M001146; Thu, 30 Nov 2006 17:06:13 -0500 (EST) To: Alvaro Herrera cc: pgsql-hackers@postgreSQL.org Subject: FOR SHARE vs FOR UPDATE locks Date: Thu, 30 Nov 2006 17:06:13 -0500 Message-ID: <1144.1164924373@sss.pgh.pa.us> From: Tom Lane X-Virus-Scanned: Maia Mailguard 1.0.1 X-Archive-Number: 200611/1012 X-Sequence-Number: 94474 I just realized that we have a bit of a problem with upgrading row locks. Consider the following sequence: regression=# begin; BEGIN regression=# select * from int4_tbl where f1 = 0 for share; f1 ---- 0 (1 row) regression=# savepoint x; SAVEPOINT regression=# select * from int4_tbl where f1 = 0 for update; f1 ---- 0 (1 row) regression=# rollback to x; ROLLBACK The FOR UPDATE replaces the former shared row lock with an exclusive lock in the name of the subtransaction. After the ROLLBACK, the row appears not to be locked at all (it is ex-locked with XMAX = a failed transaction), so another backend could come along and modify it. That shouldn't happen --- we should act as though the outer transaction's FOR SHARE lock is still held. Unfortunately, I don't think there is any good way to implement that, since we surely don't have room in the tuple header to track multiple locks. One possibility is to try to assign the ex-lock in the name of the highest subtransaction holding a row lock, but that seems messy, and it wouldn't really have the correct semantics anyway --- in the above example, the outer transaction would be left holding ex-lock which would be surprising. I'm tempted to just error out in this scenario rather than allow the lock upgrade. Thoughts? regards, tom lane