一、为什么是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. docker入门(利用docker部署web应用)

    第一章 什么是docker1.1 docker的发展史2010年几个年轻人成立了一个做PAAS平台的公司dotCloud.起初公司发展的不错,不但拿到过一些融资,还获得了美国著名孵化器YCombina ...

  2. 在windows下导入react项目并且打包编译后部署到nginx上

    在windows下导入react项目并且打包编译后部署到nginx上 一.安装npm 二.创建react项目 三.安装nginx 四.总结 最近接手了公司的一个django项目,这是应该前后端分离的项 ...

  3. 【机器学习】李宏毅——Transformer

    Transformer具体就是属于Sequence-to-Sequence的模型,而且输出的向量的长度并不能够确定,应用场景如语音辨识.机器翻译,甚至是语音翻译等等,在文字上的话例如聊天机器人.文章摘 ...

  4. avue框架 拼接后端返回的数据到table中

    根据要求展示下列详细地址情况: 后端返回的数据: 具体实现步骤: { label: "详细地址", prop: "buildingName", display: ...

  5. 判断条件为NULL

    在ASCII码表里NULL的二进制位0.所以NULL作为判断条件时,表示为假的意思. ASCII表               二进制                       字符         ...

  6. 《HelloGitHub》第 81 期

    兴趣是最好的老师,HelloGitHub 让你对编程感兴趣! 简介 HelloGitHub 分享 GitHub 上有趣.入门级的开源项目. https://github.com/521xueweiha ...

  7. [OpenCV实战]19 使用OpenCV实现基于特征的图像对齐

    目录 1 背景 1.1 什么是图像对齐或图像对准? 1.2 图像对齐的应用 1.3 图像对齐基础理论 1.4 如何找到对应点 2 OpenCV的图像对齐 2.1 基于特征的图像对齐的步骤 2.2 代码 ...

  8. [编程基础] Python中的绝对导入与相对导入

    如果您从事的Python项目有多个文件,那么您以前可能不得不使用import语句.即使对于拥有多个项目的Python重度使用者(比如我),import也可能会造成混淆!您可能正在阅读本文,因为您想对P ...

  9. 降本超30%,智聆口语通过 TKE 注册节点实现 IDC GPU 节点降本增效实践

    背景介绍 腾讯云智聆口语评测(Smart Oral Evaluation,SOE)是腾讯云推出的中英文语音评测产品,支持从儿童到成人全年龄覆盖的语音评测,提供单词.句子.段落.自由说等多种评测模式,从 ...

  10. NW js 打包入门教程

    NW js 打包入门教程 NW.JS的安装与打包_u013288292的博客-CSDN博客_nwjs打包