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不会回滚事务所以在业务侧看起来更加易用但也更加容易让人混淆。