大批量单表导入数据引发性能故障
现象:服务器卡死,但cpu利用率不高,free查看内存耗尽 判断是否有大量数据导入操作,有先删除索引,在进行数据导入
pg_double_cache
读取数据块的时候会占用2份内存。缓存,就是内存会在os的page cache和数据库的buffer库里面会体现出来。存在内存浪费
技术原理
pg写操作用了buffer IO 的接口,到os层会产生缓存,最后由io子系统写入到块设备里面去,读操作类似
影响行业或导致问题
所有行业,内存浪费 os的buffer IO,调度配置不好的话,对导致大量IO,IO hang,导致checkpoint,和别的的读数据的响应时间
始终要过一次层os cache
解决方法
好处 1.会在os层合并之后在写入,减少总的io次数 2.数据库在重启的时候可以缓冲一下,在发起读请求的时候其实是从os层面cache读出来的,(业务繁忙的时候,挂了,重启的场景) 3.刷盘,checkpoint
避免 无解。配置较大的shared buffer
shared_buffer 设置为物理内存的25%,服务器的内存为8G,故将此选项设置为1G: shared_buffers = 2048MB
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参数
log_statements
有效值none(off),ddl,mod,all ddl记录数据定义语句,create,alter,drop mod:所有ddl以及数据修改语句 查看 show log_statement; 修改会话级别 set log_statement = none;
大批量单表导入数据引发性能故障
现象:服务器卡死,但cpu利用率不高,free查看内存耗尽 判断是否有大量数据导入操作,有先删除索引,在进行数据导入
pg_double_cache
深度解析buffer manager、index-only
什么是脏页?
缓冲管理器结构?1.。2.。3.。干嘛用的
作用:管理共享内存和持久存储之间的数据传输
1.缓冲表
2.缓冲区描述符
3.缓冲池
处理过程:
缓冲管理器收到请求–》缓冲区标签–》找到对应数据页面
缓冲区标签:
读操作:
写操作:
什么是脏页?
缓冲区管理器由那几个层组成
什么是自旋锁,自旋锁的优点不足?
buffer describe layer 会用到那些锁,作用是什么?
锁:解决并发的问题
缓冲管理器中的五种锁:
什么时候会获取独占模式的content_lock
buffermappingLock128个分区(默认)
IO进行锁,发生时间
描述将页面从存储加载到空槽的流程?
什么时候pg会使用环形缓冲区
什么是仅索引扫描
HOT的作用
数据库行数据更新时,索引也需要进行维护,如果是高并发的情况下,索引维护的代价 很大,可能造成索引分裂。Pg为了避免这个问题,采用了HOT(堆内元组技术)解决这 个问题
查询:共享锁 插入:独占锁
copy协议与事务
Copy 子协议对应三种模式:
copy-in:导入数据,对应命令 COPY FROM STDIN
copy-out:导出数据,对应命令 COPY TO STDOUT
copy-both:用于 walsender,在主备间批量传输数据
vacuum 原理解析
不同数据库之间历史版本怎么放的?
vacuum作用,清理分类?
1.清理死元组
2.freeze 冻结(我比谁都小,我对所用人可见的)
3.analyze更新统计信息
理解什么是FSM,什么时候生成的,有什么作用
FSM(Free Space Map),即空闲空间管理。
https://blog.csdn.net/weixin_39540651/article/details/100933665
什么 时候会触发autovacuum
每当死亡元组(dead tuple)超过以下公式时,就会触发自动清理
autovacuum_vacuum_threshold(门槛) + pg_class.reltuples (表上记录数)*autovacuum_vacuum_scale_factor(比例因子)
死亡元组数可以认为是pg_stat_all_tables中n_dead_tup的值
门槛默认为50,比例因子默认为0.2,就是20%,设置阈值门槛为了避免频繁清理小表,针对大表可以调小比例因子,或者放弃比例因子调大阈值
理想方案:
据各个表的delete和update频繁程度以及表的数据量单独为每个表设置阈值:
ALTER TABLE test SET (autovacuum_vacuum_threshold = 100);
计算autovacuum计算
autovacuum清理过程
清理过程相当简单,它从数据文件中读取页面(默认8kB数据块),并检查它是否需要清理.如果没有死元组,页面就会被丢弃而不做任何更改.否则它被清理 (死元组被删除),被标记为"脏"并最终写出来。
postgresql并发控制
事务标识 txid,
查看当前txid
select txid_current();
元组结构由哪几部分组成
headtupleHeaderdata:堆元组头数据
Commit Log的作用
PostgreSQL 在Commit Log 中保存事务的状态。Commit Log,通常称为clog,分配给共享内存,并在整个事务处理过程中使用。
PostgreSQL 定义了四种事务状态
理解事务是否活跃
freeze原理
表空间空闲率
SELECT count(*) as “number of pages”,pg_size_pretty(cast(avg(avail) as bigint)) as “Av. freespace size”,round(100 * avg(avail)/8192 ,2) as “Av. freespace ratio” FROM pg_freespace(’test’);
SELECT *, round(100 * avail/8192 ,2) as “freespace ratio” FROM pg_freespace(’test’);
Foreign Data Wrappers(外部数据包装)
FDW原理
EXPLAN查看
解决索引失效的问题
索引知识
btree
hash
gin
gist
sp-gist
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
如何安装插件