查看原文
其他

第5期吐槽:经常OOM?吃内存元凶找到了:元数据缓存居然不能共享

digoal PostgreSQL码农集散地 2024-07-08

文中参考文档点击阅读原文打开, 同时推荐2个学习环境: 

1、懒人Docker镜像, 已打包200+插件:《最好的PostgreSQL学习镜像

2、有web浏览器就能用的云起实验室: 《免费体验PolarDB开源数据库

3、PolarDB开源数据库内核、最佳实践等学习图谱:  https://www.aliyun.com/database/openpolardb/activity 

关注公众号, 持续发布PostgreSQL、PolarDB、DuckDB等相关文章. 

第5期吐槽:老是OOM?吃内存元凶找到了!元数据缓存居然不共享

1、产品的问题点

  • meta cache (rel/catalog cache), plan cache是每个会话私有的内存.

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

  • 正常的SQL执行过程包括sql parse, rewrite, plan, exec等几个过程, parse, rewrite, plan都比较耗费cpu, 在OLTP的短平快场景, 使用prepared statement可以避免每次调用都需要parse,rewrite,plan, 使用plan cache直接进入exec阶段(特定情况下的custom plan除外).

  • 同时为了处理sql parse, rewrite, plan等, 数据库还需要一些meta cache, 例如访问过的表结构, 索引, 视图等定义.

  • plan cache和meta cache都是会话进程私有的.

  • PG 为每个会话分配一个backend process.

3、这个问题将影响哪些行业以及业务场景

  • SaaS行业

  • 分区超多的, 而且使用长连接和绑定变量

  • 微服务

4、会导致什么问题?

  • SaaS行业, 每个B端用户一套schema, 表超级多, 一个会话在整个生命周期内可能访问很多的数据库对象, 产生很多的plan cache、relcache, 单个会话对应的backend process占用大量内存. 进程多的话会导致内存消耗巨大, 导致OOM.

  • 分区超多的, 而且使用长连接和绑定变量. 频繁更新的C端业务系统通常有这个特性, 例如共享单车, 单车数量多, 用户多, 需要通过分区提高垃圾回收和freeze的效率. 导致的问题同上.

  • 微服务, 服务超级多, 导致与数据库的连接过多. 进而导致以上类似问题.

5、业务上应该如何避免这个坑

  • 控制每个会话的生命周期, 从而避免长时间touch过多的relation, 导致内存爆增.

  • 控制总连接数, 从而降低所有会话导致的整体内存使用.

  • 使用高版本PG(大版本在逐渐优化)或pg_pathman, 避免即使只访问某个分区, 在plan过程依旧需要touch所有分区表.

  • 使用pgbouncer连接池, 控制总连接数.

6、业务上避免这个坑牺牲了什么, 会引入什么新的问题

  • 增加了复杂度, 很多初次使用PG的小伙伴不知道.

  • 微服务很多的时候, 每个微服务至上的1个连接吧, 所以控制总连接数无解.

  • 使用pgbouncer控制总连接的话必须使用statement或transaction level, 这样的话就不能使用prepared statement, 因为下次发起exec时可能已经不是之前那个backend process了.

7、数据库未来产品迭代如何修复这个坑

  • 内置线程池

  • global cache (rel catalog caches, plan)

    • pg_backend_memory_contexts 查看内存上下文

文章中的参考文档请点击阅读原文获得. 


欢迎关注我的github (https://github.com/digoal/blog) , 学习数据库不迷路.  

近期正在写公开课材料, 未来将通过视频号推出, 欢迎关注视频号:


继续滑动看下一个
向上滑动看下一个

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存