Re: [HACKERS] READ COMMITTED isolevel is implemented ... - Mailing list pgsql-hackers

From Vadim Mikheev
Subject Re: [HACKERS] READ COMMITTED isolevel is implemented ...
Date
Msg-id 36B5337C.9BDA3F48@krs.ru
Whole thread Raw
Responses RE: [HACKERS] READ COMMITTED isolevel is implemented ...
List pgsql-hackers
Hiroshi Inoue wrote:
> 
> Recently I thought about UPDATE operations in READ COMMITED
> mode a little and found it's very difficult.
> I read Oracle's manual but couldn't find the algorithm.
> 
> After I read your posting [READ COMMITTED isolevel is implemented ...],
> I tested the following [Case-1] in my Oracle database environment(Version
> 7).
> I believed that changes of the values of columns used in a QUERY caused
> re-execution.
> 
> After I posted my mail,I tested another case(the following [Case -2]) and
> found that changes of the values of columns used in a QUERY don't
> necessarily cause re-execution.
> To tell the truth,I can't understand the result of this case.
> IMHO this case requires re-execution after re-setting the time of execution
> and the result should be same as [Case-1] .
> But Oracle doesn' work as I believe.
> 
> create table t (id int4,dt int4,name text);
> insert into t values (10,5,'a0');
> insert into t values (20,10,'b0');
> insert into t values (30,15,'c0');
> 
> id      |dt     |name
> ----------------------------
> 10      |5      |a0
> 20      |10     |b0
> 30      |15     |c0
> 
> 
> session-1               session-2               session-3
> 
> [Case-1]
> update t set dt=dt+1,
>                   ^^^^^^^^
>         name='c1'
>     where id=30;
> UPDATE 1
>                         update t set dt=dt+2
>                         where dt >7;
>                         ^^^^^^^^^^^^^
>                         (blocked)
>                                                 update t set dt=dt+3,
>                                                              ^^^^^^^^^
>                                                         id=id+1
>                                                     where id=10;
>                                                 UPDATE 1
>                                                 commit;
>                                                 COMMIT
> commit;
> COMMIT
>                         UPDATE 3
>                         ^^^^^^^^^^^^

Ops. I'm quite suprized that T2 sees changes made by T3 after
T2' statement started! What would be results if T3 wouldn't
make UPDATE but made INSERT INTO t VALUES (11, 8, 'a1') ?
> [result]        id      |dt     |name
>         ---------------------------
>         11      |10     |a0
>         20      |12     |b0
>         30      |18     |c1
> 
> If      dt=dt+1      ==>  dt=dt
>             ^^^^^^^^
> then            UPDATE 3  ==> UPDATE 2
>         ^^^^^^^^^^^^
> 
> [result]        id      |dt     |name
>         ---------------------------
>         11      |8      |a0
>         20      |12     |b0
>         30      |17     |c1
> 

Why T2 doesn't change id=11 row now???
Does Oracle re-execute _entire_ query after being blocked
by concurrent transaction T only if T made changes in columns
used in QUAL?!

Yes! Case-2 confirmes this!

> [Case-2]
> 
> update t set dt=dt+1,
>               ^^^^^^^^
>         name='c1'
>     where id=30;
> UPDATE 1
>                         update t set dt=dt+2
>                         where id > 10;
>                                  ^^^^^^^^^
>                         (blocked)
>                                                 update t set dt=dt+3,
>                                                         id=id+1
>                                                         ^^^^^^^^
>                                                     where id=10;
>                                                 UPDATE 1
>                                                 commit;
>                                                 COMMIT
> commit;
> COMMIT
>                        UPDATE 2
>                       ^^^^^^^^^^^^
> 
> [result]        id      |dt     |name
>         ---------------------------
>         11      |8      |a0
>         20      |12     |b0
>         30      |18     |c1

id is not changed by T1 and so T2 doesn't re-execute query
after T1 committed and doesn't see changes made by T3!
T2 just re-evaluates target list.

Ok. Postgres always re-executes query after being blocked,
but makes this for single row only and so all other changes
made after query started are not visible. I would say that
we are more consistent than Oracle -:))

Oracle says:
---
Oracle always enforces statement-level read consistency. 
This guarantees that the data returned by a single query 
is consistent with respect to the time that the query began.
Therefore, a query never sees dirty data nor any of the changes 
made by transactions that commit during query execution. As query 
execution proceeds, only data committed before the query began is 
visible to the query. The query does not see changes committed after
statement execution begins. 
---

Your tests show that Oracle breaks this statement if re-evaluation
of query' qual is required!

Just wondering what would be the results of these test in
Informix or Sybase?
Could someone run them?

Vadim


pgsql-hackers by date:

Previous
From: Vadim Mikheev
Date:
Subject: Re: [HACKERS] READ COMMITTED isolevel is implemented ...
Next
From: Ian Grant
Date:
Subject: Is libpq re-entrant?