Return-Path: pg_adm@postgres.berkeley.edu Received: by postgres.Berkeley.EDU (5.61/1.29) id AA15734; Tue, 27 Apr 93 10:50:20 -0700 Message-Id: <9304271750.AA15734@postgres.Berkeley.EDU> From: Jeff Meredith Subject: Re: Re deadlock ( bug in begin/end? replace?) To: postgres@postgres.berkeley.edu Sender: pg_adm@postgres.berkeley.edu In-Reply-To: Your message of "Tue, 27 Apr 93 05:15:47 PDT." <9304271215.AA13941@postgres.Berkeley.EDU> Date: Tue, 27 Apr 93 10:46:35 -0700 From: Jeff Meredith message <9304271215.AA13941@postgres.Berkeley.EDU> read as follows: > I've been watching the mail over the last couple of days but still > haven't seen a definitive answer to avoiding deadlock. If: > > >a replace query of the form: > > > > replace foo (attribute1 =foo.attribute1 + 1) > > > >will first do a scan over foo (acquiring a readlock) then attempt to > >write a new instance/row/tuple (acquiring a write lock). any time you > >"upgrade" a read lock to a write lock you're vulnerable to deadlock. > > then how do I code a transaction that is guaranteed not to deadlock? > Would a dummy append do it or should I be considering my own locking > outside Postgres? as a workaround you might try (my syntax is rusty please forgive me): begin\g append foo (attribute1 = somedummyvalue)\g replace foo (attribute1 =foo.attribute1 + 1)\g end\g note that the write lock on foo will only be acquired if you actually write something to the relation. so for example having an append with a qual that is never satisfied will not do: append foo (attribute1 = 1) where 1 = 0\g the ugly side effect is that you end up with dummy values in your relation. i did not do a good job in deploying the lock manager after fixing it up at the university. the system should probably watch for the above case and automatically set a write at the outset. it doesn't. what also might be nice is for the postgres group to provide a built-in function that takes a relation name and sets an exclusive (write) lock on that relation. this would allow things like: begin\g retrieve (x=set_excl_lock("foo"))\g replace foo (attribute1 =foo.attribute1 + 1) end\g the lock manager already does a good job releasing all locks acquired during a xact at commit/abort. This would give users more control (the ability to hang themselves?), but should probably guard against the obvious abuses e.g. locking a system table, locking a table you don't have permission to replace or append to etc. incidentally, in my opinion doing your own locking outside of the db is not a good idea, but then again i'm a product of the mike stonebraker school of software development. jeff meredith mer@miro.com