PostgreSQL snapshot too old补丁, 防止数据库膨胀
背景
PostgreSQL 9.6已支持snapshot too old , 目前仅仅针对未申请事务号的事务(pg_stat_activity.backend_xid为空的事务),这种事务会被CANCEL,而申请了事务号的事务(例如写事务)则不会触发snapshot too old。
所以即使你使用9.6,对于写事务,也不要为所欲为,因为依旧会影响垃圾回收。
PostgreSQL 9.6新增的一个patch,暂时还没有提交,这个patch主要是防止数据库中的某些long sql导致LONG snapshot导致数据库膨胀。
原理参考:
http://blog.163.com/digoal@126/blog/static/1638770402015329115636287/
下载补丁和数据库源码(使用2015-10-13号master分支源码)
http://www.postgresql.org/message-id/flat/BLU437-SMTP193E7367B788D2EC2B2B81DC160@phx.gbl#BLU437-SMTP193E7367B788D2EC2B2B81DC160@phx.gbl
打补丁
[root@digoal soft_bak]# tar -zxvf postgresql-aa7f949.tar.gz
[root@digoal soft_bak]# cd postgresql-aa7f949
[root@digoal postgresql-aa7f949]# patch -p1 < ../snapshot-too-old-v3.diff
patching file doc/src/sgml/config.sgml
patching file src/backend/access/brin/brin.c
patching file src/backend/access/brin/brin_revmap.c
patching file src/backend/access/gin/ginbtree.c
patching file src/backend/access/gin/gindatapage.c
patching file src/backend/access/gin/ginget.c
patching file src/backend/access/gin/gininsert.c
patching file src/backend/access/gist/gistget.c
patching file src/backend/access/hash/hash.c
patching file src/backend/access/hash/hashsearch.c
patching file src/backend/access/heap/heapam.c
patching file src/backend/access/heap/pruneheap.c
patching file src/backend/access/nbtree/nbtinsert.c
patching file src/backend/access/nbtree/nbtpage.c
patching file src/backend/access/nbtree/nbtsearch.c
patching file src/backend/access/spgist/spgscan.c
patching file src/backend/commands/vacuum.c
patching file src/backend/commands/vacuumlazy.c
patching file src/backend/storage/ipc/ipci.c
patching file src/backend/storage/ipc/procarray.c
patching file src/backend/storage/lmgr/lwlocknames.txt
patching file src/backend/utils/errcodes.txt
patching file src/backend/utils/misc/guc.c
patching file src/backend/utils/misc/postgresql.conf.sample
patching file src/backend/utils/time/snapmgr.c
patching file src/include/access/brin_revmap.h
patching file src/include/access/gin_private.h
patching file src/include/access/nbtree.h
patching file src/include/storage/bufmgr.h
patching file src/include/utils/rel.h
patching file src/include/utils/snapmgr.h
patching file src/include/utils/snapshot.h
patching file src/test/modules/Makefile
patching file src/test/modules/sto/.gitignore
patching file src/test/modules/sto/Makefile
patching file src/test/modules/sto/t/001_snapshot_too_old.pl
patching file src/test/modules/sto/t/002_snapshot_too_old_select.pl
patching file src/test/perl/TestLib.pm
安装
# ./configure --prefix=/opt/pgsql9.5devel
# gmake world -j 32
# gmake install-world
su - pg95
vi .bash_profile
# add by digoal
export PS1="$USER@`/bin/hostname -s`-> "
export PGPORT=1931
export PGDATA=/data01/pg_root_1931
export LANG=en_US.utf8
export PGHOME=/opt/pgsql9.5devel
export LD_LIBRARY_PATH=$PGHOME/lib:/lib64:/usr/lib64:/usr/local/lib64:/lib:/usr/lib:/usr/local/lib:$LD_LIBRARY_PATH
export DATE=`date +"%Y%m%d%H%M"`
export PATH=$PGHOME/bin:$PATH:.
export MANPATH=$PGHOME/share/man:$MANPATH
export PGHOST=$PGDATA
export PGDATABASE=postgres
export PGUSER=postgres
alias rm='rm -i'
alias ll='ls -lh'
unalias vi
. ~/.bash_profile
pg95@digoal-> initdb -D $PGDATA -U postgres -W -E UTF8 --locale=C
为了快速测试效果,设置1分钟的snapshot,实际应用中用户可以根据实际的需要设置。
vi $PGDATA/postgresql.conf
old_snapshot_threshold = 1min
启动数据库
pg_ctl start
测试:
会话1
postgres=# create table test(id int, crt_time timestamp);
CREATE TABLE
postgres=# insert into test values (1,now()) returning *;
id | crt_time
----+----------------------------
1 | 2015-11-09 14:24:26.161537
(1 row)
INSERT 0 1
会话2,开启一个RC隔离级别的事务
postgres=# begin transaction isolation level repeatable read;
BEGIN
postgres=# select *,now(),clock_timestamp() from test;
id | crt_time | now | clock_timestamp
----+----------------------------+-------------------------------+------------------------------
1 | 2015-11-09 14:24:26.161537 | 2015-11-09 14:24:37.289911+08 | 2015-11-09 14:24:47.88468+08
(1 row)
会话1
postgres=# update test set crt_time=now() where id=1 returning *;
id | crt_time
----+----------------------------
1 | 2015-11-09 14:25:04.101895
(1 row)
UPDATE 1
会话2
postgres=# select *,now(),clock_timestamp() from test;
id | crt_time | now | clock_timestamp
----+----------------------------+-------------------------------+-------------------------------
1 | 2015-11-09 14:24:26.161537 | 2015-11-09 14:24:37.289911+08 | 2015-11-09 14:25:12.821213+08
(1 row)
......
在发生snapshot old错误前,我们看到这个事务占领了一个snapshot id backend_xmin , 数据库无法回收这之后产生的垃圾。
-[ RECORD 2 ]----+-------------------------------------------------------
datid | 13241
datname | postgres
pid | 16575
usesysid | 10
usename | postgres
application_name | psql
client_addr |
client_hostname |
client_port | -1
backend_start | 2015-11-09 14:19:59.45462+08
xact_start | 2015-11-09 14:24:37.289911+08
query_start | 2015-11-09 14:25:12.820912+08
state_change | 2015-11-09 14:25:12.821263+08
waiting | f
state | idle in transaction
backend_xid |
backend_xmin | 1769
query | select *,now(),clock_timestamp() from test;
postgres=# vacuum verbose test;
INFO: vacuuming "public.test"
INFO: "test": found 0 removable, 2 nonremovable row versions in 1 out of 1 pages
DETAIL: 1 dead row versions cannot be removed yet.
There were 0 unused item pointers.
Skipped 0 pages due to buffer pins.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
VACUUM
当这个会话去访问1分钟前的快照时,报错。
postgres=# select *,now(),clock_timestamp() from test;
ERROR: snapshot too old
这个时候,可以回收之前的垃圾了,
postgres=# vacuum verbose test;
INFO: vacuuming "public.test"
INFO: "test": found 1 removable, 1 nonremovable row versions in 1 out of 1 pages
DETAIL: 0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
Skipped 0 pages due to buffer pins.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
VACUUM
因为这个事务已经释放了backend_xmin 。
-[ RECORD 2 ]----+--------------------------------------------
datid | 13241
datname | postgres
pid | 16575
usesysid | 10
usename | postgres
application_name | psql
client_addr |
client_hostname |
client_port | -1
backend_start | 2015-11-09 14:19:59.45462+08
xact_start |
query_start | 2015-11-09 14:26:00.545314+08
state_change | 2015-11-09 14:26:00.545849+08
waiting | f
state | idle in transaction (aborted)
backend_xid |
backend_xmin |
query | select *,now(),clock_timestamp() from test;
再次发起请求直接报要求用户回滚事务。
postgres=# select *,now(),clock_timestamp() from test;
ERROR: current transaction is aborted, commands ignored until end of transaction block
年龄也可以正常的降低:
postgres=# vacuum freeze test;
VACUUM
postgres=# select age(relfrozenxid) from pg_class where relname='test';
age
-----
0
(1 row)
测试游标(貌似snapshot too old对游标不起作用):
会话1
postgres=# insert into test select generate_series(1,100),clock_timestamp();
INSERT 0 100
会话2
postgres=# begin;
BEGIN
postgres=# declare c1 scroll cursor with hold for select * from test order by id;
DECLARE CURSOR
会话1
postgres=# update test set crt_time=now() where id=15;
UPDATE 1
postgres=# select * from test where id=15;
id | crt_time
----+----------------------------
15 | 2015-11-09 14:58:19.889967
(1 row)
会话2,已超1分钟。
postgres=# select clock_timestamp();
clock_timestamp
-------------------------------
2015-11-09 14:59:23.534014+08
(1 row)
无法回收垃圾
postgres=# vacuum verbose test;
INFO: vacuuming "public.test"
INFO: "test": found 0 removable, 102 nonremovable row versions in 1 out of 1 pages
DETAIL: 1 dead row versions cannot be removed yet.
There were 0 unused item pointers.
Skipped 0 pages due to buffer pins.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
VACUUM
fetch前后数据一致。
postgres=# fetch 1 from c1;
id | crt_time
----+----------------------------
10 | 2015-11-09 14:40:16.318757
(1 row)
postgres=# fetch 1 from c1;
id | crt_time
----+---------------------------
11 | 2015-11-09 14:40:16.31876
(1 row)
postgres=# fetch 1 from c1;
id | crt_time
----+----------------------------
12 | 2015-11-09 14:40:16.318763
(1 row)
postgres=# fetch 1 from c1;
id | crt_time
----+----------------------------
13 | 2015-11-09 14:40:16.318765
(1 row)
postgres=# fetch 1 from c1;
id | crt_time
----+----------------------------
14 | 2015-11-09 14:40:16.318767
(1 row)
postgres=# fetch 1 from c1;
id | crt_time
----+----------------------------
15 | 2015-11-09 14:40:16.319126
(1 row)
postgres=# fetch 1 from c1;
id | crt_time
----+---------------------------
16 | 2015-11-09 14:40:16.31915
(1 row)
postgres=# fetch 100 from c1;
id | crt_time
-----+----------------------------
17 | 2015-11-09 14:40:16.319153
18 | 2015-11-09 14:40:16.319155
19 | 2015-11-09 14:40:16.319158
20 | 2015-11-09 14:40:16.31916
21 | 2015-11-09 14:40:16.319163
22 | 2015-11-09 14:40:16.319165
23 | 2015-11-09 14:40:16.319168
24 | 2015-11-09 14:40:16.31917
25 | 2015-11-09 14:40:16.319173
26 | 2015-11-09 14:40:16.319175
27 | 2015-11-09 14:40:16.319178
28 | 2015-11-09 14:40:16.31918
29 | 2015-11-09 14:40:16.319183
30 | 2015-11-09 14:40:16.319185
31 | 2015-11-09 14:40:16.319188
32 | 2015-11-09 14:40:16.31919
33 | 2015-11-09 14:40:16.319193
34 | 2015-11-09 14:40:16.319195
35 | 2015-11-09 14:40:16.319198
36 | 2015-11-09 14:40:16.3192
37 | 2015-11-09 14:40:16.319203
38 | 2015-11-09 14:40:16.319205
39 | 2015-11-09 14:40:16.319208
40 | 2015-11-09 14:40:16.31921
41 | 2015-11-09 14:40:16.319213
42 | 2015-11-09 14:40:16.319215
43 | 2015-11-09 14:40:16.319218
44 | 2015-11-09 14:40:16.31922
45 | 2015-11-09 14:40:16.319222
46 | 2015-11-09 14:40:16.319225
47 | 2015-11-09 14:40:16.319227
48 | 2015-11-09 14:40:16.31923
49 | 2015-11-09 14:40:16.319232
50 | 2015-11-09 14:40:16.319235
51 | 2015-11-09 14:40:16.319237
52 | 2015-11-09 14:40:16.31924
53 | 2015-11-09 14:40:16.319242
54 | 2015-11-09 14:40:16.319245
55 | 2015-11-09 14:40:16.319247
56 | 2015-11-09 14:40:16.31925
57 | 2015-11-09 14:40:16.319252
58 | 2015-11-09 14:40:16.319255
59 | 2015-11-09 14:40:16.319257
60 | 2015-11-09 14:40:16.319259
61 | 2015-11-09 14:40:16.319262
62 | 2015-11-09 14:40:16.319264
63 | 2015-11-09 14:40:16.319267
64 | 2015-11-09 14:40:16.319269
65 | 2015-11-09 14:40:16.319272
66 | 2015-11-09 14:40:16.319274
67 | 2015-11-09 14:40:16.319277
68 | 2015-11-09 14:40:16.319279
69 | 2015-11-09 14:40:16.319282
70 | 2015-11-09 14:40:16.319284
71 | 2015-11-09 14:40:16.319287
72 | 2015-11-09 14:40:16.319303
73 | 2015-11-09 14:40:16.319306
74 | 2015-11-09 14:40:16.319309
75 | 2015-11-09 14:40:16.319311
76 | 2015-11-09 14:40:16.319314
77 | 2015-11-09 14:40:16.319316
78 | 2015-11-09 14:40:16.319319
79 | 2015-11-09 14:40:16.319321
80 | 2015-11-09 14:40:16.319324
81 | 2015-11-09 14:40:16.319326
82 | 2015-11-09 14:40:16.319329
83 | 2015-11-09 14:40:16.319331
84 | 2015-11-09 14:40:16.319334
85 | 2015-11-09 14:40:16.319336
86 | 2015-11-09 14:40:16.319339
87 | 2015-11-09 14:40:16.319341
88 | 2015-11-09 14:40:16.319343
89 | 2015-11-09 14:40:16.319346
90 | 2015-11-09 14:40:16.319348
91 | 2015-11-09 14:40:16.319351
92 | 2015-11-09 14:40:16.319353
93 | 2015-11-09 14:40:16.319356
94 | 2015-11-09 14:40:16.319358
95 | 2015-11-09 14:40:16.319361
96 | 2015-11-09 14:40:16.319363
97 | 2015-11-09 14:40:16.319366
98 | 2015-11-09 14:40:16.319368
99 | 2015-11-09 14:40:16.319371
100 | 2015-11-09 14:40:16.319373
(84 rows)
postgres=# fetch 100 from c1;
id | crt_time
----+----------
(0 rows)
postgres=# \h fetch
Command: FETCH
Description: retrieve rows from a query using a cursor
Syntax:
FETCH [ direction [ FROM | IN ] ] cursor_name
where direction can be empty or one of:
NEXT
PRIOR
FIRST
LAST
ABSOLUTE count
RELATIVE count
count
ALL
FORWARD
FORWARD count
FORWARD ALL
BACKWARD
BACKWARD count
BACKWARD ALL
postgres=# fetch backward 100 from c1;
id | crt_time
-----+----------------------------
100 | 2015-11-09 14:40:16.319373
99 | 2015-11-09 14:40:16.319371
98 | 2015-11-09 14:40:16.319368
97 | 2015-11-09 14:40:16.319366
96 | 2015-11-09 14:40:16.319363
95 | 2015-11-09 14:40:16.319361
94 | 2015-11-09 14:40:16.319358
93 | 2015-11-09 14:40:16.319356
92 | 2015-11-09 14:40:16.319353
91 | 2015-11-09 14:40:16.319351
90 | 2015-11-09 14:40:16.319348
89 | 2015-11-09 14:40:16.319346
88 | 2015-11-09 14:40:16.319343
87 | 2015-11-09 14:40:16.319341
86 | 2015-11-09 14:40:16.319339
85 | 2015-11-09 14:40:16.319336
84 | 2015-11-09 14:40:16.319334
83 | 2015-11-09 14:40:16.319331
82 | 2015-11-09 14:40:16.319329
81 | 2015-11-09 14:40:16.319326
80 | 2015-11-09 14:40:16.319324
79 | 2015-11-09 14:40:16.319321
78 | 2015-11-09 14:40:16.319319
77 | 2015-11-09 14:40:16.319316
76 | 2015-11-09 14:40:16.319314
75 | 2015-11-09 14:40:16.319311
74 | 2015-11-09 14:40:16.319309
73 | 2015-11-09 14:40:16.319306
72 | 2015-11-09 14:40:16.319303
71 | 2015-11-09 14:40:16.319287
70 | 2015-11-09 14:40:16.319284
69 | 2015-11-09 14:40:16.319282
68 | 2015-11-09 14:40:16.319279
67 | 2015-11-09 14:40:16.319277
66 | 2015-11-09 14:40:16.319274
65 | 2015-11-09 14:40:16.319272
64 | 2015-11-09 14:40:16.319269
63 | 2015-11-09 14:40:16.319267
62 | 2015-11-09 14:40:16.319264
61 | 2015-11-09 14:40:16.319262
60 | 2015-11-09 14:40:16.319259
59 | 2015-11-09 14:40:16.319257
58 | 2015-11-09 14:40:16.319255
57 | 2015-11-09 14:40:16.319252
56 | 2015-11-09 14:40:16.31925
55 | 2015-11-09 14:40:16.319247
54 | 2015-11-09 14:40:16.319245
53 | 2015-11-09 14:40:16.319242
52 | 2015-11-09 14:40:16.31924
51 | 2015-11-09 14:40:16.319237
50 | 2015-11-09 14:40:16.319235
49 | 2015-11-09 14:40:16.319232
48 | 2015-11-09 14:40:16.31923
47 | 2015-11-09 14:40:16.319227
46 | 2015-11-09 14:40:16.319225
45 | 2015-11-09 14:40:16.319222
44 | 2015-11-09 14:40:16.31922
43 | 2015-11-09 14:40:16.319218
42 | 2015-11-09 14:40:16.319215
41 | 2015-11-09 14:40:16.319213
40 | 2015-11-09 14:40:16.31921
39 | 2015-11-09 14:40:16.319208
38 | 2015-11-09 14:40:16.319205
37 | 2015-11-09 14:40:16.319203
36 | 2015-11-09 14:40:16.3192
35 | 2015-11-09 14:40:16.319198
34 | 2015-11-09 14:40:16.319195
33 | 2015-11-09 14:40:16.319193
32 | 2015-11-09 14:40:16.31919
31 | 2015-11-09 14:40:16.319188
30 | 2015-11-09 14:40:16.319185
29 | 2015-11-09 14:40:16.319183
28 | 2015-11-09 14:40:16.31918
27 | 2015-11-09 14:40:16.319178
26 | 2015-11-09 14:40:16.319175
25 | 2015-11-09 14:40:16.319173
24 | 2015-11-09 14:40:16.31917
23 | 2015-11-09 14:40:16.319168
22 | 2015-11-09 14:40:16.319165
21 | 2015-11-09 14:40:16.319163
20 | 2015-11-09 14:40:16.31916
19 | 2015-11-09 14:40:16.319158
18 | 2015-11-09 14:40:16.319155
17 | 2015-11-09 14:40:16.319153
16 | 2015-11-09 14:40:16.31915
15 | 2015-11-09 14:40:16.319126
14 | 2015-11-09 14:40:16.318767
13 | 2015-11-09 14:40:16.318765
12 | 2015-11-09 14:40:16.318763
11 | 2015-11-09 14:40:16.31876
10 | 2015-11-09 14:40:16.318757
9 | 2015-11-09 14:40:16.318755
8 | 2015-11-09 14:40:16.318753
7 | 2015-11-09 14:40:16.31875
6 | 2015-11-09 14:40:16.318748
5 | 2015-11-09 14:40:16.318745
4 | 2015-11-09 14:40:16.318743
3 | 2015-11-09 14:40:16.31874
2 | 2015-11-09 14:40:16.318733
1 | 2015-11-09 14:40:16.318608
(100 rows)
postgres=# fetch backward 100 from c1;
id | crt_time
----+----------------------------
1 | 2015-11-09 14:25:04.101895
(1 row)
postgres=# fetch backward 100 from c1;
id | crt_time
----+----------
(0 rows)
postgres=# fetch 1000 from c1;
id | crt_time
-----+----------------------------
1 | 2015-11-09 14:25:04.101895
1 | 2015-11-09 14:40:16.318608
2 | 2015-11-09 14:40:16.318733
3 | 2015-11-09 14:40:16.31874
4 | 2015-11-09 14:40:16.318743
5 | 2015-11-09 14:40:16.318745
6 | 2015-11-09 14:40:16.318748
7 | 2015-11-09 14:40:16.31875
8 | 2015-11-09 14:40:16.318753
9 | 2015-11-09 14:40:16.318755
10 | 2015-11-09 14:40:16.318757
11 | 2015-11-09 14:40:16.31876
12 | 2015-11-09 14:40:16.318763
13 | 2015-11-09 14:40:16.318765
14 | 2015-11-09 14:40:16.318767
15 | 2015-11-09 14:40:16.319126
16 | 2015-11-09 14:40:16.31915
17 | 2015-11-09 14:40:16.319153
18 | 2015-11-09 14:40:16.319155
19 | 2015-11-09 14:40:16.319158
20 | 2015-11-09 14:40:16.31916
21 | 2015-11-09 14:40:16.319163
22 | 2015-11-09 14:40:16.319165
23 | 2015-11-09 14:40:16.319168
24 | 2015-11-09 14:40:16.31917
25 | 2015-11-09 14:40:16.319173
26 | 2015-11-09 14:40:16.319175
27 | 2015-11-09 14:40:16.319178
28 | 2015-11-09 14:40:16.31918
29 | 2015-11-09 14:40:16.319183
30 | 2015-11-09 14:40:16.319185
31 | 2015-11-09 14:40:16.319188
32 | 2015-11-09 14:40:16.31919
33 | 2015-11-09 14:40:16.319193
34 | 2015-11-09 14:40:16.319195
35 | 2015-11-09 14:40:16.319198
36 | 2015-11-09 14:40:16.3192
37 | 2015-11-09 14:40:16.319203
38 | 2015-11-09 14:40:16.319205
39 | 2015-11-09 14:40:16.319208
40 | 2015-11-09 14:40:16.31921
41 | 2015-11-09 14:40:16.319213
42 | 2015-11-09 14:40:16.319215
43 | 2015-11-09 14:40:16.319218
44 | 2015-11-09 14:40:16.31922
45 | 2015-11-09 14:40:16.319222
46 | 2015-11-09 14:40:16.319225
47 | 2015-11-09 14:40:16.319227
48 | 2015-11-09 14:40:16.31923
49 | 2015-11-09 14:40:16.319232
50 | 2015-11-09 14:40:16.319235
51 | 2015-11-09 14:40:16.319237
52 | 2015-11-09 14:40:16.31924
53 | 2015-11-09 14:40:16.319242
54 | 2015-11-09 14:40:16.319245
55 | 2015-11-09 14:40:16.319247
56 | 2015-11-09 14:40:16.31925
57 | 2015-11-09 14:40:16.319252
58 | 2015-11-09 14:40:16.319255
59 | 2015-11-09 14:40:16.319257
60 | 2015-11-09 14:40:16.319259
61 | 2015-11-09 14:40:16.319262
62 | 2015-11-09 14:40:16.319264
63 | 2015-11-09 14:40:16.319267
64 | 2015-11-09 14:40:16.319269
65 | 2015-11-09 14:40:16.319272
66 | 2015-11-09 14:40:16.319274
67 | 2015-11-09 14:40:16.319277
68 | 2015-11-09 14:40:16.319279
69 | 2015-11-09 14:40:16.319282
70 | 2015-11-09 14:40:16.319284
71 | 2015-11-09 14:40:16.319287
72 | 2015-11-09 14:40:16.319303
73 | 2015-11-09 14:40:16.319306
74 | 2015-11-09 14:40:16.319309
75 | 2015-11-09 14:40:16.319311
76 | 2015-11-09 14:40:16.319314
77 | 2015-11-09 14:40:16.319316
78 | 2015-11-09 14:40:16.319319
79 | 2015-11-09 14:40:16.319321
80 | 2015-11-09 14:40:16.319324
81 | 2015-11-09 14:40:16.319326
82 | 2015-11-09 14:40:16.319329
83 | 2015-11-09 14:40:16.319331
84 | 2015-11-09 14:40:16.319334
85 | 2015-11-09 14:40:16.319336
86 | 2015-11-09 14:40:16.319339
87 | 2015-11-09 14:40:16.319341
88 | 2015-11-09 14:40:16.319343
89 | 2015-11-09 14:40:16.319346
90 | 2015-11-09 14:40:16.319348
91 | 2015-11-09 14:40:16.319351
92 | 2015-11-09 14:40:16.319353
93 | 2015-11-09 14:40:16.319356
94 | 2015-11-09 14:40:16.319358
95 | 2015-11-09 14:40:16.319361
96 | 2015-11-09 14:40:16.319363
97 | 2015-11-09 14:40:16.319366
98 | 2015-11-09 14:40:16.319368
99 | 2015-11-09 14:40:16.319371
100 | 2015-11-09 14:40:16.319373
(101 rows)
回滚后可以正常回收垃圾。
postgres=# rollback;
ROLLBACK
postgres=# vacuum verbose test;
INFO: vacuuming "public.test"
INFO: "test": found 1 removable, 101 nonremovable row versions in 1 out of 1 pages
DETAIL: 0 dead row versions cannot be removed yet.
There were 0 unused item pointers.
Skipped 0 pages due to buffer pins.
0 pages are entirely empty.
CPU 0.00s/0.00u sec elapsed 0.00 sec.
VACUUM
参考
1. http://www.postgresql.org/message-id/flat/BLU437-SMTP193E7367B788D2EC2B2B81DC160@phx.gbl#BLU437-SMTP193E7367B788D2EC2B2B81DC160@phx.gbl
2. http://git.postgresql.org/gitweb/?p=postgresql.git;a=snapshot;h=aa7f9493a02f5981c09b924323f0e7a58a32f2ed;sf=tgz
3. http://blog.163.com/digoal@126/blog/static/1638770402015329115636287/