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
表膨胀解决方法
新引入的问题
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
如何安装插件