Re: Row-level Locks & SERIALIZABLE transactions, postgres vs. Oracle
От | Robert Haas |
---|---|
Тема | Re: Row-level Locks & SERIALIZABLE transactions, postgres vs. Oracle |
Дата | |
Msg-id | AANLkTikyfIb2e9s8K_FNUxIJVPS_SnrJkLMtHzaxz2-T@mail.gmail.com обсуждение исходный текст |
Ответ на | Re: Row-level Locks & SERIALIZABLE transactions, postgres vs. Oracle (Tom Lane <tgl@sss.pgh.pa.us>) |
Ответы |
Re: Row-level Locks & SERIALIZABLE transactions, postgres vs. Oracle
(Florian Pflug <fgp@phlo.org>)
|
Список | pgsql-hackers |
On Thu, May 13, 2010 at 5:39 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote: > Florian Pflug <fgp@phlo.org> writes: >> All in all, I believe that SHARE and UPDATE row-level locks should be >> changed to cause concurrent UPDATEs to fail with a serialization >> error. > > I don't see an argument for doing that for FOR SHARE locks, and it > already happens for FOR UPDATE (at least if the row actually gets > updated). AFAICS this proposal mainly breaks things, in pursuit of > an unnecessary and probably-impossible-anyway goal of making FK locking > work with only user-level snapshots. After giving this considerable thought and testing the behavior at some length, I think the OP has it right. One thing I sometimes need to do is denormalize a copy of a field, e.g. CREATE TABLE parent (id serial, mode integer not null, primary key (id)); CREATE TABLE child (id serial, parent_id integer not null references parent (id), parent_mode integer not null); The way I have typically implemented this in the past is: 1. Add a trigger to the parent table so that, whenever the mode column gets updated, we do an update on the parent_mode of all children. 2. Add a trigger to the child table so that, when a new child is inserted, it initializes parent_mode from its parent. I do SELECT with FOR UPDATE on the parent parent can't change under me; though FOR SHARE ought to be enough also since we're just trying to lock out concurrent updates. Suppose T1 updates the parent's mode while T2 adds a new child; then both commit. In read committed mode, this seems to work OK regardless of the order of T1 and T2. If T1 grabs the lock first, then T2 sees the updated version of the row after T1 commits. If T2 grabs the lock first, then the update on the parent blocks until the child commits. Subsequently, when the trigger fires, it apparently uses an up-to-date snapshot, so the new child is updated also. In serializable mode, things are not so good. If T1 grabs the lock first, the child waits to see whether it commits or aborts. On commit, it complains that it can't serialize and aborts, which is reasonable - transaction aborts are the price you pay for serializability. If T2 grabs the lock first, the update on the parent blocks as before, but now the update is done with the old snapshot and ignores the new child, so the new child now has a value for parent_mode that doesn't match the parent's actual mode. That is, you get the wrong answer due to a serialization anomaly that didn't existed at the read committed level. Increasing the transaction isolation level is supposed to *eliminate* serialization anomalies, not create them. -- Robert Haas EnterpriseDB: http://www.enterprisedb.com The Enterprise Postgres Company
В списке pgsql-hackers по дате отправления:
Следующее
От: hubert depesz lubaczewskiДата:
Сообщение: Re: Generating Lots of PKs with nextval(): A Feature Proposal