Postgresql在RR级别(可重复读)不会出现幻读

2022-05-12 10:44:11 浏览数 (1)

Isolation Level

Dirty Read

Nonrepeatable Read

Phantom Read

Serialization Anomaly

Read uncommitted

Allowed, but not in PG

Possible

Possible

Possible

Read committed

Not possible

Possible

Possible

Possible

Repeatable read

Not possible

Not possible

Allowed, but not in PG

Possible

Serializable

Not possible

Not possible

Not possible

Not possible

  • 其他事务提交:为避免幻读直接回滚当前事务
  • 其他事务回滚:正常提交

PG对于事务行为有更为苛刻的保证,使用回滚的方式避免幻读,MYSQL不会回滚事务所以在业务侧看起来更加易用但也更加容易让人混淆。

准备数据

代码语言:javascript复制

postgres=# create table tbl1(id int primary key, data text);
CREATE TABLE
postgres=# insert into tbl1 values (1, 'jack');
INSERT 0 1
postgres=# insert into tbl1 values (2, 'tom');
INSERT 0 1
 

PG表现

代码语言:javascript复制
transaction1                                        transaction2
begin;                                              begin;
set transaction isolation level repeatable read;    set transaction isolation level repeatable read;
postgres=# select * from tbl1 where id=3;
 id | data
---- ------
(0 rows) 
                                                    insert into tbl1 values (3, 'sam');
                                                    INSERT 0 1
 
 
postgres=# insert into tbl1 values (3, 'geller');   
注意,这里会block等待事务2的行为。
 
                                         
                                                    postgres=# commit;
 
                                                    COMMIT
 
postgres=# insert into tbl1 values (3, 'geller');
ERROR:  duplicate key value violates
DETAIL:  Key (id)=(3) already exists.
注意,事务1已经自动回滚
 

MYSQL表现

transaction1                                        transaction2
begin;                                              begin;
select * from tbl1 where id=3;
无结果返回
                                                    insert into tbl1 values (3, 'sam');
                                                    INSERT 0 1
 
 
insert into tbl1 values (3, 'geller');   

注意,这里会直接报主键冲突,但是事务并不回滚。发生幻读!

上述场景的差异:MYSQL发生了幻读,而PG会等待其他事务的行为进而作出不同的相应:

其他事务提交:为避免幻读直接回滚当前事务

其他事务回滚:正常提交

PG对于事务行为有更为苛刻的保证,使用回滚的方式避免幻读,MYSQL不会回滚事务所以在业务侧看起来更加易用但也更加容易让人混淆。

0 人点赞