也聊聊PostgreSQL中的空间膨胀与AutoVacuum

news/2024/7/9 23:28:07 标签: postgresql, 数据库
微信公众号:数据库杂记   个人微信: _iihero
我是iihero. 也可以叫我Sean.
iihero@CSDN(https://blog.csdn.net/iihero) 
Sean@墨天轮 (https://www.modb.pro/u/16258)
iihero@zhihu (https://www.zhihu.com/people/iihero)
数据库领域的资深爱好者一枚。SAP数据库技术专家与架构师,PostgreSQL ACE.
水木早期数据库论坛发起人db2@smth. 早期多年水木论坛数据库版版主。
国内最早一批DB2 DBA。前后对Sybase, PostgreSQL, HANA, 
Oracle, DB2, SQLite均有涉猎。曾长期担任CSDN相关数据库版版主。
三本著作:<<Java2网络协议内幕>> <<Oracle Spatial及OCI高级编程>> 
<<Sybase ASE 15.X全程实践>>
兴趣领域:数据库技术及云计算、GenAI

业余专长爱好:中国武术六段 陈式太极拳第13代传人(北京陈式太极拳第5代传人)
职业太极拳教练,兼任北京陈式太极拳研究会副秘书长。
如果想通过习练陈式太极拳强身健体,也可以与我联系。

1、前言介绍

PostgreSQL数据库,由于其自身特有的MVCC机制,它没有自己的Undo Log。更新操作相当于一个删除叠加一个插入操作,反映在表数据文件当中就是内部的一条新增记录,加上原有记录的删除。那些已被删除的元组(死元组)所占的空间如果得不到及时的回收,那么表数据文件所用空间将会不断膨胀,查询及其它CUD操作也会变慢,直到系统不可承受。这就是AutoVaccum存在的原因。

这也是PostgreSQL MVCC背后的基本思想之一,因为它允许更大并发,在不同的进程之间最小的锁定.这个MVCC实现的缺点是留下了已删除的元组,即使在所有可能看到这些版本的事务完成之后也是如此.可以想见,为何PostgreSQL在并发读写的测试中,很多场景下为何性能异常优秀。

如果是一名DB Ops或DBA,对这种空间膨胀缺乏必要的异常监控,一旦出问题,系统也将变得容易出问题,有时候会酿成大问题。

2、并发控制中的增删改

为了方便理解空间的膨胀以及死元组,我们可以用小实验来简单体会一下。
我们建一张两个字段的表,并插入一行值:

CREATE TABLE t1 (id int, col2 varchar(32));
insert into t1 values(1, 'wang');

查询一下它的基本情况,包括一些常规的内置字段:

mydb=# select tableoid, ctid, xmin, xmax, cmin, cmax, * from t1;
 tableoid | ctid  | xmin | xmax | cmin | cmax | id | col2
----------+-------+------+------+------+------+----+------
    21377 | (0,1) | 1395 |    0 |    0 |    0 |  1 | wang
(1 row)

看一下,会有点小吃惊,多达6个内置字段。回想,我们在PG中有400多个keyword. (用SELECT word FROM pg_get_keywords()可以得,略过),但是那些keyword里并不包含tableoid之类的。但是你如果想建表,字段名称与上边的内置字段相重,建表会失败的。如果遇到别的数据库,刚好有这几个字段中的几个,移植过来,就得想办法了。我们来看看这6个字段的含义:

  • tableoid:指的是table t1的对象标识id (OID)的值,它在表对象一级是全局唯一的。使用下边的查询一样可以得到它的值。并且顺便得到table对应的文件路径(base/21371/21465):
mydb=# select oid, pg_relation_filepath(oid), relname, relkind, relpages from pg_class where relname = 't1';
  oid  | pg_relation_filepath | relname | relkind | relpages
-------+----------------------+---------+---------+----------
 21377 | base/21371/21465     | t1      | r       |        0
ctid: 元组的id, 它相当于一个坐标值(pair), 第一个元素描述的是页号,
第二个元素描述的是元组在页内的序号。
  • xmin, xmax: 最小最大事务号, 这里有一定的规则。我们任意时刻都可以

使用txid_current()得到当前的事务号。

\1) 如果是插入操作,xmin取的是当前的事务号, xmax置为0

\2) 如果是删除操作,使用xmax标识当前的事务号

\3) 如果是更新操作,相当于旧行做一个删除,然后插入一个新行

  • cmin, cmax: 最小最大command id,记录的是事务当中的第几个命令和命令范围。

大致明白了这些字段含义,我们可以进一步往下处理。这里要用到pageinspect

内置插件。大家可以自行安装:(create extension pageinspect),需要

用到函数:heap_page_items以及get_raw_page。

做一次删除操作:

mydb=*# select txid_current();
 txid_current
--------------
         1400
(1 row)
mydb=*# delete from t1;
DELETE 1
mydb=*# select tableoid, ctid, xmin, xmax, cmin, cmax, * from t1;
 tableoid | ctid | xmin | xmax | cmin | cmax | id | col2
----------+------+------+------+------+------+----+------
(0 rows)
mydb=*# SELECT lp as tuple, t_xmin, t_xmax, t_field3 as t_cid, t_ctid, t_data
FROM heap_page_items(get_raw_page('t1', 0));
 tuple | t_xmin | t_xmax | t_cid | t_ctid |        t_data
-------+--------+--------+-------+--------+----------------------
     1 |   1395 |   1400 |     0 | (0,1)  | \x010000000b77616e67
