配置 Linux 内核选项来优化 PostgreSQL

配置 Linux 内核选项来优化 PostgreSQL 最佳 PostgreSQL 性能取决于正确定义的操作系统参数。 操作系统内核设置配置不当可能会导致数据库服务器性能不佳。 因此,必须根据数据库服务器及其工作负载来配置这些设置。 在这篇文章中,我们将讨论一些可能影响数据库服务器性能的重要 Linux 内核参数以及如何配置它们。

SHMMAX / SHMALL

SHM最大 是一个内核参数,用于确定 Linux 进程可以分配的单个共享内存段的最大大小。 在版本 9.2 之前,PostgreSQL 使用 System V (SysV),这需要 SHMMAX 设置。 9.2之后,PostgreSQL改用POSIX共享内存。 因此,现在需要更少的 System V 共享内存字节。

在9.3版本之前,SHMMAX是最重要的内核参数。 SHMMAX 值以字节为单位指定。

同样的, 上海商城 是另一个内核参数,用于确定
系统范围的共享内存页面量。 要查看当前的 SHMMAX、SHMALL 或 SHMMIN 值,请使用命令 电脑.

SHM* 详细信息 - Linux

$ ipcs -lm

------ Shared Memory Limits --------
max number of segments = 4096
max seg size (kbytes) = 1073741824
max total shared memory (kbytes) = 17179869184
min seg size (bytes) = 1

SHM* 详细信息 - MacOS X

$ ipcs -M
IPC status from  as of Thu Aug 16 22:20:35 PKT 2018
shminfo:
	shmmax: 16777216	(max shared memory segment size)
	shmmin:       1	(min shared memory segment size)
	shmmni:      32	(max number of shared memory identifiers)
	shmseg:       8	(max shared memory segments per process)
	shmall:    1024	(max amount of shared memory in pages)

PostgreSQL 使用 系统V IPC 分配共享内存。 该参数是最重要的内核参数之一。 每当您收到以下错误消息时,这意味着您使用的是较旧版本的 PostgreSQL,并且您的 SHMMAX 值非常低。 用户应根据自己打算使用的共享内存来调整和增加该值。

可能的配置错误

如果 SHMMAX 配置不正确,您在尝试使用以下命令初始化 PostgreSQL 集群时可能会收到错误消息 初始化数据库.

初始化数据库失败
DETAIL: Failed system call was shmget(key=1, size=2072576, 03600).

HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter. 
You can either reduce the request size or reconfigure the kernel with larger SHMMAX. To reduce the request size (currently 2072576 bytes),
reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.

If the request size is already small, it's possible that it is less than your kernel's SHMMIN parameter,
in which case raising the request size or reconfiguring SHMMIN is called for.

The PostgreSQL documentation contains more information about shared memory configuration. child process exited with exit code 1

同样,使用以下命令启动 PostgreSQL 服务器时可能会收到错误 pg_ctl.

pg_ctl 失败
DETAIL: Failed system call was shmget(key=5432001, size=14385152, 03600).

HINT: This error usually means that PostgreSQL's request for a shared memory segment exceeded your kernel's SHMMAX parameter.

