VPS Tutorials
Running MySQL Docker on a Low-Memory VPS (2026): OOM 137, ibdata1 Lock and Swap Tuning
For 1-core 1G/2G VPS running MySQL 8 Docker, this covers Exit Code 137, ibdata1 error 11 and container restart issues, with troubleshooting and tuning steps for dmesg, lsof, Docker memory limits, InnoDB buffer pool, Performance Schema and Swap.

When running the MySQL 8.0 Docker image on low-spec servers (such as 1-core 1G / 1-core 2G cloud servers), you often run into hidden problems like containers restarting endlessly and data files being locked. This article documents a real troubleshooting process, from the OOM crash (Exit Code 137) to the file lock conflict (Error 11), covering the complete path of pitfalls and solutions.
After starting the MySQL container, check the logs with docker logs -f mysql-docker and you will find it interrupts at the InnoDB initialization step:
mysql-docker | ... [System] [MY-013576] [InnoDB] InnoDB initialization has started.
mysql-docker exited with code 137 (restarting)
Exit Code 137 corresponds to the Linux signal 128 + 9 (SIGKILL), meaning the process was forcibly terminated by the Linux kernel's OOM Killer (Out-Of-Memory killer).
MySQL 8.0's default startup configuration has high memory requirements, and it pre-allocates a large Buffer Pool when initializing InnoDB. When the host's available memory is insufficient, the kernel kills the mysqld process consuming the most memory to prevent the system from going down.
Run the following command on the host to confirm whether it is a memory issue:
# 查看宿主机系统内核日志
dmesg -T | grep -i oom
# 查看 Docker 是否记录了 OOM
docker inspect mysql-docker --format='{{.State.OOMKilled}}'
If the output shows true or contains Killed process ... (mysqld), it is confirmed to be an out-of-memory condition.
After limiting the container's memory or force-killing and restarting the container, the logs may show a new error:
[ERROR] [MY-012574] [InnoDB] Unable to lock ./ibdata1 error: 11
- Error 11 (
EAGAIN / Resource temporarily unavailable): This means the data fileibdata1has already been given a Write Lock by another process. - Why it happens: When the previous container crashed suddenly due to OOM, orphan processes that had not fully exited may remain in the background; or, although the old container has stopped, the system still holds file handles to the mounted volume at a lower level.
Use lsof to see who is occupying ibdata1:
# 查出占用 ibdata1 的进程
lsof /var/lib/mysql/ibdata1
Example output:
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
mysqld 429692 systemd-coredump 9uW REG 253,1 12582912 31823670 /var/lib/mysql/ibdata1
- Reading the flags: The
Win9uWstands for Write Lock, proving that PID429692has exclusive access to the file. - User explanation:
systemd-coredumpis because themysqluser UID inside the Docker container (such as 999) is mapped to the corresponding account name on the host, further confirming that this is a leftover container process from the previous crash.
For the two problems above, the correct order of handling is: clean up leftover lock processes -> optimize MySQL configuration -> configure container memory and Swap.
Force-kill the leftover mysqld process on the host:
# 1. 强杀残留进程
kill -9 429692
# 2. 清理旧容器
docker stop mysql-docker && docker rm mysql-docker
Running MySQL 8.0 in a low-memory environment requires limiting memory overhead. It is recommended to reduce the InnoDB buffer pool and disable Performance Schema:
--innodb-buffer-pool-size=128M(or 256M): Lower the buffer pool to a reasonable range (the default is often 1G or more).--performance-schema=OFF: Disable performance monitoring, which can directly free up 200MB~400MB of memory.
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
If physical memory is only 1GB, it is recommended to add 2GB of Swap to prevent sudden memory spikes from being killed by 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
- Exit code 137 = killed by the kernel due to insufficient memory (OOM); check
dmesgfirst when troubleshooting. - Error 11 (Unable to lock) = leftover process or unreleased lock; use
lsoffirst to find the PID and force-kill it. - Essential configuration for low-spec servers: lower
innodb-buffer-pool-size+ disableperformance-schema+ enable systemSwap; these three together let MySQL run stably on a 1G-memory lightweight cloud server.