【DB吐槽大会】第5期 - PG local memory

背景


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 查看内存上下文
上一篇:【DB吐槽大会】第65期 - PG 没有内置进程池


下一篇:【DB吐槽大会】第12期 - 没有自动成本校准器