Обсуждение: Implicit row locking during an UPDATE

Поиск
Список
Период
Сортировка

Implicit row locking during an UPDATE

От
"Dr. Evil"
Дата:
I'm still not understanding this, and it's vitally important to the
project I'm working on, so I have a question:

From my understanding, this:

UPDATE account SET value = 10 WHERE number = 99;

actually implies all of this:

BEGIN;
SELECT value FOR UPDATE FROM account WHERE number = 99;
UPDATE account SET value = 10 WHERE number = 99;
COMMIT;
END;

Is this correct?  If so, there's something I don't understand.

In order to test locking stuff, I created a little C function:

int pgsleep(int i) { sleep(i); return(i); }

which I then linked into PG using CREATE FUNCTION....  It worked just
as I expected.  So to test locking, I opened up two windows, and ran
psql in each.

In one window, I run:

UPDATE account SET value = pgsleep(20) WHERE number = 99;

Then, a few seconds later, in the other window, I run:

UPDATE account SET value = 30 WHERE number = 99;

What I would expect to happen is that Window 1 would lock the row
where number = 99, and then set the value to 20, and then the command
in Window 2 would run, setting the value to 30.

Instead, the UPDATE in Window 2 runs immediately, setting the value to
30, and then, after the twenty seconds have gone by, the UPDATE in
Window 1 finishes, and sets the value to 20.

So, what's actually going on here?

Thanks for any tips.

Re: Implicit row locking during an UPDATE

От
Tom Lane
Дата:
"Dr. Evil" <drevil@sidereal.kz> writes:
> From my understanding, this:

> UPDATE account SET value = 10 WHERE number = 99;

> actually implies all of this:

> BEGIN;
> SELECT value FOR UPDATE FROM account WHERE number = 99;
> UPDATE account SET value = 10 WHERE number = 99;
> COMMIT;
> END;

Not really.  Plain UPDATE doesn't lock the target tuple in advance of
computing the new version; it optimistically assumes that it doesn't
need to do that.  If that turns out to be wrong when it actually goes
to update the tuple, it backs off, recomputes the update, and tries
again.  Normally this ends up at the same place as your two-step
example, but not when the UPDATE targetlist has side effects...

            regards, tom lane

Re: Implicit row locking during an UPDATE

От
"Eric G. Miller"
Дата:
On Fri, May 25, 2001 at 02:23:50AM -0000, Dr. Evil wrote:
>
> I'm still not understanding this, and it's vitally important to the
> project I'm working on, so I have a question:
>
> >From my understanding, this:
>
> UPDATE account SET value = 10 WHERE number = 99;
>
> actually implies all of this:
>
> BEGIN;
> SELECT value FOR UPDATE FROM account WHERE number = 99;
> UPDATE account SET value = 10 WHERE number = 99;
> COMMIT;
> END;
>
> Is this correct?  If so, there's something I don't understand.

No.  Maybe you want to read the manual.  Specifically look at
transaction isolation level under MVCC.  Hmm, SET TRANSACTION ISOLATION
LEVEL doesn't seem to be taking in 7.1.1... Is that a bug?  Guess the
only way to be sure is to use the transaction semantics above...

--
Eric G. Miller <egm2@jps.net>