默认情况下,Linux 使用一种有争议的(用于数据库)内存扩展功能,称为Overcommit。PG 手册的管理内核资源部分介绍了它如何与 PostgreSQL 交互。
Overcommit 允许客户端预先分配超出服务器 RAM 的虚拟内存。它们只被固定在一个真正的分配上,这让应用程序拥有更平坦的内存模型,而无需处理虚拟内存编码。该模型还提高了交换的工作效率。
如果最近升级了 PostgreSQL 或增加了服务器的shared_buffers设置,可能会发现 Linux 的“已提交”部分现在列出了以前不明显的更大的内存块。让我们通过足够多的内容来解释相关的系统内存指标。
共享内存历史
在 PostgreSQL 9.2 之前的版本中,运行服务器所需的共享内存块被直接分配为 UNIX System V 共享内存。那个时代的文档给出了该块所需内存的估计。在9.2内核资源有其表17-2中“PostgreSQL的共享内存使用”。
从 PostgreSQL 9.3 开始,PostgreSQL 通常分配非常少量的 System V 共享内存,以及大量 POSIX (mmap) 共享内存,引用10.0 Kernel Resources。然后系统提交shared_buffers内存以固定它们并进行初始化。这就是为什么较新 Postgres 服务器的共享/承诺平衡看起来与旧版本非常不同的原因。由于此更改,内存使用公式编号在很大程度上已过时,无论如何,该表不可能在文档中很好地维护。这就是为什么在切换到新的mmap分配样式时降低了详细程度的原因。
PG10 示例
此示例使用 Ubuntu 18.04 附带的 PostgreSQL 10;您可以使用任何 Linux 发行版,尽管具有不同的服务控制脚本。从关闭服务器开始(更多关于下面的正确语法)并查看内存使用情况:
$ service postgresql stop
$ cat /proc/meminfo | grep Commit
CommitLimit: 10252072 kB
Committed_AS: 806928 kB
复制
在这个 16GB RAM 服务器上,这给 CommitLimit=10252072kB ~= 10GB。当前锁定,已提交 RAM Committed_AS=806928kB ~= 800MB。这是专用于核心 Linux 操作系统及其实用程序的内存。您可能会得出这样的结论:该操作系统的配置至少需要 1GB 才能运行,这是准确的。
在这台服务器上,正确启动数据库意味着我必须回到我的用户帐户才能使用sudo。您可以轻松地将这些权力赋予postgres Linux 帐户,这在我的测试系统上不是必需的。在此服务器上停止和启动数据库的正确systemd调用使用systemctl。以下是您可能需要使用的一些替代形式的启动行:
gsmith@hydra:~$ sudo systemctl start postgresql@10-main
postgres@hydra:~$ service postgresql start
postgres@hydra:~$ pg_ctlcluster 10 main start # Debian/Ubuntu, PG10
复制
确认刚刚重启的数据库:
postgres@hydra:~$ ps -eaf | grep postgres postgres 8022 1 0 06:40 ? 00:00:00 /usr/lib/postgresql/10/bin/postgres -D /var/lib/postgresql/10/main -c config_file=/etc/postgresql/10/main/postgresql.conf postgres 8024 8022 0 06:40 ? 00:00:00 postgres: 10/main: checkpointer process postgres 8025 8022 0 06:40 ? 00:00:00 postgres: 10/main: writer process postgres 8026 8022 0 06:40 ? 00:00:00 postgres: 10/main: wal writer process postgres 8027 8022 0 06:40 ? 00:00:00 postgres: 10/main: autovacuum launcher process postgres 8028 8022 0 06:40 ? 00:00:00 postgres: 10/main: stats collector process postgres 8029 8022 0 06:40 ? 00:00:00 postgres: 10/main: bgworker: logical replication launcher postgres@hydra:~$ date Sat May 1 06:42:45 EDT 2021
复制
并检查已提交内存的最大用户shared_buffers:
postgres@hydra:~$ psql -c "show shared_buffers"
shared_buffers
----------------
4GB
复制
现在让我们再看看内存:
postgres@hydra:~$ cat /proc/meminfo | grep Commit
CommitLimit: 10252072 kB
Committed_AS: 5115160 kB
复制
Committed_AS 跃升至 5115160 kB= 4.9GB。由于之前是 800MB,这意味着数据库服务器在启动时提交了一个新的 4308232kb= 4.1GB 。那是共享内存块,其中包括shared_buffers以及客户端和其他共享状态的一些开销。
挖掘去向
使用pmap实用程序时,您可以查看有关内存去向的更多信息。虽然大部分字节是shared_buffers,但大部分文本输出链接到各种共享库。这是一个 grep 命令,可以筛选出大部分琐事:
postgres@hydra:~$ pmap -x 8022 | egrep -v "anon|lib|ld|locale"
Address Kbytes RSS Dirty Mode Mapping
00005637cb721000 7012 3492 0 r-x-- postgres
00005637cb721000 0 0 0 r-x-- postgres
00005637cbffa000 136 136 136 r---- postgres
00005637cbffa000 0 0 0 r---- postgres
00005637cc01c000 52 52 52 rw--- postgres
00005637cc01c000 0 0 0 rw--- postgres
00007f919cb75000 4317408 108240 108240 rw-s- zero (deleted)
00007f919cb75000 0 0 0 rw-s- zero (deleted)
00007f92ae841000 8 4 4 rw-s- PostgreSQL.158420325
00007f92ae841000 0 0 0 rw-s- PostgreSQL.158420325
00007f92ae843000 4 4 4 rw-s- [ shmid=0x48000 ]
00007f92ae843000 0 0 0 rw-s- [ shmid=0x48000 ]
00007ffec9539000 132 32 32 rw--- [ stack ]
00007ffec9539000 0 0 0 rw--- [ stack ]
---------------- ------- ------- -------
total kB 4492416 124396 110252
复制
关键块显然是这个:
00007f919cb75000 4317408 108240 108240 rw-s- zero (deleted)
复制
这表明 4317408k 是包含 shared_buffers 的清零缓冲区空间,而 108240k 是使用旧的 SysV 驻留内存分配 (RSS) 确定的。该 RSS 块是 Postgres 需要运行的开销,类似于旧文档放入“共享内存使用”表中的内容。
大多数人发现使用top命令在热服务器上更容易跟踪此信息。对于 Postgres建议使用top -c,因为它将解码所有数据库进程正在执行的操作。此服务器的顶部输出显示了VIRT列中的大虚拟内存块:
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND 8025 postgres 20 0 4492412 36020 33992 S 0.0 0.2 0:00.15 postgres: 10/main: writer process 8026 postgres 20 0 4492412 21412 19388 S 0.0 0.1 0:00.42 postgres: 10/main: wal writer process 8028 postgres 20 0 175124 4396 2260 S 0.0 0.0 0:00.26 postgres: 10/main: stats collector process 8024 postgres 20 0 4493760 62308 59052 S 0.0 0.4 0:00.65 postgres: 10/main: checkpointer process 8029 postgres 20 0 4492724 4984 2840 S 0.0 0.0 0:00.00 postgres: 10/main: bgworker: logical replication launcher 8027 postgres 20 0 4492816 6800 4552 S 0.0 0.0 0:00.14 postgres: 10/main: autovacuum launcher process
复制
在现代 PostgreSQL 和 Linux 版本上处理共享内存与过去必须无休止地调整内核参数以运行数据库相比有了很大改进。
原文链接:https://blog.crunchydata.com/blog/postgresql-on-linux-counting-committed-memory