oracle也是会发生写偏斜的,Oracle中的Phantom Read异常和PostgreSQL不会回滚事务

我注意到Oracle和PostgreSQL中都出现了以下情况.

考虑到我们有以下数据库架构:

create table post (

id int8 not null,

title varchar(255),

version int4 not null,

primary key (id));

create table post_comment (

id int8 not null,

review varchar(255),

version int4 not null,

post_id int8,

primary key (id));

alter table post_comment

add constraint FKna4y825fdc5hw8aow65ijexm0

foreign key (post_id) references post;

有以下数据:

insert into post (title, version, id) values ('Transactions', 0, 1);

insert into post_comment (post_id, review, version, id)

values (1, 'Post comment 1', 459, 0);

insert into post_comment (post_id, review, version, id)

values (1, 'Post comment 2', 537, 1);

insert into post_comment (post_id, review, version, id)

values (1, 'Post comment 3', 689, 2);

如果我打开两个单独的SQL控制台并执行以下语句:

TX1: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

TX2: BEGIN TRANSACTION ISOLATION LEVEL SERIALIZABLE;

TX1: SELECT COUNT(*) FROM post_comment where post_id = 1;

TX1: > 3

TX1: UPDATE post_comment SET version = 100 WHERE post_id = 1;

TX2: INSERT INTO post_comment (post_id, review, version, id) VALUES (1, 'Phantom', 0, 1000);

TX2: COMMIT;

TX1: SELECT COUNT(*) FROM post_comment where post_id = 1;

TX1: > 3

TX1: COMMIT;

TX3: SELECT * from post_comment;

> 0;"Post comment 0";100;1

1;"Post comment 1";100;1

2;"Post comment 2";100;1

1000;"Phantom";0;1

正如预期的那样,SERIALIZABLE隔离级别保留了TX1事务开始时的快照数据,TX1只能看到3个post_comment记录.

由于Oracle和PostgreSQL中的MVCC模型,TX2允许插入新记录并提交.

为什么允许TX1提交?因为这是一个幻像读取异常,我期待看到TX1将回滚“序列化失败异常”或类似的东西.

PostgreSQL和Oracle中的MVCC Serializable模型是否仅提供快照隔离保证但没有幻像读取异常检测?

UPDATE

我甚至更改了Tx1以发出UPDATE语句,该语句更改属于同一帖子的所有post_comment记录的版本列.

这样,Tx2创建一个新记录,并且Tx1将在不知道已添加满足UPDATE过滤条件的新记录的情况下提交.

实际上,在PostgreSQL上使其失败的唯一方法是在插入幻像记录之前在Tx2中执行以下COUNT查询:

Tx2: SELECT COUNT(*) FROM post_comment where post_id = 1 and version = 0

TX2: INSERT INTO post_comment (post_id, review, version, id) VALUES (1, 'Phantom', 0, 1000);

TX2: COMMIT;

然后Tx1将回滚:

org.postgresql.util.PSQLException: ERROR: could not serialize access due to read/write dependencies among transactions

Detail: Reason code: Canceled on identification as a pivot, during conflict out checking.

Hint: The transaction might succeed if retried.

写入偏斜异常预防机制很可能检测到此更改并回滚事务.

有趣的是,Oracle似乎并没有被这种异常所困扰,因此Tx1只是成功提交.由于Oracle不会阻止写入偏差的发生,因此Tx1提交juts很好.

顺便说一下,你可以自己运行所有这些例子,因为它们是在GitHub.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值