postgresql中mvcc表膨胀问题

postgresql中mvcc表膨胀问题

POSTREGSQL

postgresql中mvcc表膨胀问题

pg中的mvcc 旧版本和新版本在同一个数据库的问题

行发生了修改就有新版本和旧版本,存在同样的数据文件里面,如果垃圾回收不及时,就会发生表膨胀

技术原理

存储旧版本:解决并发事务,方便查询旧的版本数据

影响范围,行业,业务

对于高频率的更新,插入,删除场景就会有问题

传感器,出租车位置,等更新多的场景,容易出问题,垃圾回收不及时,就会膨胀

什么时候回收不及时

看看有没有2pc

看看垃圾回收设置的内存是不是过小

垃圾回收工作进程太少了

磁盘性能

膨胀之后会有什么问题

1.存储空间不足

2.访问的时候io的范围会增加,本来访问一个数据块的现在需要访问2,3个数据块了

3.内存的消耗增加了,因为内存buffer要去缓存block

4.性能下降

解决:

设置参数 https://blog.csdn.net/weixin_34360651/article/details/90504302

表膨胀解决方法

https://ctypyb2002.blog.csdn.net/article/details/82774684?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.control

新引入的问题

1、需要io延时更低的硬盘

2、牺牲了长事务

3、需要增加监控项

有没有希望解决这个坑

基于专门的回归段的存储引擎

pg local memory

plan cachae

背后原理:

sql执行的几个阶段

​ 1解析:有没有语法错误,规整化

​ 2query的rewrit

前面

解析计划

执行

在会话里面是私有的

影响行业

1SaaS

2分区超多的场景,要使用长连接的场景

3微服务

使用local memory带来的问题

saas:提供软件服务,有一套独立的schema,服务1w家企业的话有可能有1w个schema,每个schema可能有上万的表或对象,就很多了

一个会话生命周期内访问很多表,数据库对象,就会产生很多的loacl cache就是local 的memory包括plan cache,占用的内存会越来越大,最后导致omm

分区超多,要使用长连接,

频繁更新c端的业务系统通常就有这些特性,比如共享单车数量多,用户多,通过分区提高freeze的效率,一个连接可能到

很多的分区,消耗的内存就很多

微服务

对业务灵活,对于数据库来将,每一个服务都要跟数据库产生连接

业务上如何避免这个坑

1、设置会话的连接生命周期,避免长时间使用过多的对象

2、控制总的连接数

3、避免访问分区过度,原始的即便访问分区,也要把所有的全部touch出来

4、创建一个中间连接池,控制总的连接数,pgbouncer(牺牲短频快)

会引入什么新的问题,产生什么样的牺牲

1.增加复杂度

2.微服务很多的时候控制总连接数

未来

1.内置线程池

2.local memory作成global memory

pg log_statement参数

读取数据块的时候会占用2份内存

缓存,就是内存会在os的page cache和数据库的buffer库里面会体现出来

存在内存浪费

技术原理

pg写操作用了buffer IO 的接口,到os层会产生缓存,最后由io子系统写入到块设备里面去

读操作类似

影响行业导致问题

所有

内存浪费

os的buffer IO,调度配置不好的话,对导致大量IO,IO hang,导致checkpoin,和别的的读数据的响应时间

始终要过一次层os cache

解决方法

好处

1.会在os层合并之后在写入,减少总的io次数

2.数据库在重启的时候可以缓冲一下,在发起读请求的时候其实是从os层面cache读出来的,(业务繁忙的时候,挂了,重启的场景)

3.刷盘,checkpoint

避免

无解

配置较大的shared buffer

shared_buffer

设置为物理内存的25%,服务器的内存为8G,故将此选项设置为1G:

shared_buffers = 2048MB

pg double cache

读取数据块的时候会占用2份内存

缓存,就是内存会在os的page cache和数据库的buffer库里面会体现出来

存在内存浪费

技术原理

pg写操作用了buffer IO 的接口,到os层会产生缓存,最后由io子系统写入到块设备里面去

读操作类似

影响行业导致问题

所有

内存浪费

os的buffer IO,调度配置不好的话,对导致大量IO,IO hang,导致checkpoin,和别的的读数据的响应时间

始终要过一次层os cache

解决方法

好处

1.会在os层合并之后在写入,减少总的io次数

2.数据库在重启的时候可以缓冲一下,在发起读请求的时候其实是从os层面cache读出来的,(业务繁忙的时候,挂了,重启的场景)

3.刷盘,checkpoint

避免

无解

配置较大的shared buffer

shared_buffer

设置为物理内存的25%,服务器的内存为8G,故将此选项设置为1G:

shared_buffers = 2048MB

postgresql中xid

32xid事务号

7个问题

1问题是什么

事务号unit无符号整型,可以存储40亿个value,最多40亿个事务号

只有循环使用

2问题点背后涉及的技术原理

每一行的头部信息里面都会存储这由哪个事务id存储的,或者写入的,删除的,

数据库通过这个事务号判断这个事务是过去发生的还是未来发生的

大于当前的事务号,就是未来的事务号,大于未来的事务,你就是不可见的

比如,你现在正在查询,查询结果还没出来,又有新的数据插入,这个新的xid插入的信息,对于你的就是未来的,不可见的

很快就耗尽,因此设置freeze xid,把圆切成两半,一半已经消耗了的,一半剩余还可以分配的,每20亿个xid都要移动

影响业务场景:

1、频繁更新插入,大批量更新会大量消耗事务号,会frozen,扫描全表产生大量IO

2、frozen很快的话导致剩余的可分配小于1千万的时候会告警,1百万强制数据库停库,只有执行单用户进去停库

3、大量的表的年龄增加,有可能所有的表在同一时间触发阈值进行frozen,导致风暴,因为所有的表都要去做全表扫描,

主库io性能暴增,产生大量wal日志,导致性能问题,同时从库的延时增加

业务上避免

1.pg内核的优化,不频繁更新的话扫描一次就搞定,对于已经frozen的page直接跳过

2.海量静态数据写入的时候,直接设置标记位,不需要froze

3.好硬盘

4.设置vacuum_sleep的间隙,降低IO

5.针对不同分区设置阈值,错开执行frozen

参考文章

https://blog.csdn.net/weixin_42474537/article/details/113010217

为了避坑有没有引入新的问题

1.管理成本,硬件成本增加

未来怎么修复

支持64位xid

end

如何安装插件

image-20220330223959328

http://www.bubuko.com/infodetail-910812.html