大批量单表导入数据引发性能故障

现象:服务器卡死,但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.缓冲池

处理过程:

缓冲管理器收到请求–》缓冲区标签–》找到对应数据页面

缓冲区标签:

/image//image-20220328112859993

读操作:

写操作:

什么是脏页?

/image//image-20220328202304517

/image//image-20220328202755772

缓冲区管理器由那几个层组成

/image//image-20220328202932528

/image//image-20220328204015707

/image//image-20220328204051183

/image//image-20220328204455837

/image//image-20220328204504145

/image//image-20220328204521001

什么是自旋锁,自旋锁的优点不足?

buffer describe layer 会用到那些锁,作用是什么?

/image//image-20220328205205607

/image//image-20220328210508882

锁:解决并发的问题

缓冲管理器中的五种锁:

什么时候会获取独占模式的content_lock

/image//image-20220328205901912

buffermappingLock128个分区(默认)

/image//image-20220328132403203

IO进行锁,发生时间

/image//image-20220328210333934

描述将页面从存储加载到空槽的流程?

/image//image-20220328211042611

/image//image-20220328212958015

什么时候pg会使用环形缓冲区

/image//image-20220328213902552

什么是仅索引扫描

/image//image-20220328232438274

HOT的作用

数据库行数据更新时,索引也需要进行维护,如果是高并发的情况下,索引维护的代价 很大,可能造成索引分裂。Pg为了避免这个问题,采用了HOT(堆内元组技术)解决这 个问题

/image//image-20220328232627190

/image//image-20220328232635225

/image//image-20220328232645887

查询:共享锁 插入:独占锁

copy协议与事务

Copy 子协议对应三种模式:

copy-in:导入数据,对应命令 COPY FROM STDIN

copy-out:导出数据,对应命令 COPY TO STDOUT

copy-both:用于 walsender,在主备间批量传输数据

/image//image-20220329111721950

/image//image-20220329112025307

/image//image-20220329112055975

vacuum 原理解析

不同数据库之间历史版本怎么放的?

/image//image-20220329141037347

vacuum作用,清理分类?

/image//image-20220329142139021

1.清理死元组

2.freeze 冻结(我比谁都小,我对所用人可见的)

3.analyze更新统计信息

理解什么是FSM,什么时候生成的,有什么作用

FSM(Free Space Map),即空闲空间管理。

/image//image-20220330110433077

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%,设置阈值门槛为了避免频繁清理小表,针对大表可以调小比例因子,或者放弃比例因子调大阈值

/image//image-20220330150051165

理想方案:

据各个表的delete和update频繁程度以及表的数据量单独为每个表设置阈值:

ALTER TABLE test SET (autovacuum_vacuum_threshold = 100);

/image//image-20220330150802564

计算autovacuum计算

/image//image-20220330174908192

autovacuum清理过程

清理过程相当简单,它从数据文件中读取页面(默认8kB数据块),并检查它是否需要清理.如果没有死元组,页面就会被丢弃而不做任何更改.否则它被清理 (死元组被删除),被标记为"脏"并最终写出来。

postgresql并发控制

/image//image-20220330203913767

事务标识 txid,

查看当前txid

select txid_current();

/image//image-20220330204411958

元组结构由哪几部分组成

headtupleHeaderdata:堆元组头数据

/image//image-20220330204444264

Commit Log的作用

PostgreSQL 在Commit Log 中保存事务的状态。Commit Log,通常称为clog,分配给共享内存,并在整个事务处理过程中使用。

PostgreSQL 定义了四种事务状态

/image//image-20220330205007116

/image//image-20220330205612781

理解事务是否活跃

/image//image-20220330205727542

freeze原理

/image//image-20220330210059905

表空间空闲率

/image//image-20220330210231473

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’);

/image//image-20220330210240765

/image//image-20220330224151535

/image//image-20220330224308898

/image//image-20220330210319228

/image//image-20220330224404182

/image//image-20220330224435288

/image//image-20220330224509431

/image//image-20220330210330360

/image//image-20220330224611291

Foreign Data Wrappers(外部数据包装)

FDW原理

/image//image-20220331224905393

/image//image-20220331225229197

/image//image-20220331225245174

/image//image-20220331225304947

EXPLAN查看

/image//image-20220401144530554

/image//image-20220401144605868

解决索引失效的问题

/image//image-20220401144658541

/image//image-20220401144712464

索引知识

btree

/image//image-20220401152126652

hash

/image//image-20220401152252758 gin /image//image-20220401152457032

gist

/image//image-20220401152627287

sp-gist

/image//image-20220401152644285

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