本页目录

UStore 下 Vacuum Full 会让可重复读事务的 Snapshot 过期,而 AStore 不会

在可重复读隔离级别下,对 UStore 表执行 Vacuum Full 或 Online Vacuum Full 会导致事务报错“Snapshot too old”;相同操作在 AStore 上不会触发该错误。

现象与复现

下面的测试使用两个会话。创建 test 表时,根据测试场景选择 UStore 或 AStore:

drop table dummy;
create table dummy(a int);
drop table test;

-- 以下两条语句按测试场景二选一
create table test(a int) with (storage_type=ustore);
-- create table test(a int) with (storage_type=astore);

insert into test values(1);
insert into dummy values(1);

-- Session 2:开启可重复读事务并获取快照
start transaction isolation level repeatable read;
select * from dummy;

-- Session 1:更新并执行 Online Vacuum Full
update test set a=2;
vacuum full test online;

-- Session 2:使用原快照读取 test
select * from test;
commit;

UStore 执行结果

gaussdb=# select * from dummy; -- 随便执行一条 SQL,获取快照
 a
---
 1
(1 row)

gaussdb=# select * from test;
ERROR: Snapshot too old, ScanRelation, the info: snapxmax is 236244314,
snapxmin is 236244311, csn is 130631, relfrozenxid64 is 236244318,
globalRecycleXid is 236244311.
gaussdb=# commit;
ROLLBACK

AStore 执行结果

gaussdb=# select * from dummy; -- 随便执行一条 SQL,获取快照
 a
---
 1
(1 row)

gaussdb=# select * from test;
 a
---
 1
(1 row)

gaussdb=# commit;
COMMIT

原因分析

UStore 将数据页面(data page)和 UNDO 日志分离存储:最新版本的数据位于数据页面,历史版本的数据位于 UNDO 空间。执行 Vacuum Full 时,系统不会复制 UNDO 日志。

相关函数: CopyUHeapDataInternal