天天看点

如何度量Kernel Resources for PostgreSQL

对于操作系统来说,数据库算是比较大型的应用,往往需要耗费大量的系统资源,特别是在内部进程间通信这块的资源。

操作系统默认的配置可能无法满足数据库对资源使用的需求。

那么应该如何根据数据库的需要,设置操作系统相关资源参数呢?

在讲资源分配前,大家可以参考阅读一下

<a href="https://www.postgresql.org/docs/9.5/static/kernel-resources.html#sysvipc">https://www.postgresql.org/docs/9.5/static/kernel-resources.html#sysvipc</a>

<a href="https://www.postgresql.org/docs/9.5/static/runtime-config-resource.html#runtime-config-resource-memory">https://www.postgresql.org/docs/9.5/static/runtime-config-resource.html#runtime-config-resource-memory</a>

kernel-doc-xxx/documentation/sysctl/kernel.txt

<a href="https://en.wikipedia.org/wiki/unix_system_v">https://en.wikipedia.org/wiki/unix_system_v</a>

这一篇主要讲的是进程间通信

<a href="https://docs.oracle.com/cd/e19455-01/806-4750/6jdqdflta/index.html">https://docs.oracle.com/cd/e19455-01/806-4750/6jdqdflta/index.html</a>

关于postgresql的共享内存管理,早期的 postgresql 版本共享内存分配只支持sysv的方式,数据库启动时,需要分配一块共享内存段,这个需求主要与配置多大的shared_buffers 有关。

社区在9.3的版本做了一个变动,使用mmap分配共享内存,大幅降低了系统对system v共享内存的需求量。

<a href="https://www.postgresql.org/docs/9.3/static/release-9-3.html">https://www.postgresql.org/docs/9.3/static/release-9-3.html</a>

但是mmap并不好,会带来额外的io开销,所以postgresql 9.4开始,又做了一个变动,支持动态分配共享内存,主要是为多核并行计算做的铺垫,而且默认的共享内存分配的方法变成了posix(如果环境支持),同样不需要启动时分配大的共享内存段 。

<a href="https://www.postgresql.org/docs/9.4/static/release-9-4.html">https://www.postgresql.org/docs/9.4/static/release-9-4.html</a>

从9.4开始,共享内存分配方法通过参数 dynamic_shared_memory_type 控制。

不同的值,创建共享内存段的方法也不一样,例如posix使用shm_open,sysv使用shmget,mmap使用mmap。

正是由于创建共享内存段的方法不一样,所以需要配置的操作系统内核参数也不一样。

不同的共享内存分配方法,对操作系统的内核参数配置要求也不一样。

涉及的资源以及计算方法如下

| name | description | reasonable values |

| ---- | ---- | ---- |

| shmmax | 单个共享内存段最大允许多大 (bytes) | 见另一张表,或者直接设置为内存的80% |

| shmmin | 单个共享内存段最小允许多小 (bytes) | 1 |

| shmall | 整个系统允许分配多少共享内存,(所有共享内存段相加) (bytes or pages) | 需考虑其他需要分配共享内存的应用,确保大于所有应用的需求量,通常可以设置为实际内存大小 |

| shmseg | 每个进程允许分配多少个共享内存段 | only 1 segment is needed, but the default is much higher, 所以不需要设置 |

| shmmni | 整个系统允许分配多少个共享内存段 | 需要分配共享内存的进程数 * shmseg |

| semmni | 允许分配多少组信号量id (i.e., sets) | at least ceil((max_connections + autovacuum_max_workers + 5) / 16) ,postgresql每16个进程一组 |

| semmns | 允许分配多少个信号量 | ceil((max_connections + autovacuum_max_workers + 5) / 16) 17 plus room for other applications,每组信号量需要17字节,加上其他软件的需求。实际设置时设置为semmnisemmsl |

| semmsl | 每组允许开多少信号量 | at least 17 |

