Postgresql - Transaction - Snapshot

在PG内部,可以设置三个不同的隔离级别,对应于读提交、可重复读取和可序列化的级别。默认为READ COMMITTED。

ISOLATION LEVEL { SERIALIZABLE | REPEATABLE READ | READ COMMITTED | READ UNCOMMITTED }

这个在另一篇文章中有介绍和实验。

READ COMMITTED隔离级别,意味着可以看到已提交的数据,无法看到未提交的数据,所以可能造成幻读。

当我们有需要的时候,可以选择更高的安全隔离级别,REPEATABLE READ,提供了更强的保证。意味着我们只能看到事务开始之前已经提交的数据。在事务完成之前,其他回话引起的任何更改对我们都是不可见。

重点是,每个事务都具有不同的数据库数据。每个事务都可以看到以前事务提交的数据的快照,以及在事务本身中创建的所有尚未提交的数据。

“以前的事务”的含义取决于您何时开始您的语句(在read committed中)或何时开始您的事务(在repeatable read中),但在这两种情况下,都无法选择。如果需要同步状态,这可能是一个问题,因为无法保证不同的语句或事务将完全同时启动。

这时,可以设置你想看哪个事务之前的数据,设置一个snapshot。

创建一个实验表。
create table test0115(id int);

session A: 查询一个snapshot点
mytest=# begin;
BEGIN
mytest=# select pg_export_snapshot();
 pg_export_snapshot
---------------------
 00000007-00000037-1
(1 row)

session B: 一个插入数据的事务
mytest=# begin;
BEGIN
mytest=# insert into test0115(id) values (1);
INSERT 0 1
mytest=# insert into test0115(id) values (2);
INSERT 0 1
mytest=# commit;
COMMIT

Session C: 关键点!!!
mytest=# select * from test0115;
 id
----
  1
  2
(2 rows)
mytest=# begin isolation level repeatable read;
BEGIN
mytest=# set transaction snapshot '00000007-00000037-1';
SET
mytest=# select * from test0115 ;
 id
----
(0 rows)

是不是灰常神奇的操作!

我们来看看数据库做了哪些操作。

当我们执行了Session A 中的语句之后,数据库在$PGDATA/pg_snapshots文件夹下生成了与snapshot同名的文件。

查看文件内容为

vxid:6/328
pid:32460
dbid:16385
iso:1
ro:0
xmin:10093
xmax:10093
xcnt:0
sof:0
sxcnt:0
rec:0

记录了snapshot的一些信息。当我们查询的时候,我们会根据这些版本号,去表中去查询。

mytest=# select xmin,cmin,xmax,cmax,ctid from test0115;
 xmin  | cmin | xmax | cmax | ctid
-------+------+------+------+-------
 10094 |    0 |    0 |    0 | (0,1)
 10095 |    0 |    0 |    0 | (0,2)
(2 rows)

猜你喜欢

转载自blog.csdn.net/chuckchen1222/article/details/86491926