MySQL Error: The Server Quit Without Updating PID File — Complete Diagnostic and Fix Guide
The "The server quit without updating PID file" error means MySQL terminated before it could write its process identifier to the configured `.pid` file — a hard stop that prevents the daemon from accepting connections. This failure is almost always a symptom of a deeper issue: a misconfiguration in `my.cnf`, a permissions mismatch on the data directory, a full disk partition, table-level corruption, or a port conflict with a second MySQL or MariaDB instance.
This guide walks through every confirmed root cause, provides exact shell commands to diagnose and repair each one, and covers edge cases that generic tutorials routinely miss.
What the PID File Actually Does and Why Its Absence Matters
MySQL writes its process ID (PID) to a small plain-text file — typically `/var/run/mysqld/mysqld.pid` — immediately after the daemon initializes. Init systems, service managers (systemd, SysVinit), and monitoring tools read this file to send signals to the correct process. If MySQL crashes, exits abnormally, or encounters a fatal error during startup, it never reaches the point of writing that file. The service manager then reports the "quit without updating PID file" message.
Understanding this sequence is critical: the PID file error is a *consequence*, not the root cause. Chasing the PID file itself without reading the error log first is the single most common mistake administrators make.
Common Root Causes at a Glance
| Root Cause | Typical Symptom in Error Log | Affected Systems |
|---|---|---|
| — | — | — |
| Wrong `pid-file` path in `my.cnf` | `Can't start server: can't create PID file` | All distros |
| Incorrect ownership on `/var/run/mysqld` | `Permission denied` on PID directory | Debian/Ubuntu after upgrades |
| Full disk or inode exhaustion | `No space left on device` | Any server with small `/var` |
| Corrupted `ibdata1` or InnoDB redo logs | `InnoDB: Corruption detected` | MySQL 5.7, 8.0, MariaDB |
| Stale `.pid` file from a previous crash | `A mysqld process already exists` | Any system after hard reboot |
| Port 3306 already in use | `Can't start server: Bind on TCP/IP port` | Multi-instance setups |
| AppArmor or SELinux policy denial | `apparmor="DENIED"` in syslog | Ubuntu, RHEL/CentOS |
| Mismatched `datadir` after package upgrade | `[ERROR] Fatal error: Can't open and lock privilege tables` | Major version upgrades |
Step 1 — Read the MySQL Error Log First
Every other step depends on what the error log says. Do not skip this.
“`bash
Debian/Ubuntu default path
sudo tail -100 /var/log/mysql/error.log
RHEL/CentOS/AlmaLinux default path
sudo tail -100 /var/log/mysqld.log
If you are unsure of the path, query the running config
mysqld –verbose –help 2>/dev/null | grep "log-error"
“`
Search for lines containing `[ERROR]`, `[FATAL]`, `Aborting`, or `InnoDB`. The first `[ERROR]` entry in the startup sequence is almost always the true cause.
Step 2 — Verify and Fix the PID File Directory
The PID directory is often recreated as `root`-owned after a system reboot because `/var/run` is a `tmpfs` mount on modern Linux distributions. This is one of the most frequently overlooked causes on Ubuntu 20.04+ and Debian 11+.
“`bash
Check current ownership
ls -ld /var/run/mysqld
Recreate the directory with correct ownership
sudo mkdir -p /var/run/mysqld
sudo chown mysql:mysql /var/run/mysqld
sudo chmod 755 /var/run/mysqld
“`
To make this persistent across reboots on systemd systems, create a `tmpfiles.d` rule:
“`bash
echo "d /var/run/mysqld 0755 mysql mysql -" | sudo tee /etc/tmpfiles.d/mysqld.conf
“`
Confirm the PID path configured in `my.cnf` matches the directory you just created:
“`bash
sudo grep -i "pid" /etc/mysql/my.cnf /etc/mysql/mysql.conf.d/*.cnf 2>/dev/null
“`
Step 3 — Audit Data Directory Ownership and Permissions
MySQL's data directory must be owned entirely by the `mysql` system user. Package upgrades, manual file copies, or restores from backup frequently break this.
“`bash
Correct ownership recursively
sudo chown -R mysql:mysql /var/lib/mysql
Correct permissions — directories 750, files 640 is more secure than 755/644
sudo find /var/lib/mysql -type d -exec chmod 750 {} ;
sudo find /var/lib/mysql -type f -exec chmod 640 {} ;
“`
Important edge case: If you restored a backup using `rsync` or `cp` as `root`, the socket file `/var/lib/mysql/mysql.sock` may also be root-owned. Remove it — MySQL will recreate it on startup:
“`bash
sudo rm -f /var/lib/mysql/mysql.sock
sudo rm -f /var/run/mysqld/mysqld.sock
“`
Step 4 — Check Disk Space and Inode Availability
A full disk silently prevents MySQL from writing any file, including the PID file and binary logs.
“`bash
Check disk space
df -h
Check inode usage — often overlooked
df -i
Find the largest directories consuming space
sudo du -sh /var/lib/mysql/* | sort -rh | head -20
“`
If the partition is full, common culprits are binary logs (`mysql-bin.000*`), general query logs left enabled accidentally, or core dump files. To safely purge old binary logs from within MySQL:
“`bash
mysql -u root -p -e "PURGE BINARY LOGS BEFORE DATE_SUB(NOW(), INTERVAL 7 DAY);"
“`
Step 5 — Eliminate Stale PID Files and Conflicting Processes
After a kernel panic, power loss, or `kill -9`, a stale PID file may remain on disk. MySQL refuses to start if it finds one.
“`bash
Check for a stale PID file
cat /var/run/mysqld/mysqld.pid
Verify whether that PID is actually running
ps aux | grep mysqld
If the process is not running but the file exists, remove it
sudo rm -f /var/run/mysqld/mysqld.pid
“`
If another MySQL or MariaDB instance is genuinely running and occupying port 3306:
“`bash
sudo ss -tlnp | grep 3306
sudo systemctl stop mariadb
sudo systemctl stop mysql
sudo killall -9 mysqld mysqld_safe
“`
Wait three seconds after killing processes before attempting a restart to allow kernel socket TIME_WAIT states to clear.
Step 6 — Check AppArmor and SELinux Policies
This cause is almost never mentioned in basic tutorials, yet it is responsible for a significant percentage of PID file errors on Ubuntu and RHEL-family systems.
Ubuntu / AppArmor:
“`bash
sudo dmesg | grep -i apparmor | grep -i mysql
sudo grep -i "DENIED" /var/log/syslog | grep mysql
“`
If AppArmor is blocking MySQL, either update the profile or temporarily set it to complain mode for diagnosis:
“`bash
sudo aa-complain /usr/sbin/mysqld
“`
RHEL / CentOS / AlmaLinux — SELinux:
“`bash
sudo ausearch -c 'mysqld' –raw | audit2why
sudo sealert -a /var/log/audit/audit.log | grep mysqld
“`
A common fix for SELinux context issues after moving the data directory:
“`bash
sudo semanage fcontext -a -t mysqld_db_t "/new/datadir(/.*)?"
sudo restorecon -Rv /new/datadir
“`
Step 7 — Diagnose and Repair InnoDB Corruption
If the error log contains messages like `InnoDB: Corruption detected`, `[ERROR] InnoDB: Unable to lock ./ibdata1`, or references to redo log inconsistencies, the InnoDB tablespace itself is damaged.
For MyISAM tables, use `mysqlcheck`:
“`bash
sudo mysqlcheck –all-databases –repair –user=root –password
“`
For InnoDB corruption, `mysqlcheck` is insufficient. The correct approach is to enable InnoDB forced recovery mode in `my.cnf`:
“`ini
[mysqld]
innodb_force_recovery = 1
“`
Start MySQL with this setting, immediately dump all databases, then rebuild:
“`bash
mysqldump –all-databases –single-transaction -u root -p > full_backup.sql
“`
Increment `innodb_force_recovery` from 1 to 6 only if lower values fail to start the server. At level 4 and above, data loss is possible — treat the instance as read-only and export immediately.
After a successful dump:
“`bash
sudo systemctl stop mysql
sudo rm -rf /var/lib/mysql/ib_logfile* # Remove corrupt redo logs
Remove innodb_force_recovery from my.cnf
sudo systemctl start mysql
mysql -u root -p < full_backup.sql
“`
Step 8 — Isolate Configuration Errors in my.cnf
A single typo or an invalid directive in `my.cnf` will abort startup before the PID file is written. MySQL 8.0+ is stricter about unknown options than 5.7 was.
“`bash
Validate configuration without starting the server
mysqld –validate-config
Or test with verbose output
mysqld –verbose –help > /dev/null
“`
Back up and strip the configuration to defaults:
“`bash
sudo cp /etc/mysql/my.cnf /etc/mysql/my.cnf.bak.$(date +%F)
“`
Common problematic directives after major version upgrades include deprecated options like `query_cache_size`, `query_cache_type`, `innodb_file_format`, and `innodb_large_prefix` — all removed in MySQL 8.0.
Step 9 — Restart MySQL and Validate
“`bash
sudo systemctl restart mysql
Check service status
sudo systemctl status mysql
Confirm the PID file was written
cat /var/run/mysqld/mysqld.pid
Confirm MySQL is accepting connections
mysqladmin -u root -p status
“`
Step 10 — Reinstalling MySQL (Last Resort with Data Preservation)
Reinstallation should only happen after exhausting every diagnostic step above. Before proceeding, back up all data:
“`bash
If MySQL can start in recovery mode, dump first
mysqldump –all-databases -u root -p > /backup/full_$(date +%F).sql
Copy raw data directory as a secondary backup
sudo rsync -av /var/lib/mysql/ /backup/mysql_datadir_$(date +%F)/
“`
Then remove and reinstall:
“`bash
sudo systemctl stop mysql
sudo apt-get remove –purge mysql-server mysql-client mysql-common
sudo apt-get autoremove && sudo apt-get autoclean
sudo rm -rf /var/lib/mysql /etc/mysql
sudo apt-get install mysql-server
sudo mysql_secure_installation
“`
Restore from dump:
“`bash
mysql -u root -p < /backup/full_$(date +%F).sql
“`
Choosing the Right Hosting Environment to Prevent Recurrence
Many of these failures — disk exhaustion, permission resets after reboots, resource contention from co-hosted services — are infrastructure problems as much as MySQL problems. Running a production database on a properly provisioned server with dedicated resources eliminates entire categories of these errors.
If you are managing a MySQL-backed application, a VPS Hosting environment gives you full root access, isolated resources, and the ability to configure `tmpfiles.d`, AppArmor profiles, and systemd unit overrides without restriction. For high-traffic databases requiring guaranteed IOPS and RAM, Dedicated Servers remove all resource-sharing concerns entirely.
For teams that prefer a managed control panel rather than direct CLI administration, VPS with cPanel provides MySQL management interfaces alongside server-level access. If your stack also requires domain and DNS configuration, Domain Registration and SSL Certificates can be managed from the same provider, reducing operational overhead.
Decision Matrix: Which Fix to Apply First
| Symptom in Error Log | First Action | Estimated Resolution Time |
|---|---|---|
| — | — | — |
| `Permission denied` on PID or data dir | Fix ownership with `chown mysql:mysql` | 2 minutes |
| `No space left on device` | Purge binary logs, expand disk | 5–30 minutes |
| `A mysqld process already exists` | Remove stale PID file, kill orphan process | 2 minutes |
| `Bind on TCP/IP port: Address already in use` | Stop conflicting instance, check `ss -tlnp` | 5 minutes |
| `InnoDB: Corruption detected` | Enable `innodb_force_recovery`, dump, rebuild | 30 minutes to several hours |
| `apparmor="DENIED"` in syslog | Update AppArmor profile or set complain mode | 10 minutes |
| `unknown variable` in log | Run `mysqld –validate-config`, fix `my.cnf` | 5 minutes |
| No specific error, all else fails | Reinstall MySQL, restore from backup | 1–2 hours |
Technical Key-Takeaway Checklist
- Always read `/var/log/mysql/error.log` or `/var/log/mysqld.log` before touching any file — the first `[ERROR]` line identifies the actual cause.
- On systemd systems with `tmpfs` on `/var/run`, create a persistent `/etc/tmpfiles.d/mysqld.conf` rule to prevent permission resets on every reboot.
- After any `rsync` or manual backup restore, run `chown -R mysql:mysql /var/lib/mysql` before attempting to start MySQL.
- Check `df -i` (inode usage) alongside `df -h` (disk space) — a full inode table produces identical symptoms to a full disk.
- For InnoDB corruption, use `innodb_force_recovery` incrementally from 1 upward; never jump straight to level 6.
- Validate `my.cnf` syntax with `mysqld –validate-config` before restarting — this catches typos without a failed start attempt.
- Remove deprecated MySQL 5.7 directives (`query_cache_*`, `innodb_file_format`) before upgrading to MySQL 8.0.
- On Ubuntu, check AppArmor denials in `/var/log/syslog`; on RHEL/AlmaLinux, check SELinux with `ausearch -c mysqld`.
Frequently Asked Questions
What is the fastest way to find why MySQL failed to start?
Run `sudo tail -50 /var/log/mysql/error.log` and look for the first line containing `[ERROR]` or `[FATAL]`. That single line identifies the root cause in the vast majority of cases and determines which fix to apply.
Why does the PID directory lose its permissions after a reboot?
On Linux distributions using `tmpfs` for `/var/run` (which includes Ubuntu 18.04+ and Debian 10+), the entire `/var/run` tree is rebuilt in memory at boot. Any directory not defined in `/etc/tmpfiles.d/` is recreated as `root:root`. The fix is to add a `tmpfiles.d` rule: `echo "d /var/run/mysqld 0755 mysql mysql -" | sudo tee /etc/tmpfiles.d/mysqld.conf`.
Can I recover data if MySQL will not start at all due to InnoDB corruption?
Yes, in most cases. Set `innodb_force_recovery = 1` in `my.cnf`, start MySQL, and immediately run `mysqldump –all-databases`. If level 1 does not start the server, increment to 2, then 3, and so on. At levels 4–6, some data may be unrecoverable, but the majority of tables are typically intact.
How do I prevent "no space left on device" from taking down MySQL again?
Enable binary log expiration: set `binlog_expire_logs_seconds = 604800` (7 days) in `my.cnf`. Additionally, disable the general query log in production (`general_log = 0`) and set up a disk usage alert at 80% capacity through your monitoring system.
Does this error occur on MariaDB as well, and is the fix the same?
Yes. MariaDB uses the same PID file mechanism and the same data directory structure as MySQL. All diagnostic steps in this guide apply directly to MariaDB, with the only difference being that the service name is `mariadb` instead of `mysql` in `systemctl` commands, and the error log may be located at `/var/log/mariadb/mariadb.log` depending on the distribution.
