标签
PostgreSQL , Freeze , 风暴
背景
PostgreSQL 目前默认的存储引擎,事务可见性需要依赖行头的事务号,因为事务号是32位的,会循环使用。
在一条记录产生后,如果再次经历了20亿个事务,必须对其进行freeze,否则数据库会认为这条记录是未来事务产生的(可见性判断)。
因此FREEZE操作是数据库在32位事务号的情况下,经常要做的。
对全表进行FREEZE操作时,会扫描整表,将大于指定阈值least(autovacuum_freeze_min_age, 表级参数vacuum_freeze_min_age)年龄的记录设置为freeze。可能导致大量的读IO,写IO(主要是写数据文件,WAL日志, full page write WAL)。
一些参数决定数据库在什么时候触发FREEZE,以及触发FREEZE时,冻结哪些记录,以及是否涉及到调度(sleep)。
同时很多参数有库级、表级选项。表级优先,然后是库级,最后是实例级。
1、多久检查一次哪些表是否需要FREEZE
postgres=# show autovacuum_naptime ;
autovacuum_naptime
--------------------
1s
(1 row)
2、哪些表需要被自动FREEZE,
超过如下阈值,如果设置了表级参数则以表级参数为准,否则以系统参数为准。
表级参数
autovacuum_freeze_max_age
autovacuum_freeze_table_age
系统级参数
autovacuum_freeze_max_age
3、手工执行普通vacuum时,哪些表会被扫描全表,并freeze
超过如下阈值
系统级参数
vacuum_freeze_table_age
注意,现在PG支持VM文件里面记录一个PAGE是否需要被FREEZE,所以即使全表扫描,也会根据VM标记位,跳过一些BLOCK,所以FREEZE并不一定会产生大量读IO。根据表的情况而定。
3、触发FREEZE时,哪些记录需要被FREEZE
超过如下阈值的记录被FREEZE,如果设置了表级参数则以表级参数为准,否则以系统参数为准。