问题
I'm running PostgreSQL 9.5.3.
I am trying to understand why I see a difference in behavior between the two routines below. I find this behavior counter-intuitive, but there may be a very good reason for it; I just want to know what it is if so.
Setting ISOLATION LEVEL REPEATABLE READ
does not seem to take effect until after the first SELECT
statement.
The only difference between the two routines is that in "Routine 2" I put in a superfluous SELECT 1 ;
statement, whereas in "Routine 1" I did not do this. I got my desired results in "Routine 2".
See my (overly-lengthy) question that I posted earlier in which I incorrectly assumed the behavior I was seeing was something to do with what particular tables I was querying.
I've modified the routine from krokodilko's answer to demonstrate what I'm seeing. Thanks, krokodilko!
These are meant to be executed serially, in the order listed, switching back and forth between two separate sessions.
Routine 1
Session 1:
testdb=# CREATE TABLE t1( x int ) ;
CREATE TABLE
testdb=# INSERT INTO t1 VALUES (1),(2),(3) ;
INSERT 0 3
Session 2:
testdb=# START TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
START TRANSACTION
Session 1:
testdb=# DELETE FROM t1 WHERE x = 2 ;
DELETE 1
Session 2:
testdb=# SELECT * FROM t1 ;
x
---
1
3
(2 rows)
(why am I seeing the effects from session 1 here?)
Session 2:
testdb=# COMMIT ;
COMMIT
Session 1:
testdb=# CREATE TABLE t1( x int ) ;
CREATE TABLE
testdb=# INSERT INTO t1 VALUES (1),(2),(3) ;
INSERT 0 3
Session 2:
testdb=# START TRANSACTION ISOLATION LEVEL REPEATABLE READ ;
START TRANSACTION
testdb=# SELECT 1 ;
?column?
----------
1
(1 row)
(why should I have to do this?)
Session 1:
testdb=# DELETE FROM t1 WHERE x = 2 ;
DELETE 1
Session 2:
testdb=# SELECT * FROM t1 ;
x
---
1
2
3
(3 rows)
(that's what I expected to see!)
Session 2:
testdb=# COMMIT ;
COMMIT
testdb=# SELECT * FROM t1 ;
x
---
1
3
(2 rows)
(that's also what I expected to see)
回答1:
According to the docs (emphasis mine):
REPEATABLE READ
All statements of the current transaction can only see rows committed before the first query or data-modification statement was executed in this transaction.
I can only guess the motivation for making it this way, but I think it's because it simply doesn't matter until you start querying for data. Once you start to query the data is consistent.
来源:https://stackoverflow.com/questions/42322730/time-when-postgresql-isolation-level-takes-effect-seems-to-be-after-first-select