
什么时候进去 Linux 数据库服务器意外终止,需要确定原因。可能存在多种原因。例如: 信号发生器 — 由于后端服务器中的错误而失败。 但这种情况很少见。 大多数情况下,您只是耗尽了磁盘空间或内存。 如果磁盘空间不足,只有一种方法:释放空间并重新启动数据库。
内存不足杀手
什么时候 伺服器 或者进程内存不足, Linux 内存溢出杀手(Out-Of-Memory Killer)提供两种解决方案:导致整个系统崩溃,或者终止占用大量内存的进程(应用程序)。当然,终止进程以避免操作系统崩溃是更好的选择。简而言之,内存溢出杀手是一个会终止应用程序以防止内核崩溃的进程。它牺牲应用程序来维持操作系统的运行。我们首先讨论一下内存溢出的工作原理以及如何控制它,然后再看看内存溢出杀手是如何决定终止哪些应用程序的。
其中一项主要任务 Linux — 当进程请求内存时才为其分配内存。通常情况下,进程或应用程序会向操作系统请求内存,但并不会完全使用。如果操作系统为所有请求内存但并不打算使用的进程分配内存,系统很快就会耗尽内存,最终导致系统崩溃。为了防止这种情况发生,操作系统会为进程预留内存,但实际上并不分配。只有当进程真正需要使用内存时,操作系统才会进行分配。有时操作系统没有可用内存,但它会为进程分配内存,并在进程需要时,如果内存可用,操作系统才会进行分配。缺点是,有时操作系统会预留内存,但当需要时却没有可用内存,从而导致系统崩溃。OOM(内存溢出)机制在这种情况下起着关键作用,它会终止进程以防止内核崩溃。当 PostgreSQL 进程被强制终止时,日志中会出现以下消息:
Out of Memory: Killed process 12345 (postgres).如果系统内存不足且无法释放,则调用该函数 out_of_memory。 在这个阶段,她只剩下一件事要做——完成一个或多个流程。 OOM-killer 应该立即终止进程还是可以等待? 显然,当out_of_memory被调用时,是由于等待I/O操作或分页到磁盘。 因此,OOM Killer 必须首先执行检查,并根据检查结果决定需要终止该进程。 如果以下所有检查都是肯定的,OOM 将终止该过程。
工艺选择
当内存耗尽时,调用该函数 out_of_memory()。 它有一个功能 select_bad_process(),它接收来自函数的评估 badness()。 “最差”的流程将成为目标。 功能 badness() 根据一定的规则选择进程。
- 内核本身需要一些最小内存。
- 您需要释放大量内存。
- 无需终止使用少量内存的进程。
- 需要完成最少的流程。
- 复杂的算法增加了用户自己想要完成的那些过程的完成机会。
完成所有这些检查后,OOM 检查分数 (oom_score)。 OOM 分配 oom_score 每个进程,然后将该值乘以内存量。 具有较大值的进程更有可能成为 OOM Killer 的受害者。 与 root 用户关联的进程得分较低,并且不太可能被强制终止。
postgres=# SELECT pg_backend_pid();
pg_backend_pid
----------------
3813
(1 row)Postgres 进程 ID 为 3813,因此在另一个 shell 中可以使用此内核参数获取分数 oom_score:
vagrant@vagrant:~$ sudo cat /proc/3813/oom_score
2如果您根本不希望 OOM-Killer 终止进程,还有另一个内核选项: oom_score_adj。 添加较大的负值可减少完成您重视的流程的机会。
sudo echo -100 > /proc/3813/oom_score_adj设置一个值 oom_score_adj,在服务块中设置 OOMScoreAdjust:
[Service]
OOMScoreAdjust=-1000或者使用 oomprotect 在一个团队中 rcctl.
rcctl set <i>servicename</i> oomprotect -1000强制终止进程
当一个或多个进程已被选择时,OOM-Killer 会调用该函数 oom_kill_task()。 该函数向进程发送终止信号。 如果内存不足 oom_kill() 调用此函数向进程发送 SIGKILL 信号。 一条消息被写入内核日志。
Out of Memory: Killed process [pid] [name].如何控制 OOM-Killer
В Linux 您可以启用或禁用 OOM-Killer(尽管不建议禁用)。要启用或禁用它,请使用以下参数。 vm.oom-kill。 要在运行时启用 OOM-Killer,请运行命令 sysctl.
sudo -s sysctl -w vm.oom-kill = 1要禁用 OOM-Killer,请在同一命令中指定值 0:
sudo -s sysctl -w vm.oom-kill = 0该命令的结果不会永久保存,只会保存到第一次重新启动之前。 如果您需要更多持久性,请将此行添加到文件中 /etc/sysctl.conf:
echo vm.oom-kill = 1 >>/etc/sysctl.conf启用和禁用的另一种方法是写入变量 panic_on_oom。 该值始终可以签入 /proc.
$ cat /proc/sys/vm/panic_on_oom
0如果将该值设置为0,那么当内存耗尽时,不会出现内核恐慌。
$ echo 0 > /proc/sys/vm/panic_on_oom如果将该值设置为1,那么当内存耗尽时,将会发生内核恐慌。
echo 1 > /proc/sys/vm/panic_on_oom正如我们前面提到的,OOM-Killer 可以开启和关闭。 Linux 可能会为进程预留比可用内存更多的内存,但实际上不会分配这些内存,这种行为由内核参数控制。 Linux该变量是造成这种情况的原因。 vm.overcommit_memory.
您可以为其指定以下值:
0: 内核本身会决定是否预留过多内存。这在大多数版本中是默认值。 Linux.
1: 内核总是会保留额外的内存。 这是有风险的,因为内存可能会耗尽,因为很可能有一天进程会需要它。
2: 内核不会保留比参数中指定的更多的内存 overcommit_ratio.
使用此参数,您可以指定允许过度保留的内存百分比。 如果没有空间,则不会分配内存,并且保留将被拒绝。 这是为 PostgreSQL 推荐的最安全的选项。 OOM-Killer 受到另一个因素的影响——交换能力,该能力由变量控制 cat /proc/sys/vm/swappiness。 这些值告诉内核如何处理分页。 该值越高,OOM 终止进程的可能性越小,但由于 I/O 操作,它确实会对数据库产生负面影响。 反之亦然 - 值越低,OOM-Killer 干预的可能性越高,但数据库性能也越高。 默认值为 60,但如果整个数据库都适合内存,则最好将该值设置为 1。
结果
不要让 OOM-Killer 中的“杀手”吓到您。 在这种情况下,杀手将成为你系统的救星。 它“杀死”最糟糕的进程并避免系统崩溃。 为了避免使用 OOM-Killer 来终止 PostgreSQL,请设置为 vm.overcommit_memory 值 2。这并不能保证 OOM-Killer 不必干预,但会降低强制 PostgreSQL 进程终止的可能性。
来源: habr.com
