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.

  • MySQL
  • MariaDB
  • Storage