Amazon EC2, início de aborto do mysql porque falhou InnoDB: mmap (x bytes); errno 12


95

Tenho criado um micro servidor instância no EC2 com base no que eu li aqui

O servidor mysql falha frequentemente e pela terceira vez o servidor mysql desapareceu. Os logs mostram apenas

120423 09:13:38 mysqld_safe mysqld from pid file /var/run/mysqld/mysqld.pid ended
120423 09:14:27 mysqld_safe Starting mysqld daemon with databases from /var/lib/mysql
120423  9:14:27 [Note] Plugin 'FEDERATED' is disabled.
120423  9:14:27 InnoDB: The InnoDB memory heap is disabled
120423  9:14:27 InnoDB: Mutexes and rw_locks use GCC atomic builtins
120423  9:14:27 InnoDB: Compressed tables use zlib 1.2.3
120423  9:14:27 InnoDB: Using Linux native AIO
120423  9:14:27 InnoDB: Initializing buffer pool, size = 512.0M
InnoDB: mmap(549453824 bytes) failed; errno 12
120423  9:14:27 InnoDB: Completed initialization of buffer pool
120423  9:14:27 InnoDB: Fatal error: cannot allocate memory for the buffer pool
120423  9:14:27 [ERROR] Plugin 'InnoDB' init function returned error.
120423  9:14:27 [ERROR] Plugin 'InnoDB' registration as a STORAGE ENGINE failed.
120423  9:14:27 [ERROR] Unknown/unsupported storage engine: InnoDB
120423  9:14:27 [ERROR] Aborting

O que é realmente failed; errno 12? E como eu poderia dar mais espaço / memória ou o que fosse necessário para fazer isso corrigido.

Eu corrijo isso todas as vezes, reiniciando todo o sistema, excluindo todos os logs e reiniciando o servidor mysql. Mas eu sei que algo está errado com minha configuração.

