Tutoriais de VPS
Executar MySQL Docker em VPS de pouca memória (2026): OOM 137, bloqueio do ibdata1 e ajuste de Swap
Para VPS de 1 núcleo e 1G/2G executando MySQL 8 Docker, aborda o Exit Code 137, o erro 11 do ibdata1 e reinícios do contêiner, com etapas de diagnóstico e ajuste de dmesg, lsof, limites de memória do Docker, buffer pool do InnoDB, Performance Schema e Swap.

Lições aprendidas: guia completo de diagnóstico e ajuste do MySQL Docker em servidores de pouca memória
Ao executar a imagem Docker do MySQL 8.0 em servidores de baixa configuração (como servidores em nuvem de 1 núcleo e 1G / 1 núcleo e 2G), é comum encontrar problemas ocultos como contêineres reiniciando sem parar e arquivos de dados bloqueados. Este artigo documenta um processo real de diagnóstico, desde a falha por OOM (Exit Code 137) até o conflito de bloqueio de arquivo (Error 11), cobrindo todo o caminho de erros e soluções.
Após iniciar o contêiner do MySQL, verifique os logs com docker logs -f mysql-docker e você verá que ele é interrompido na etapa de inicialização do InnoDB:
mysql-docker | ... [System] [MY-013576] [InnoDB] InnoDB initialization has started.
mysql-docker exited with code 137 (restarting)
Exit Code 137 corresponde ao sinal do Linux 128 + 9 (SIGKILL), o que significa que o processo foi encerrado à força pelo OOM Killer (mecanismo de encerramento por falta de memória) do kernel do Linux.
A configuração de inicialização padrão do MySQL 8.0 exige bastante memória e pré-aloca um Buffer Pool grande ao inicializar o InnoDB. Quando a memória disponível no host é insuficiente, o kernel encerra diretamente o processo mysqld que mais consome memória para evitar que o sistema caia.
Execute o comando a seguir no host para confirmar se é um problema de memória:
# 查看宿主机系统内核日志
dmesg -T | grep -i oom
# 查看 Docker 是否记录了 OOM
docker inspect mysql-docker --format='{{.State.OOMKilled}}'
Se a saída mostrar true ou contiver Killed process ... (mysqld), fica confirmado que é falta de memória.
Depois de limitar a memória do contêiner ou de encerrá-lo à força e reiniciá-lo, os logs podem mostrar um novo erro:
[ERROR] [MY-012574] [InnoDB] Unable to lock ./ibdata1 error: 11
- Error 11 (
EAGAIN / Resource temporarily unavailable): indica que o arquivo de dadosibdata1já recebeu um Write Lock (bloqueio de escrita) de outro processo. - Por que acontece: quando o contêiner anterior caiu de repente por OOM, podem ter ficado processos órfãos que não terminaram de sair; ou, mesmo que o contêiner antigo tenha parado, o sistema ainda mantém descritores de arquivo sobre o volume montado em nível mais baixo.
Use lsof para ver quem está ocupando ibdata1:
# 查出占用 ibdata1 的进程
lsof /var/lib/mysql/ibdata1
Exemplo de saída:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 429692 systemd-coredump 9uW REG 253,1 12582912 31823670 /var/lib/mysql/ibdata1
- Interpretação das marcações: o
Wem9uWrepresenta Write Lock (bloqueio de escrita), comprovando que o PID429692tem o arquivo em exclusividade. - Explicação do usuário:
systemd-coredumpocorre porque o UID do usuáriomysqldentro do contêiner Docker (por exemplo, 999) é mapeado para o nome de conta correspondente no host, confirmando ainda mais que se trata de um processo de contêiner residual da falha anterior.
Para os dois problemas acima, a ordem correta de tratamento é: limpar os processos de bloqueio residuais -> otimizar a configuração do MySQL -> configurar a memória do contêiner e o Swap.
Encerre à força o processo mysqld residual no host:
# 1. 强杀残留进程
kill -9 429692
# 2. 清理旧容器
docker stop mysql-docker && docker rm mysql-docker
Executar o MySQL 8.0 em ambiente de pouca memória exige limitar o consumo de memória. Recomenda-se reduzir o buffer pool do InnoDB e desativar o Performance Schema:
--innodb-buffer-pool-size=128M(ou 256M): reduza o buffer pool para uma faixa razoável (o valor padrão costuma ser 1G ou mais).--performance-schema=OFF: desative o monitoramento de desempenho, o que pode liberar diretamente de 200MB a 400MB de memória.
docker run -d \
--name mysql-docker \
--restart=always \
--memory=1g \
-v /var/lib/mysql:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=your_password \
mysql:8.0 \
--innodb-buffer-pool-size=128M \
--performance-schema=OFF
version: '3.8'
services:
mysql:
image: mysql:8.0
container_name: mysql-docker
restart: always
deploy:
resources:
limits:
memory: 1024M # 限制容器最大内存
command:
- --innodb-buffer-pool-size=128M
- --performance-schema=OFF
environment:
MYSQL_ROOT_PASSWORD: your_password
volumes:
- ./data:/var/lib/mysql
Se a memória física for de apenas 1GB, recomenda-se adicionar 2GB de Swap (partição de troca) para evitar que picos de memória sejam encerrados por OOM:
# 创建并启用 2GB Swap 文件
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 永久生效(追加到 /etc/fstab)
echo '/swapfile swap swap defaults 0 0' | sudo tee -a /etc/fstab
- Código de saída 137 = encerrado pelo kernel por falta de memória (OOM); ao diagnosticar, verifique primeiro
dmesg. - Error 11 (Unable to lock) = processo residual ou bloqueio não liberado; use primeiro
lsofpara encontrar o PID e encerrá-lo à força. - Configuração essencial em servidores de baixa configuração: reduzir
innodb-buffer-pool-size+ desativarperformance-schema+ ativar oSwapdo sistema; as três medidas juntas permitem que o MySQL funcione de forma estável em um servidor em nuvem leve de 1G de memória.