(1 row)
我们会发现,t_xmax的值变了,变成1400了。它是新的txid。比t_xmin大。
再插入一条新记录,然后更新一下那条记录看下:
mydb=# begin;
BEGIN
mydb=*# select pg_current_xact_id(), txid_current();
 pg_current_xact_id | txid_current
--------------------+--------------
               1401 |         1401
(1 row)

mydb=*# delete from t1;
DELETE 1
mydb=*# SELECT lp as tuple, t_xmin, t_xmax, t_field3 as t_cid, t_ctid, t_data
FROM heap_page_items(get_raw_page('t1', 0));
 tuple | t_xmin | t_xmax | t_cid | t_ctid |        t_data
-------+--------+--------+-------+--------+----------------------
     1 |   1395 |   1401 |     0 | (0,1)  | \x010000000b77616e67
(1 row)

mydb=*# insert into t1 values(2, 'aaaa');
INSERT 0 1
mydb=*# select tableoid, ctid, xmin, xmax, cmin, cmax, * from t1;
 tableoid | ctid  | xmin | xmax | cmin | cmax | id | col2
----------+-------+------+------+------+------+----+------
    21377 | (0,2) | 1401 |    0 |    1 |    1 |  2 | aaaa
(1 row)

mydb=*#  SELECT lp as tuple, t_xmin, t_xmax, t_field3 as t_cid, t_ctid, t_data
mydb-*# FROM heap_page_items(get_raw_page('t1', 0));
 tuple | t_xmin | t_xmax | t_cid | t_ctid |        t_data
-------+--------+--------+-------+--------+----------------------
     1 |   1395 |   1401 |     0 | (0,1)  | \x010000000b77616e67
     2 |   1401 |      0 |     1 | (0,2)  | \x020000000b61616161
(2 rows)

mydb=*# update t1 set col2='bbbb';
UPDATE 1
mydb=*# select tableoid, ctid, xmin, xmax, cmin, cmax, * from t1;
 tableoid | ctid  | xmin | xmax | cmin | cmax | id | col2
----------+-------+------+------+------+------+----+------
    21377 | (0,3) | 1401 |    0 |    2 |    2 |  2 | bbbb
(1 row)

mydb=*#  SELECT l

http://www.niftyadmin.cn/n/5469334.html

相关文章

基于springboot+vue的企业校园招聘面试管理系统【超级管理员、平台企业、学校、学生、HR】

招聘系统将为招聘者和求职者构建一个功能齐全、方便快捷的招聘平台&#xff0c;减少双方投入招聘活动的成本&#xff0c;为招聘求职双方带来便利&#xff0c;系统将实现如下目标&#xff1a; (1)针对系统内的不同角色&#xff0c;系统能够赋予其不同的操作权限。招聘者和求职者…

44.网络游戏逆向分析与漏洞攻防-角色管理功能通信分析-角色创建服务器反馈数据包分析

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 如果看不懂、不知道现在做的什么&#xff0c;那就跟着做完看效果 现在的代码都是依据数据包来写的&#xff0c;如果看不懂代码&#xff0c;就说明没看懂数据包…

Rust所有权和Move关键字使用和含义讲解,以及Arc和Mutex使用

Rust 所有权规则 一个值只能被一个变量所拥有&#xff0c;这个变量被称为所有者。 一个值同一时刻只能有一个所有者&#xff0c;也就是说不能有两个变量拥有相同的值。所以对应变量赋值、参数传递、函数返回等行为&#xff0c;旧的所有者会把值的所有权转移给新的所有者&#…

C++从入门到精通——入门知识

1. C关键字(C98) C总计63个关键字&#xff0c;C语言32个关键字 2. 命名空间 在C/C中&#xff0c;变量、函数和后面要学到的类都是大量存在的&#xff0c;这些变量、函数和类的名称都将存在于全局作用域中&#xff0c;可能会导致很多冲突。使用命名空间的目的就是对标识符的名…

产品推荐 | 基于VIRTEX UltraScale+系列的 FACE-VU3P-B高性能FPGA开发平台

01、产品概述 FACE-VU3P-B高性能FPGA开发平台是FACE系列的新产品。FACE-VU3P-B搭载有16nm工艺的VIRTEX UltraScale系列主器件XCVU3P。该主器件具有丰富的FPGA可编程逻辑资源&#xff0c;其资源量高于常用的V7-690器件&#xff0c;并且其性能远远高于V7-690器件。 平台板载有丰…

java Web 健身管理系统idea开发mysql数据库LayUI框架java编程计算机网页源码maven项目

一、源码特点 java Web健身管理系统是一套完善的信息管理系统&#xff0c;结合java 开发技术和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 前段主要技术 layUI bootst…

水泥5G智能制造工厂数字孪生可视化平台,推进水泥行业数字化转型

水泥5G智能制造工厂数字孪生可视化平台&#xff0c;推进水泥行业数字化转型。水泥5G智能制造工厂数字孪生可视化平台&#xff0c;是水泥行业数字化转型的关键推手。数字孪生平台运用先进的信息技术和数字化手段&#xff0c;实现水泥生产过程的数字化模拟、可视化监控和智能化管…

基于springboot的粮仓管理系统

文章目录 项目介绍主要功能截图&#xff1a;部分代码展示设计总结项目获取方式 &#x1f345; 作者主页&#xff1a;超级无敌暴龙战士塔塔开 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题库【关注我&#xff0c;都给你】 &…