Além disso, meu `my.cnf 'é como abaixo:

[mysqld]
# Settings user and group are ignored when systemd is used.
# If you need to run mysqld under different user or group,
# customize your systemd unit file for mysqld according to the
# instructions in http://fedoraproject.org/wiki/Systemd
# max_allowed_packet=500M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0


innodb_buffer_pool_size         = 512M


[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

Eu tenho o mesmo problema na minha micro instância EC2. Tentei definir innodb_buffer_pool_size = 128M e verei como funciona.
swxxii

Pode ser necessário adicionar espaço de troca se você estiver usando uma microinstância
pmoubed

1
Em micro Instâncias EC2, NÃO há espaço de troca por padrão e é necessário configurar manualmente. Caso contrário, você pode ver muitos travamentos do MySQL devido à falta de memória.
pmoubed de

Respostas:


163

Eu encontrei o mesmo problema quando tentei executar um wordpress na minha microinstância sem RDS.

Adicionar uma página de troca resolveu o problema para mim.

Você pode seguir as etapas abaixo para configurar o espaço de troca.

Se ainda não funcionar para você, considere usar o serviço RDS.

===================================================

Copiei o conteúdo do blog para registro. O crédito vai para o autor do blog pmoubed :

Espaço de troca de microinstância do Amazon EC2 - Linux

Eu tenho uma instância do Amazon EC2 Linux Micro. Como as microinstâncias têm apenas 613 MB de memória, o MySQL travava de vez em quando. Depois de uma longa pesquisa sobre MySQL, Microinstância e Gerenciamento de Memória, descobri que não há espaço SWAP padrão para Microinstância. Portanto, se você quiser evitar o travamento, pode precisar configurar um espaço de troca para sua microinstância. Na verdade, em termos de desempenho, é melhor habilitar a troca.

As etapas abaixo mostram como fazer um espaço de troca para sua microinstância. Presumo que você tenha uma conta AWS com uma microinstância em execução.

  1. Corre dd if=/dev/zero of=/swapfile bs=1M count=1024
  2. Corre mkswap /swapfile
  3. Corre swapon /swapfile
  4. Adicione esta linha /swapfile swap swap defaults 0 0a/etc/fstab

A etapa 4 é necessária se você deseja habilitar automaticamente o arquivo de troca após cada reinicialização.

Alguns comandos úteis relacionados ao espaço SWAP:

$ swapon -s   
$ free -k

$ swapoff -a
$ swapon  -a

Referências:

  1. http://www.thegeekstuff.com/2010/08/how-to-add-swap-space/
  2. http://cloudstory.in/2012/02/getting-the-best-out-of-amazon-ec2-micro-instances/
  3. http://cloudstory.in/2012/02/adding-swap-space-to-amazon-ec2-linux-micro-instance-to-increase-the-performance/
  4. http://aws.amazon.com/ec2/instance-types/

Obrigado! Isso me ajudou!
Desfazer

8
Para sua informação, funcionou para mim em uma gota do Digital Ocean (512 MB). Não que isso deva surpreender ninguém, mas no caso de alguém que não tenha certeza, provavelmente funcionará em qualquer servidor com os mesmos problemas.
jfacemyer

Obrigado por este salva-vidas! Também estava executando uma microinstância com Ubuntu Server.
ECC-Dan

4
Para usuários do Digital Ocean, segui este tutorial e funcionou perfeitamente
Chris Ray

Muito obrigado. Tenho puxado meu cabelo nas últimas 24 horas, jogado com todos os tipos de tamanhos de buffer / cache / consulta .. Você salva minha vida!
pranshus

23

Eu também tive esse problema em uma microinstância do Amazon EC2. Tentei diminuir o uso de memória do inno_db adicionando o seguinte ao/etc/my.cnf

innodb_buffer_pool_size = 64M

Isso não funcionou, eu tentei diminuir para 16M e ainda não funcionou. Então percebi que a instância tinha basicamente zero memória livre. Tentei reiniciar o apache

sudo system httpd restart
sudo system mysqld restart

E tudo funcionou bem. Talvez outra solução seja configurar o apache para não consumir tanta memória de alguma forma.


2
O MySQL ainda pode travar, então pode ser necessário adicionar espaço de troca à sua microinstância.
pmoubed de

Obrigado, isso faz sentido. Acho que também posso tentar limitar o número de threads que o apache pode gerar.
wfbarksdale

Funciona bem. Eu também tenho esse problema e, reiniciando o httpd, resolvi o problema.
Lionel Chan,

1
Captura incrível, mesmo barco aqui. Eu configurei meu apache para usar menos memória RAM e também criei um arquivo de troca de 512m, mas configurei o vm.swappiness para 10 para que ele só fosse usado em uma pitada.
newz2000

Reiniciar nginx e php-fpm também liberou memória suficiente para permitir que o mysql inicie! Obrigado!
msEmmaMays

4

Parece que você está solicitando 128 MB de memória para innodb_buffer_pool_size no arquivo my.cfg que você mostra na postagem, mas o MySQL acha que você está pedindo 512 MB de memória:

Inicializando buffer pool, tamanho = 512,0M

Algumas linhas abaixo, a mensagem de erro informa que o MySQL não iniciará porque não pode reservar memória suficiente (512M) para o buffer pool do InnoDB:

Erro fatal: não é possível alocar memória para o buffer pool

Isso levanta três questões:

  1. Quanta memória há em sua instância? Deve haver memória suficiente para acomodar o 512M que o InnoDB está tentando pegar para o buffer pool, mais tudo o mais que o MySQL aloca, mais seu (s) aplicativo (s), mais o sistema operacional?
  2. Por que o InnoDB está tentando pegar mais do que você acha que deveria?
  3. Por que o MySQL está reiniciando de qualquer maneira?

Você pode responder 1.

Quanto a 2., existem alguns lugares diferentes onde os arquivos de opções do MySQL podem ser localizados. Os arquivos encontrados posteriormente substituem as opções especificadas nos arquivos encontrados anteriormente. Vejo

http://dev.mysql.com/doc/refman/5.5/en/option-files.html

O problema 3. pode ser devido a uma condição de falta de memória que ocorre algum tempo após a inicialização. Você deve ver uma indicação disso nos registros, se for esse o caso.

Finalmente, mas de forma algo não relacionado, você está usando instâncias apoiadas pelo EBS? Isso geralmente é altamente recomendado para servidores de banco de dados (na verdade, para qualquer instância, exceto circunstâncias especiais). Para mais informações, consulte

https://stackoverflow.com/a/3630707/141172


2

Para mim, exatamente esse problema foi corrigido adicionando um volume de swap à minha instância EC2. Meus serviços estavam simplesmente consumindo toda a memória da caixa e travavam. Não é algo que eu estava acostumado, sendo um administrador RedHat / CentOS por anos - o Anaconda faz MUITOS trabalhos que a instância gratuita do Ubuntu EC2 não faz.

Simplesmente criei um volume de 2 Gb por meio do console da web, anexei-o à minha instância e fiz "mkswap / dev / [qualquer]", editei / etc / fstab e o travamento parou.

Essas instâncias NÃO são instaladas como uma instalação de sistema operacional baseada em mídia com a qual a maioria de nós está acostumada - é despojada, sem pacotes, sem sistema de arquivos adequado e coisas como AppArmor, que causam todos os tipos de problemas se você não estiver ciente disso e / ou não sei como configurá-lo.


1

O problema é que o servidor não tem memória suficiente para alocar para o processo MySQL. Existem algumas soluções para esse problema.

(1) Aumente a RAM física. Adicionar 1 GB de RAM adicional resolverá o problema. (2) Alocar espaço SWAP. A instância do Digital Ocean VPS não está configurada para usar o espaço de troca por padrão. Ao alocar 512 MB de espaço de troca, conseguimos resolver este problema. Para adicionar espaço de troca ao seu servidor, siga as seguintes etapas:

## As a root user, perform the following:
# dd if=/dev/zero of=/swap.dat bs=1024 count=512M
# mkswap /swap.dat
# swapon /swap.dat
## Edit the /etc/fstab, and the following entry.
/swap.dat      none    swap    sw      0       0 

Reduza o tamanho do buffer pool do MySQL

## Edit /etc/my.cnf, and add the following line under the [mysqld] heading.
[mysqld]
innodb_buffer_pool_size=64M

Verifique também o espaço em disco. Certifique-se de ter espaço suficiente.

df-h


1

RESPOSTA FÁCIL:

* * * * * systemctl is-active --quiet mysqld || systemctl restart mysqld

RESPOSTA DETALHADA:

Esta é uma questão importante, especialmente para pessoas que usam um VPS muito pequeno, digamos 1 GB de RAM ou menos. Se o MySQL estiver caindo, pode ser um problema com a configuração do servidor (Apache | nginx) ou configuração do MySQL. Ataques DOS podem causar um aumento no uso de recursos do sistema (veja a imagem). O resultado final é que o processo do MySQL é encerrado pelo Kernel. Para uma solução de longo prazo, você deve olhar para otimizar suas configurações do Apache ou MySQL.

Aumento dos recursos do sistema causando pico de RAM (pouco antes das 18h) e pico de recursos do sistema causando apenas um pico de CPU Meia-noite na terça 18

Existem várias outras discussões sobre os tópicos do Stack Overflow, bem como o manual do MySQL e o Percona Blog:

Manual do MySQL - Como o MySQL usa memória:

https://dev.mysql.com/doc/refman/8.0/en/memory-use.html

Percona - Melhores práticas para configurar o uso ideal da memória MySQL:

https://www.percona.com/blog/2016/05/03/best-practices-for-configuring-optimal-mysql-memory-usage/

Como otimizar o desempenho do MySQL usando o MySQLTuner:

https://www.linode.com/docs/databases/mysql/how-to-optimize-mysql-performance-using-mysqltuner/

Configuração de uso de memória Apache:

/server/254436/apache-memory-usage-optimization

Manual Apache sobre ajuste de desempenho:

https://httpd.apache.org/docs/2.4/misc/perf-tuning.html

Ajustando o servidor Apache:

https://www.linode.com/docs/web-servers/apache-tips-and-tricks/tuning-your-apache-server/

No entanto, com relação à sua pergunta original, sim, você pode criar um script de solução temporária que verifica se o serviço MySQL está carregado e ativo e irá reiniciar o MySQL se não estiver carregado e ativo.

Você não mencionou qual sistema operacional está usando. Isso ajudaria a dar a você um comando específico. Vou te dar um exemplo para CentOS linux.
Observe a seguinte saída do comando systemctl status mysql. Você pode ver na parte superior que o serviço está carregado e ativo .

[root@centos-mysql-demo ~]# systemctl status mysqld
 mysqld.service - MySQL Server
   Loaded: loaded (/usr/lib/systemd/system/mysqld.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2019-06-18 18:28:18 UTC; 924ms ago
     Docs: man:mysqld(8)
           http://dev.mysql.com/doc/refman/en/using-systemd.html
  Process: 3350 ExecStart=/usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid $MYSQLD_OPTS (code=exited, status=0/SUCCESS)
  Process: 3273 ExecStartPre=/usr/bin/mysqld_pre_systemd (code=exited, status=0/SUCCESS)
 Main PID: 3353 (mysqld)
   CGroup: /system.slice/mysqld.service
           └─3353 /usr/sbin/mysqld --daemonize --pid-file=/var/run/mysqld/mysqld.pid

Jun 18 18:28:11 centos-mysql-demo systemd[1]: Starting MySQL Server...
Jun 18 18:28:18 centos-mysql-demo systemd[1]: Started MySQL Server.

Se o serviço não estiver carregado, um comando como:

systemctl status mysqld || systemctl restart mysqld 

fará o truque de reiniciar o processo. Você poderia cron que:

* * * * * systemctl status mysqld || systemctl restart mysqld

No entanto, caso o mysql seja carregado , mas o serviço não esteja ativo , seu cron não fará nada. Portanto, você deve usar um comando mais detalhado, como:

* * * * * systemctl is-active --quiet mysqld || systemctl restart mysqld

Nesse caso, se o serviço estiver carregado, mas inativo , como o estado em que um ataque DOS pode deixar seu serviço mysql, o comando também reiniciará o mysql. Usar o --quietsinalizador apenas especifica o comando apenas para retornar um código de status, sem exibir nada na tela. Se você omitir o --quietsinalizador, verá uma saída de status de activeou inactive.

Você também pode criar algum espaço de troca para adicionar mais recursos de RAM disponíveis ao seu servidor, como:

sudo dd if=/dev/zero of=/swapfile count=2096 bs=1MiB
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
swapon --show
swapon --summary
free -h

0

Use qualquer uma das seguintes soluções:

  1. Aumente a RAM física. Adicionar 1 GB de RAM adicional resolverá o problema.

  2. Aloque espaço SWAP usando as alterações de configuração abaixo:

config

dd if=/dev/zero of=/extraswap bs=1024 count=512M
mkswap  /extraswap 
swapon  /extraswap 
## Edit the /etc/fstab, and the following entry.
/extraswap      none    swap    sw      0       0
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.