| semmap | number of entries in semaphore map | see text |

| semvmx | maximum value of semaphore | at least 1000 (the default is often 32767; do not change unless necessary) |

共享内存 sysv 管理 (适用于 &lt; 9.3 的版本)

<a href="https://www.postgresql.org/docs/9.2/static/kernel-resources.html">https://www.postgresql.org/docs/9.2/static/kernel-resources.html</a>

因此对于9.2以及更低版本的共享内存sysv管理的情况,shmmax的需求计算方法如下,将所有项相加。

usage

approximate shared memory bytes required (as of 8.3)

connections

(1800 + 270 max_locks_per_transaction) max_connections

autovacuum workers

(1800 + 270 max_locks_per_transaction) autovacuum_max_workers

prepared transactions

(770 + 270 max_locks_per_transaction) max_prepared_transactions

shared disk buffers

(block_size + 208) * shared_buffers

wal buffers

(wal_block_size + 8) * wal_buffers

fixed space requirements

770 kb

共享内存 sysv 管理 (适用于 &gt;= 9.3 的版本)

对于9.3以及更高版本的postgresql, 即使使用sysv,也不需要这么多共享内存。后面会有实测。

通常需要4kb左右。

共享内存 posix, mmap, none 管理

一个postgresql集群只需要56字节(实测)的共享内存段大小

小结

9.3 以下版本,设置这3个内核参数

(9.3 以及以上版本,需要的shmmax没那么大,所以也可以使用以上设置。 )

如果一台服务器中要启动多个postgresql集群,则每个集群都需要

shmmin和shmseg不需要设置,从shmget的开发者手册也可以得到证实

系统页大小(未使用huge page时)

man shmget

信号量的需求,和数据库版本无关,计算方法如下。

需要多少组

semmni &gt;= (max_connections + max_worker_processes + autovacuum_max_workers + 5) / 16

需要多少信号量

semmns &gt;= ((max_connections + max_worker_processes + autovacuum_max_workers + 5) / 16) * 17 + 其他程序的需求

每组需要多少信号量

semmsl &gt;= 17

对应系统内核配置举例

含义分别为

如何查看当前系统设置的sysv资源限制

如何查看已使用的sysv资源

shmmax与信号量实测

共享内存管理方法 posix, mmap, none 实测 shmmax 需求 如下

启动数据库, 查看ipc

共享内存管理方法 sysv 实测 shmmax 需求 如下

如果设置低于数据库的需求,会报错

报错

把shm加到到20gb,

9.5的版本,启动时实际需要的内存并不多,如果你在9.2或者更低版本测试,那会需要很多

postgresql 9.2 shared_buffer=16gb , 启动时需要申请大量的内存.

ulimit 设置主要是限制进程级别对系统资源的使用。

配置文件举例

/etc/security/limits.conf

查看进程设置

# cat /proc/$pid/limits

查看当前用户的limit配置

postgresql 推荐设置

core dump 相关内核设置

postgresql 的守护进程是postgres,如果它挂了,数据库就挂了,其他进程挂了它会负责crash recovery,自动重启数据库(默认设置了 restart_after_crash = on )

所以如果要防止系统oom时杀掉postgres主进程,需要在启动数据库前,使用root用户设置self脚本进程的oom_score_adj,然后启动数据库。

例子

man shm_open, shmget, mmap, semctl, sem_overview

本文主要帮助大家理解postgresql数据库对操作系统资源的需求,以及计算方法。

如果用户需要在一个系统中运行多个数据库集群,则需要将所有集群的需求加起来。

postgresql 9.2以及以前的版本,在数据库启动时对sysv共享内存段的需求很大,所以要设得比较大,需要用户注意。

祝大家玩得开心,欢迎随时来 阿里云促膝长谈业务需求 ,恭候光临。

阿里云的小伙伴们加油,努力 做好内核与服务,打造最贴地气的云数据库 。