PostgreSQL VACUUM 没有效果(无法清理死元组)的原因
众所周知,在PostgreSQL里面使用VACUUM FULL来回收dead tuples空间并将其返回给操作系统。但是我执行VACUUM FULL却没有任何效果,是数据库版本出现了bug?当然不是!
经排查原来是Physical Replication Slot导致(具体解释见http://mysql.taobao.org/monthly/2015/02/03/)。将hot_standby_feedback设为on时,从库关闭,主库的xmin不再改变,主库的vaccum操作停滞,造成主库被频繁更新的表大小暴增。
为什么VACUUM不清理死元组
?
VACUUM
只能删除不再需要的那些行版本(也称为“元组”)。如果删除事务的事务 ID(存储在xmax
中)早于 PostgreSQL 数据库(或共享表的整个集群)中仍处于活动状态的最旧事务,则无法清除元组。
在 PostgreSQL 集群中,有三件事可以阻止这个VACUUM回收死元组:
-
长时间运行的事务:
可以通过以下查询找到长时间运行的事务及其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
. -
废弃的Replication Slot:
复制槽是一种数据结构,保持从主库丢弃但仍需要由备用服务器赶上主要信息PostgreSQL服务器的数据。
如果复制延迟或备用服务器关闭,复制槽将阻止
VACUUM
删除旧行。可以使用此查询找到所有复制槽及其xmin值:
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
在这种情况下检查列。 -
孤立的准备运行的事务:
在两阶段提交期间,分布式事务首先用
PREPARE
语句准备,然后用COMMIT PREPARED
语句提交。一旦一个事务准备好,它就会一直“等待”直到它被提交或中止。它甚至必须在服务器重启后还需要保留下来!通常,事务不会长时间保持准备状态,但有时会出错,必须由管理员手动删除准备好的事务。
可以
xmin
使用以下查询找到所有准备好的交易及其价值:SELECT gid, prepared, owner, database, transaction AS xmin FROM pg_prepared_xacts ORDER BY age(transaction) DESC;
使用
ROLLBACK PREPARED
SQL 语句删除准备好的事务。
原文地址:https://www.cnblogs.com/VicLiu/p/15392814.html
- MySQL主从不一致的细小问题分析(r12笔记第62天)
- Linux在批量服务器管理中实用的PS1命令提示符格式
- Golang语言社区-并发模型和应用场景
- 翻过那座山,就能看见海|kubernetes让DBA更优雅地管理数据库
- 基于TextCNN的谩骂评论识别模型
- Golang语言社区-文件操作
- MySQL service启动脚本浅析(r12笔记第59天)
- 分享WordPress显示评论者IP的归属地及运营商信息的2种方案
- 解决dos2unix/unix2dos报错,并在家目录下生成u2dtmp*文件问题
- 【前沿】TensorFlow Pytorch Keras代码实现深度学习大神Hinton NIPS2017 Capsule论文
- Nginx通过二级目录(路径)映射不同的反向代理,规避IP+端口访问
- MySQL中批量初始化数据的对比测试(r12笔记第71天)
- Golang语言--包的概念、导入与可见性
- MySQL中的change,modify和自增列的关系(r12笔记第70天)
- MySQL 教程
- MySQL 安装
- MySQL 管理与配置
- MySQL PHP 语法
- MySQL 连接
- MySQL 创建数据库
- MySQL 删除数据库
- MySQL 选择数据库
- MySQL 数据类型
- MySQL 创建数据表
- MySQL 删除数据表
- MySQL 插入数据
- MySQL 查询数据
- MySQL where 子句
- MySQL UPDATE 查询
- MySQL DELETE 语句
- MySQL LIKE 子句
- mysql order by
- Mysql Join的使用
- MySQL NULL 值处理
- MySQL 正则表达式
- MySQL 事务
- MySQL ALTER命令
- MySQL 索引
- MySQL 临时表
- MySQL 复制表
- 查看MySQL 元数据
- MySQL 序列 AUTO_INCREMENT
- MySQL 处理重复数据
- MySQL 及 SQL 注入
- MySQL 导出数据
- MySQL 导入数据
- MYSQL 函数大全
- MySQL Group By 实例讲解
- MySQL Max()函数实例讲解
- mysql count函数实例
- MYSQL UNION和UNION ALL实例
- MySQL IN 用法
- MySQL between and 实例讲解