一、为什么是VACUUM?

每当更新或删除PostgreSQL表中的行时,都会留下死元组。VACUUM摆脱了它们,以便空间可以重复使用。如果一个表没有被清理,它就会变得臃肿,这会浪费磁盘空间并减慢表的顺序扫描(以及索引扫描)。VACUUM还负责冻结表行,以避免在事务ID计数器环绕时出现问题,但这是另一回事。通常,您不必处理所有这些,因为PostgreSQL中内置的autovacuum 守护程序会为您完成这些工作。

二、问题

如果你的表变得臃肿,首先你需要检查的是 autovacuum 是否已处理它们:

SELECT schemaname, relname, n_live_tup, n_dead_tup, last_autovacuum
FROM pg_stat_all_tables
ORDER BY n_dead_tup
/ (n_live_tup
* current_setting('autovacuum_vacuum_scale_factor')::float8
+ current_setting('autovacuum_vacuum_threshold')::float8)
DESC
LIMIT 10;

如果你的臃肿的表没有出现在这里,n_dead_tup是0并且last_autovacuum是 NULL,你可能有统计信息收集器的问题。

如果臃肿的表就在顶部,但last_autovacuum为NULL,则您可能需要将autovacuum 配置为更积极,以便完成对表的处理。

但有时结果会如下所示:

schemaname |    relname   | n_live_tup | n_dead_tup |   last_autovacuum
------------+--------------+------------+------------+---------------------
laurenz | vacme | 50000 | 50000 | 2018-02-22 13:20:16
pg_catalog | pg_attribute | 42 | 165 |
pg_catalog | pg_amop | 871 | 162 |
pg_catalog | pg_class | 9 | 31 |
pg_catalog | pg_type | 17 | 27 |
pg_catalog | pg_index | 5 | 15 |
pg_catalog | pg_depend | 9162 | 471 |
pg_catalog | pg_trigger | 0 | 12 |
pg_catalog | pg_proc | 183 | 16 |
pg_catalog | pg_shdepend | 7 | 6 |
(10 rows)

autovacuum最近在这里运行,但它没有释放死元组!

我们可以通过运行VACUUM (VERBOSE)来验证问:

test=> VACUUM (VERBOSE) vacme;
INFO: vacuuming "laurenz.vacme"
INFO: "vacme": found 0 removable, 100000 nonremovable row versions in
443 out of 443 pages
DETAIL: 50000 dead row versions cannot be removed yet,
oldest xmin: 22300
There were 0 unused item pointers.
Skipped 0 pages due to buffer pins, 0 frozen pages.
0 pages are entirely empty.
CPU: user: 0.01 s, system: 0.00 s, elapsed: 0.01 s.

三、为什么VACUUM不能删除死元组?

VACUUM只能删除不再需要的那些行版本(也称为“元组”)。如果删除事务的事务 ID(存储在xmax中)早于 PostgreSQL 数据库(或共享表的整个集群)中仍处于活动状态的最旧事务,则无法清除元组。

这个值(VACUUM上面输出中的 22300)称为“xmin 水平”。

在 PostgreSQL集群中,有三件事可以阻止这个xmin范围:

1、长时间运行的事务:

可以通过以下查询找到长时间运行的事务及其xmin值:

SELECT pid, datname, usename, state, backend_xmin
FROM pg_stat_activity
WHERE backend_xmin IS NOT NULL
ORDER BY age(backend_xmin) DESC;

可以使用该pg_terminate_backend()函数来终止阻止您的VACUUM.

2、废弃的Replication Slot:

复制槽是一种数据结构,保持从主库丢弃但仍需要由备用服务器赶上主要信息PostgreSQL服务器的数据。

如果复制延迟或备用服务器关闭,复制槽将阻

SELECT slot_name, slot_type, database, xmin
FROM pg_replication_slots
ORDER BY age(xmin) DESC;

使用该pg_drop_replication_slot()函数删除不再需要的复制槽。

注意:如果hot_standby_feedback = on. 对于逻辑复制存在类似的危险(无法回收元组),但只有系统目录受到影响。catalog_xmin在这种情况下检查列。

hot_standby_feedback参数之后备库会定期向主库通知最小活跃事务id(xmin)值,这样使得主库vacuum进程不会清理大于xmin值的事务。

3、孤立的准备运行的事务:

在两阶段提交期间,分布式事务首先用PREPARE语句准备,然后用COMMIT PREPARED语句提交。

一旦一个事务准备好,它就会一直“等待”直到它被提交或中止。它甚至必须在服务器重启后还需要保留下来!通常,事务不会长时间保持准备状态,但有时会出错,必须由管理员手动删除准备好的事务。

可以xmin使用以下查询找到所有准备好的交易及其价值:

SELECT gid, prepared, owner, database, transaction AS xmin
FROM pg_prepared_xacts
ORDER BY age(transaction) DESC;

使用ROLLBACK PREPAREDSQL 语句删除准备好的事务。

 

