根据 PostgreSQL 的 MVCC 机制,数据被插入时 PostgreSQL会分配给每行 tuples一个事务ID,即表上的隐含字段 Xmin, 而 PostgreSQL 的事务号由 32 bit 位 ( 40 亿) 组成,事务号分配完了后会循环,这样会造成过去的记录不可见的情况,为了解决这个问题,理论上在 20 亿事务之内需要 vacuum 每一个数据库的每一个表, 而vacuum 操作会替换某些老记录的xid 成 FrozenXID,这样即使事务号循环,这些被替换成 FrozenXID 的记录依然对当前事务可见,下面是模拟表数据的tuples 的xid 被替换成 FrozenXID 的几个例子。
Freezing 实验一 ( vacuum freeze )
1.1 创建测试表并插入测试数据
1 |
mydb=> create table test_vacuum1(id integer,name varchar(32)); |
1.2 查询表及tuples 的年龄
1 |
mydb=> select relname,relfrozenxid,age(relfrozenxid) from pg_class where relname='test_vacuum1'; |
1.3 执行 vacuum freeze
1 |
mydb=> vacuum freeze test_vacuum1; |
备注:对表 test_vacuum1 执行 vacuum freeze 后,test_vacuum1 上的所有记录被 frozen,即 xmin 值被修改,并且 tuples 的年龄为 2147483647,这个 XID 比较特殊,不参与普通 XID的比较,可以认为这个 XID 比 所有 XID 都老。
Freezing 实验二 ( vacuum )
–2.1 创建表并插入测试数据
1 |
mydb=> create table test_vacuum2 (id integer,name varchar(32)); |
2.2 查看表和 tuples 年龄
1 |
mydb=> select relname,relfrozenxid,age(relfrozenxid) from pg_class where relname='test_vacuum2'; |
2.3 设置 session 级 vacuum_freeze_min_age 参数,并 vacuum
1 |
mydb=> set vacuum_freeze_min_age=10; |
备注:发现 test_vaccum2 的记录 xmin 被替换成 frozenXID。
Freezing 实验三 ( autovacuum )
3.1 创建测试表并插入数据
1 |
mydb=> create table test_vacuum3(id integer,name varchar(32)); |
3.2 修改表的 autovacuum_freeze_min_age 参数
1 |
mydb=> alter table test_vacuum3 set (autovacuum_freeze_min_age = 0); |
3.3 删除 250 条记录,触发 autovacuum
1 |
mydb=> delete from test_vacuum3 where id < 251; |
备注:关于删除多少条记录会触发 autovacuum,可以参考之前写的 blog: https://postgres.fun/20110314162516.html
3.4 观察 CSV 日志
在上步 delete 数据后,等一会,如果看到以下日志,说明表 test_vacuum3 被 autovacuum 进程 vacuum了。
1 |
2012-05-06 21:42:04.864 CST,,,32232,,4fa67fac.7de8,1,,2012-05-06 21:42:04 CST,3/397,3660,LOG,00000,"automatic analyze of table ""mydb.mydb.test_vacuum3"" system usage: CPU 0.00s/0.00u sec elapsed 0.01 sec",,,,,,,,,"" |
备注:修改表的 autovacuum_freeze_min_age 参数,目标是让表的 tuples 在 autovacuum 时即被 frozenXID替换。
3.5 再次查看表和 tuples 的年龄
1 |
mydb=> select relname,relfrozenxid,age(relfrozenxid) from pg_class where relname='test_vacuum3'; |
备注:表 test_vacuum3 的 xmin 已经被 FrozenXID 替换,其中实验三需要触发两个条件,第一需要想办法触发 autovacuum,第二需设置事务时长,触发表上记录被 FrozenXID 替换。
参考
- http://blog.163.com/digoal@126/blog/static/1638770402011830105342275/
- http://www.postgresql.org/docs/9.1/static/sql-vacuum.html
- http://www.postgresql.org/docs/9.1/static/routine-vacuuming.html#VACUUM-FOR-WRAPAROUND
原创文章,作者:1402239773,如若转载,请注明出处:https://blog.ytso.com/tech/database/237849.html