
Cuando el servidor de la base de datos se cierra inesperadamente en Linux, debe encontrar el motivo. Puede haber varias razones. Por ejemplo, SIGSEGV : bloqueo debido a un error en el servidor de fondo. Pero esto es una rareza. La mayoría de las veces, el espacio en disco o la memoria simplemente se agota. Si se agota el espacio en disco, una forma de hacerlo es liberar espacio y reiniciar la base de datos.
Asesino sin memoria
Cuando el servidor o proceso se queda sin memoria, Linux ofrece 2 soluciones: bloquear el sistema completo o finalizar el proceso (aplicación) que consume memoria. Es mejor, por supuesto, completar el proceso y salvar el sistema operativo de una terminación anormal. En pocas palabras, Out-Of-Memory Killer es el proceso que termina una aplicación para salvar el núcleo de un bloqueo. Sacrifica la aplicación para mantener el sistema operativo en ejecución. Primero analicemos cómo funciona OOM y cómo controlarlo, y luego veamos cómo OOM Killer decide qué aplicación finalizar.
Una de las principales tareas de Linux es asignar memoria a los procesos cuando lo soliciten. Por lo general, un proceso o una aplicación solicita memoria del sistema operativo, pero ellos mismos no la usan por completo. Si el sistema operativo emitirá memoria a todos los que la soliciten, pero no planee usarla, muy pronto la memoria terminará y el sistema fallará. Para evitar esto, el sistema operativo reserva memoria para el proceso, pero en realidad no lo emite. La memoria se asigna solo cuando el proceso realmente la va a usar. Sucede que el sistema operativo no tiene memoria libre, pero asigna memoria al proceso, y cuando el proceso lo necesita, el sistema operativo lo asigna si puede. La desventaja es que a veces el sistema operativo reserva memoria, pero en el momento adecuado no hay memoria libre y el sistema se bloquea. OOM juega un papel importante en este escenario y finaliza los procesos para evitar que el núcleo entre en pánico. Cuando el proceso PostgreSQL se termina por la fuerza, aparece un mensaje en el registro:
Out of Memory: Killed process 12345 (postgres).
Si hay poca memoria en el sistema y es imposible liberarla, se out_of_memory
función out_of_memory
. En esta etapa, solo le queda una cosa: completar uno o más procesos. ¿Debería OOM-killer terminar el proceso de inmediato o puedo esperar? Obviamente, cuando se llama a out_of_memory, esto se debe a la espera de una operación de E / S o cambio de página al disco. Por lo tanto, el asesino de OOM primero debe realizar verificaciones y, con base en ellas, decidir que el proceso debe completarse. Si todas las verificaciones a continuación dan un resultado positivo, OOM terminará el proceso.
Proceso de selección
Cuando se agota la memoria, se out_of_memory()
función out_of_memory()
. Tiene una función select_bad_process()
, que recibe una estimación de la función select_bad_process()
. La distribución del proceso más "malo". La función badness()
selecciona un proceso de acuerdo con ciertas reglas.
- El núcleo necesita algo de memoria mínima para sí mismo.
- Necesita liberar mucha memoria.
- No es necesario terminar los procesos que usan poca memoria.
- Necesita completar un mínimo de procesos.
- Algoritmos complejos que aumentan las posibilidades de finalización de aquellos procesos que el propio usuario desea completar.
Después de completar todas estas comprobaciones, OOM examina la calificación ( oom_score
). OOM asigna oom_score
cada proceso y luego multiplica este valor por la cantidad de memoria. Los procesos con valores más altos tienen más probabilidades de convertirse en víctimas de OOM Killer. Los procesos asociados con un usuario privilegiado tienen una calificación más baja y tienen menos probabilidades de forzar la terminación.
postgres=# SELECT pg_backend_pid(); pg_backend_pid ---------------- 3813 (1 row)
El identificador del proceso de Postgres es 3813, por lo que en otro shell puede obtener una estimación utilizando este oom_score
núcleo oom_score
:
vagrant@vagrant:~$ sudo cat /proc/3813/oom_score 2
Si no desea que OOM-Killer complete el proceso, existe otro parámetro del núcleo: oom_score_adj
. Agregue un gran valor negativo para reducir las posibilidades de completar el proceso que ama.
sudo echo -100 > /proc/3813/oom_score_adj
Para establecer el valor oom_score_adj
, establezca OOMScoreAdjust en el bloque de servicio:
[Service] OOMScoreAdjust=-1000
O use oomprotect
en el rcctl
.
rcctl set <i>servicename</i> oomprotect -1000
Terminación forzada del proceso
Cuando uno o más procesos ya están seleccionados, OOM-Killer llama a la función oom_kill_task()
. Esta función envía una señal de terminación al proceso. Si no hay suficiente memoria, oom_kill()
llama a esta función para enviar una señal SIGKILL al proceso. Se escribe un mensaje en el registro del kernel.
Out of Memory: Killed process [pid] [name].
Cómo controlar OOM-Killer
En Linux, puede habilitar o deshabilitar OOM-Killer (aunque no se recomienda este último). Para habilitar y deshabilitar, use la opción vm.oom-kill
. Para habilitar OOM-Killer en tiempo de ejecución, ejecute el comando sysctl
.
sudo -s sysctl -w vm.oom-kill = 1
Para deshabilitar OOM-Killer, especifique el valor 0 en el mismo comando:
sudo -s sysctl -w vm.oom-kill = 0
El resultado de este comando no se guardará para siempre, sino solo hasta el primer reinicio. Si necesita más persistencia, agregue esta línea al archivo /etc/sysctl.conf
:
echo vm.oom-kill = 1 >>/etc/sysctl.conf
Otra forma de habilitar y deshabilitar es escribir la variable panic_on_oom
. El valor siempre se puede verificar en /proc
.
$ cat /proc/sys/vm/panic_on_oom 0
Si establece el valor en 0, cuando la memoria se agote, el kernel panic no lo hará.
$ echo 0 > /proc/sys/vm/panic_on_oom
Si establece el valor en 1, cuando se agote la memoria, sucederá el pánico del kernel.
echo 1 > /proc/sys/vm/panic_on_oom
OOM-Killer no solo se puede encender y apagar. Ya hemos dicho que Linux puede reservar más memoria para los procesos que la que existe, pero no asignarla de hecho, y este comportamiento está controlado por el parámetro del kernel de Linux. La variable vm.overcommit_memory
es responsable de esto.
Puede especificar los siguientes valores para ello:
0: El núcleo mismo decide si reservar demasiada memoria. Este es el valor predeterminado en la mayoría de las versiones de Linux.
1: el núcleo siempre reservará memoria extra. Esto es arriesgado, porque la memoria puede terminar, porque, muy probablemente, algún día los procesos exigirán lo que se supone que es.
2: el kernel no reservará más memoria de la especificada en el parámetro overcommit_ratio
.
En este parámetro, especifica el porcentaje de memoria para el que se permite la redundancia. Si no hay espacio para ello, la memoria no está asignada, la reserva será denegada. Esta es la opción más segura recomendada para PostgreSQL. OOM-Killer se ve afectado por otro elemento: la función de intercambio, que está controlada por la variable cat /proc/sys/vm/swappiness
. Estos valores le dicen al núcleo cómo manejar la paginación. Cuanto mayor sea el valor, es menos probable que OOM termine el proceso, pero debido a E / S, esto afecta negativamente a la base de datos. Y viceversa: cuanto menor es el valor, mayor es la probabilidad de intervención OOM-Killer, pero el rendimiento de la base de datos también es mayor. El valor predeterminado es 60, pero si toda la base de datos cabe en la memoria, es mejor establecer el valor en 1.
Resumen
No te asustes con el asesino en OOM-Killer. En este caso, el asesino será el salvador de su sistema. "Mata" los peores procesos y salva al sistema de una terminación anormal. Para evitar tener que usar OOM-Killer para completar PostgreSQL, configure vm.overcommit_memory
en 2. Esto no garantiza que OOM-Killer no tenga que intervenir, pero reducirá la probabilidad de que finalice un proceso PostgreSQL forzado.