postgresql VACUUM 不会从表中删除死行的三个原因的更多相关文章

  1. InnoDB引擎,从大表中删除多行

    官方建议: InnoDB Tables If you are deleting many rows from a large table, you may exceed the lock table ...

  2. 一定要 先删除 sc表 中的 某元组 行,,, 再删除 course表中的 元组行

    一定要  先删除 sc表 中的  某元组   行,,, 再删除  course表中的  元组行 course表 SC表 删除  course表中的  元组行,,出现错误 sc    ---->参 ...

  3. 解决在mysql表中删除自增id数据后,再添加数据时,id不会自增1的问题

    https://blog.csdn.net/shaojunbo24/article/details/50036859 问题:mysql表中删除自增id数据后,再添加数据时,id不会紧接.比如:自增id ...

  4. SQL语句的使用,SELECT - 从数据库表中获取数据 UPDATE - 更新数据库表中的数据 DELETE - 从数据库表中删除数据 INSERT INTO - 向数据库表中插入数据

    SQL DML 和 DDL 可以把 SQL 分为两个部分:数据操作语言 (DML) 和 数据定义语言 (DDL). SQL (结构化查询语言)是用于执行查询的语法. 但是 SQL 语言也包含用于更新. ...

  5. SQL中将某个表中的多行数据在一个字段显示

    项目需求:将某个表中的多行数据在一个字段显示,如下: 比如表A中有字段 ID,NAME, 表B中有字段ID,PID,DES, 表A,表B中的数据分别如下: ID NAME1 张三2 李四 ID PID ...

  6. INSERT - 在表中创建新行

    SYNOPSIS INSERT INTO table [ ( column [, ...] ) ] { DEFAULT VALUES | VALUES ( { expression | DEFAULT ...

  7. 函数模块:CTVB_COMPARE_TABLES--两个表中删除/变更/粘贴分解

    这个函数模块比较两个内表,将被删除.增加和修改的内表行分别分组输出. 输入参数:TABLE_OLD:旧表TABLE_NEW:新表KEY_LENGTH:键长度,指定内表中的前若干个字节(在 Unicod ...

  8. 从表中删除重复记录的sql

    --有一个表,假设是这样的 CREATE TABLE Test ( field1 ) primary key, field2 )); --假设field1上有索引. 要删除表中所有field1重复的记 ...

  9. MYSQL delete 从多人表中删除

    语法 1. delete table_list_A from table_list_B where bool_expression; 从delete_table_list_A 删除 bool expr ...

  10. C# DataAdapter.Update() 无法更新数据表中删除的数据行

    用DataAdapter.Update() 方法更新删除了部分DataRow 的 DataTable .但是数据库中的数据没有随着更新而变化. 原因:DataTable 删除 DataRow 时,使用 ...

随机推荐

  1. 【每日一题】2021年12月11日-69. Sqrt(x)/x的平方根

    给你一个非负整数 x ,计算并返回 x 的 算术平方根 . 由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 . 注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或 ...

  2. 【FAQ】申请Health Kit权限的常见问题及解答

    华为运动健康服务(HUAWEI Health Kit)提供原子化数据开放,用户数据被授权获取后,应用可通过接口访问运动健康数据,对相关数据进行增.删.改.查等操作.这篇文章汇总了申请开通Health ...

  3. week_4

    Andrew Ng 机器学习笔记---by Orangestar Week4_Neural Networks : Representation 1. Non-linear Hypotheses 当特征 ...

  4. ESXI 7.0封装网卡驱动

    前段时间配置的All In One 主机,由于华擎H410M-ITX/AC主板的板载网卡为intel I219-V,在安装ESXI后网卡无法驱动.查询之后发现原来ESXI7.0.2的版本不含该网卡驱动 ...

  5. 腾讯微信开源数据库PhxSQL简单部署记录

    1.建立文件夹与互信关系 [root@mysql-100 ~]# mkdir -p /app/soft/phxsql [root@mysql-100 phxsql]# ssh-keygen -t rs ...

  6. (22)go-micro微服务kibana使用

    目录 一 kibana介绍 二 Kibana主要功能 三 Kibana侧边栏 四 Kibana安装 1.拉取镜像 2.运行命令 3.查看是否运行 五 Kibana使用 六 Kibana图形化界面 七 ...

  7. 都用过@Autowired,但你知道它是怎么实现的吗

    前言 在使用Spring开发的时候,配置的方式主要有两种,一种是xml的方式,另外一种是 java config的方式.在使用的过程中java config,我们难免会与注解进行各种打交道,其中,我们 ...

  8. LinkedList集合-Vector集合

    LinkedList集合 java.util.LinkedList集合数据存储的结构是链表结构.方便元素添加.删除的集合.LinkedList是一个双向链表,那么双向链表是什么样子的呢,我们用个图了解 ...

  9. Quartz.Net 官方教程 Best Practices

    最佳实践 JobDataMap 建议只存储基本数据(含String),避免序列化问题 作业执行期间,JobDetail和Trgger的底层共用一个JobDataMap 实例,因此Trigger的数据会 ...

  10. Linux存储服务

    存储服务 一.概述 存储:用于存放用户上传的内容(数据),一般应用在网站集群中 为什么要存储? 如果不使用存储,用户上传的数据就直接存放在某一台网站服务器上了,用户下次访问就可能找不到 如果使用存储, ...