Databases grow. When /var/lib/mysql fills the root disk, or you’ve added a faster or larger volume, you can move the data directory. The procedure is simple, but two security layers — AppArmor on Ubuntu and SELinux on RHEL-family systems — trip up most attempts.
Example: move data from /var/lib/mysql to /srv/mysql (on a mounted data disk).
0. Back up first
sudo mysqldump --single-transaction --routines --triggers --events --all-databases | gzip > /root/all-before-move.sql.gz
1. Check the current location
sudo mysql -e "SELECT @@datadir;"
df -h /var/lib/mysql /srv
Make sure the target filesystem has enough space and is mounted permanently (in /etc/fstab — see fstab).
2. Stop the server
sudo systemctl stop mysql # or mariadb
sudo systemctl status mysql --no-pager
3. Copy the data
sudo rsync -aHAX /var/lib/mysql/ /srv/mysql/
sudo chown -R mysql:mysql /srv/mysql
sudo chmod 750 /srv/mysql
-a keeps permissions and ownership; -H -A -X preserve hard links, ACLs and extended attributes. Keep the original directory for now — rename it rather than deleting:
sudo mv /var/lib/mysql /var/lib/mysql.old
4. Point MySQL at the new directory
MySQL on Ubuntu — /etc/mysql/mysql.conf.d/mysqld.cnf; MariaDB — /etc/mysql/mariadb.conf.d/50-server.cnf:
[mysqld]
datadir = /srv/mysql
Some clients and scripts expect the socket at the default path; it stays in /var/run/mysqld/ unless you change socket, so you normally don’t need to touch it.
5. AppArmor (Ubuntu, Debian with AppArmor)
The MySQL AppArmor profile only allows access to /var/lib/mysql. Add the new path via an alias in /etc/apparmor.d/tunables/alias:
alias /var/lib/mysql/ -> /srv/mysql/,
Reload AppArmor:
sudo systemctl reload apparmor
(MariaDB packages on recent Ubuntu/Debian may not ship an enforcing profile; check sudo aa-status | grep -i mysql.)
If you skip this, MySQL fails to start with “Permission denied” errors even though file permissions are correct — and journalctl -k | grep apparmor shows DENIED lines.
5b. SELinux (AlmaLinux, Rocky, RHEL)
Label the new directory for MySQL:
sudo semanage fcontext -a -t mysqld_db_t "/srv/mysql(/.*)?"
sudo restorecon -Rv /srv/mysql
Check denials with sudo ausearch -m avc -ts recent. Don’t disable SELinux to work around it.
6. Start and verify
The default MySQL startup check expects /var/lib/mysql to exist on some systems. Create an empty placeholder if startup complains:
sudo mkdir /var/lib/mysql/mysql -p
Then:
sudo systemctl start mysql
sudo mysql -e "SELECT @@datadir;"
sudo mysql -e "SHOW DATABASES;"
Check the error log (/var/log/mysql/error.log) for warnings, and test your applications.
7. Clean up
After a few days of normal operation:
sudo rm -rf /var/lib/mysql.old
Alternative: bind mount
Instead of changing datadir, mount the new location at /var/lib/mysql:
/srv/mysql /var/lib/mysql none bind 0 0
in /etc/fstab. MySQL’s configuration and AppArmor profile stay untouched because the path doesn’t change. Many admins find this simpler.
Docker
For containerised databases, simply mount a directory on the new disk as the data volume (-v /srv/mysql:/var/lib/mysql) — or move Docker’s whole data root. See Docker volumes.
Related: disk full troubleshooting and resizing a disk partition. Need more room for data? A Storage VPS provides 500 GB of SSD.