You can either reduce the request size or reconfigure the kernel with larger SHMMAX.; To reduce the request size (currently 14385152 bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.

If the request size is already small, it's possible that it is less than your kernel's SHMMIN parameter,
in which case raising the request size or reconfiguring SHMMIN is called for.

The PostgreSQL documentation contains more information about shared memory configuration.

了解定义的差异

在 Linux 和 MacOS X 上定义 SHMMAX/SHMALL 参数略有不同:

  • Linux:kernel.shmmax、kernel.shmall
  • MacOS X:kern.sysv.shmmax、kern.sysv.shmall

团队 系统控制 可用于临时更改该值。 要设置常量值,请添加一个条目 /etc/sysctl.conf中。 详细信息如下。

更改 MacOS X 上的内核设置

# Get the value of SHMMAX
sudo sysctl kern.sysv.shmmax
kern.sysv.shmmax: 4096

# Get the value of SHMALL
sudo sysctl kern.sysv.shmall 
kern.sysv.shmall: 4096

# Set the value of SHMMAX
sudo sysctl -w kern.sysv.shmmax=16777216
kern.sysv.shmmax: 4096 -> 16777216

# Set the value of SHMALL 
sudo sysctl -w kern.sysv.shmall=16777216
kern.sysv.shmall: 4096 -> 16777216

在 Linux 上更改内核参数

# Get the value of SHMMAX
sudo sysctl kernel.shmmax
kernel.shmmax: 4096

# Get the value of SHMALL
sudo sysctl kernel.shmall
kernel.shmall: 4096

# Set the value of SHMMAX
sudo sysctl -w kernel.shmmax=16777216
kernel.shmmax: 4096 -> 16777216

# Set the value of SHMALL 
sudo sysctl -w kernel.shmall=16777216
kernel.shmall: 4096 -> 16777216

别忘了:要使更改永久生效,请将这些值添加到 /etc/sysctl.conf

大页面

Linux 默认使用 4 KB 内存页,BSD 使用 XNUMX KB 内存页。 超级页面,以及在 Windows 上 - 大页面。 页是分配给进程的一块 RAM。 根据内存需求,一个进程可以有多个页面。 进程需要的内存越多,分配的页面就越多。 操作系统为进程维护一个页面分配表。 页大小越小,表越大,在该页表中查找页所需的时间就越长。 因此,大页面允许使用大量内存,同时减少开销; 更少的页面浏览量、更少的页面错误、在更大的缓冲区上更快的读/写操作。 结果是性能得到提高。

PostgreSQL 仅支持 Linux 上的大页面。 默认情况下,Linux使用4KB内存页面,因此在内存操作过多的情况下,需要设置更大的页面。 使用 2 MB 至 1 GB 的大页面时,可以观察到性能提升。 大页面大小可以在启动时设置。 您可以使用以下命令轻松检查 Linux 机器上的大页面参数及其使用情况 猫 /proc/meminfo | grep -i 巨大.

获取有关大页面的信息(仅限 Linux)

Note: This is only for Linux, for other OS this operation is ignored$ cat /proc/meminfo | grep -i huge
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB

在此示例中,虽然大页大小设置为 2048 (2 MB),但大页总数设置为 0。这意味着大页被禁用。

用于确定大页面数量的脚本

这个简单的脚本返回所需数量的大页面。 当 PostgreSQL 运行时,在 Linux 服务器上运行该脚本。 确保环境变量 $PGDATA 指定PostgreSQL数据目录。

获取所需大页数

#!/bin/bash
pid=`head -1 $PGDATA/postmaster.pid`
echo "Pid:            $pid"
peak=`grep ^VmPeak /proc/$pid/status | awk '{ print $2 }'`
echo "VmPeak:            $peak kB"
hps=`grep ^Hugepagesize /proc/meminfo | awk '{ print $2 }'`
echo "Hugepagesize:   $hps kB"
hp=$((peak/hps))
echo Set Huge Pages:     $hp

脚本输出如下所示:

脚本输出

Pid:            12737
VmPeak:         180932 kB
Hugepagesize:   2048 kB
Set Huge Pages: 88

大页面的建议值为 88,因此您应该将其设置为 88。

安装大页面

sysctl -w vm.nr_hugepages=88

现在检查大页,您将看到没有使用大页(HugePages_Free = HugePages_Total)。

重新访问大页面(仅限 Linux)

$ cat /proc/meminfo | grep -i huge
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
HugePages_Total:      88
HugePages_Free:       88
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB

现在在 $PGDATA/postgresql.conf 中将huge_pages 参数设置为“on”并重新启动服务器。

再次,有关大页面的信息(仅限 Linux)

$ cat /proc/meminfo | grep -i huge
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
HugePages_Total:      88
HugePages_Free:       81
HugePages_Rsvd:       64
HugePages_Surp:        0
Hugepagesize:       2048 kB

现在您可以看到很少有大页面被使用。 现在让我们尝试向数据库添加一些数据。

一些数据库操作回收大页

postgres=# CREATE TABLE foo(a INTEGER);
CREATE TABLE
postgres=# INSERT INTO foo VALUES(generate_Series(1,10000000));
INSERT 0 10000000

让我们看看现在是否使用了比以前更多的大页面。

有关大页面的更多信息(仅限 Linux)

$ cat /proc/meminfo | grep -i huge
AnonHugePages:         0 kB
ShmemHugePages:        0 kB
HugePages_Total:      88
HugePages_Free:       18
HugePages_Rsvd:        1
HugePages_Surp:        0
Hugepagesize:       2048 kB

现在您可以看到大部分大页面正在被使用。

注意:这里使用的HugePages的估计值非常低,这对于运行产品环境的机器来说不是正常值。 请估计您的系统所需的页面数量,并根据负载和资源进行相应设置。

虚拟机交换性

虚拟机交换性 是另一个可以影响数据库性能的内核参数。 此选项用于控制 Linux 中的交换行为(将页面交换进和交换出内存)。 值范围从 0 到 100。它确定将调出或调出多少内存。 零意味着没有交换,100意味着积极交换。

通过设置较低的值可以获得良好的性能。

在较新的内核上将此设置为 0 可能会导致 OOM Killer(Linux 的内存清理进程)终止该进程。 因此,如果您想最大程度地减少交换,请将其设置为 1 是安全的。 Linux 中的默认值为 60。较高的值会导致 MMU(内存管理单元)使用比 RAM 更多的交换空间,而较低的值会在内存中保留更多的数据/代码。

较低的值是提高 PostgreSQL 性能的好选择。

vm.overcommit_memory / vm.overcommit_ratio

应用程序获取内存并在不再需要时释放它。 但在某些情况下,应用程序获取过多内存并且不释放它。 这可能会导致 OOM 杀手。 以下是可能的参数值 虚拟机内存过量使用 每个都有一个描述:

  1. 启发式过量使用(默认); 基于内核的启发式
  2. 无论如何都允许过度使用
  3. 不要过度使用,不要超过过度使用比例。

链接: https://www.kernel.org/doc/Documentation/vm/overcommit-accounting

vm.overcommit_ratio — 可用于过载的 RAM 百分比。 在具有 50 GB RAM 的系统上,值 2% 最多可以分配 3 GB RAM。

vm.overcommit_memory 的值为 2 可以为 PostgreSQL 提供更好的性能。 该值可最大化服务器进程的 RAM 使用量,而不会产生被 OOM 杀手进程杀死的重大风险。 应用程序将能够重新加载,但仅限于超限范围内,这降低了 OOM 杀手终止进程的风险。 因此,值 2 比默认值 0 提供更好的性能。但是,可以通过确保超出范围的内存不过载来提高可靠性。 这消除了进程被 OOM 杀手杀死的风险。

在没有交换的系统上,可能会出现 vm.overcommit_memory 等于 2 的问题。

https://www.postgresql.org/docs/current/static/kernel-resources.html#LINUX-MEMORY-OVERCOMMIT

vm.dirty_background_ratio / vm.dirty_background_bytes

vm.dirty_background_ratio 是需要写入磁盘的脏页所占内存的百分比。 刷新到磁盘发生在后台。 该参数的取值范围为0~100; 然而,低于 5 的值可能无效,并且某些内核不支持它。 10 是大多数 Linux 系统上的默认值。 您可以通过更小的因素来提高写入密集型操作的性能,这意味着 Linux 将在后台刷新脏页。

您需要设置该值 vm.dirty_background_bytes 取决于您的驱动器的速度。

这两个参数没有“好的”值,因为两者都依赖于硬件。 但是,在大多数情况下,将 vm.dirty_background_ratio 设置为 5 并将 vm.dirty_background_bytes 设置为磁盘速度的 25% 可以将性能提高到约 25%。

vm.dirty_ratio/dirty_bytes

这与 vm.dirty_background_ratio/dirty_background_bytes,不同之处在于重置是在工作会话中执行的,从而阻止了应用程序。 因此 vm.dirty_ratio 应高于 vm.dirty_background_ratio。 这可以确保后台进程更早启动,从而尽可能避免阻塞应用程序。 您可以根据磁盘 I/O 负载调整这两个比率之间的差异。

您可以调整其他设置来提高性能,但改进很小,而且您不会看到太多好处。 我们必须记住,并非所有选项都适用于所有类型的应用程序。 当我们调整某些设置时,有些应用程序会运行得更好,而有些则不然。 您必须在针对预期工作负载和应用程序类型配置这些设置之间找到适当的平衡,并且在调整时还必须考虑操作系统行为。 配置内核参数并不像配置数据库参数那么容易;提出建议更困难。

来源: habr.com

添加评论