Moving the MySQL or MariaDB data directory to a dedicated filesystem can free space on the root volume, put database files on faster storage, and simplify backup or snapshot planning when database growth no longer fits comfortably under /var.
On Ubuntu, both database servers read the datadir setting from option files under /etc/mysql and then let systemd start the daemon against that location. A safe move therefore means stopping the service, copying the full contents with ownership and permissions intact, pointing the active server option file at the new path, and keeping the old directory as rollback until startup succeeds.
The package details differ slightly on current Ubuntu releases: MySQL uses /etc/mysql/mysql.conf.d/mysqld.cnf with the AppArmor profile /etc/apparmor.d/usr.sbin.mysqld, while MariaDB uses /etc/mysql/mariadb.conf.d/50-server.cnf with /etc/apparmor.d/usr.sbin.mariadbd. If the new path lives on a separate filesystem, make sure it is mounted before the service starts, because a missing mount can expose an empty directory at the same path and cause the move to fail or, on current MySQL packages, initialize a fresh empty data directory.
Steps to change MySQL or MariaDB data directory in Ubuntu:
- Record the current datadir value from the running server.
$ sudo mysql --table --execute "SHOW VARIABLES LIKE 'datadir';" +---------------+----------------+ | Variable_name | Value | +---------------+----------------+ | datadir | /var/lib/mysql/| +---------------+----------------+
Add --user=root --password when local administrative access is not configured for sudo mysql.
- Identify the database service unit that the host actually uses.
$ systemctl list-unit-files --type=service | grep --extended-regexp '^(mysql|mariadb)\.service' mysql.service enabled enabled
Current Ubuntu MariaDB packages usually keep mysql.service as a compatibility alias even though mariadb.service is the primary unit name, so use the name that resolves correctly on the host.
Related: How to manage MySQL or MariaDB service in Linux - Stop the database service before copying any files.
$ sudo systemctl stop mysql
Stopping the service drops active connections, so schedule the move for a maintenance window or application outage.
- Create the new data directory with the expected owner, group, and mode.
$ sudo install --directory --owner=mysql --group=mysql --mode=0750 /data/mysql
The target filesystem needs normal Linux ownership and permission support, such as ext4 or xfs.
- Confirm that the new path is already on the intended mounted filesystem.
$ df -h /data/mysql Filesystem Size Used Avail Use% Mounted on /dev/sdb1 200G 20G 170G 11% /data
Do not start the service until the real mounted filesystem is present at the new path. A missing mount can hide the copied files, and current MySQL packages on systemd can initialize an empty data directory when startup sees an empty target path.
- Copy the existing database files to the new path with metadata preserved.
$ sudo cp --archive /var/lib/mysql/. /data/mysql/
Replace /var/lib/mysql with the path returned by the earlier datadir query when it differs from the default.
- Verify the copied directory still belongs to the mysql service account.
$ sudo stat --format "%U:%G %a %n" /data/mysql mysql:mysql 750 /data/mysql
- Rename the original data directory so it remains available for rollback.
$ sudo mv /var/lib/mysql /var/lib/mysql.old
Keep the rollback copy until the service starts cleanly and the server reports the new datadir.
- Locate the option file that currently defines datadir on this host.
$ sudo grep --recursive --line-number --extended-regexp '^[[:space:]]*datadir[[:space:]]*=' /etc/mysql/ /etc/mysql/mysql.conf.d/mysqld.cnf:31:datadir = /var/lib/mysql
Current Ubuntu MySQL packages usually store this in /etc/mysql/mysql.conf.d/mysqld.cnf, while current MariaDB packages usually use /etc/mysql/mariadb.conf.d/50-server.cnf.
Related: How to locate and modify MySQL and MariaDB configuration files - Open the file that contains the active datadir setting.
$ sudoedit /etc/mysql/mysql.conf.d/mysqld.cnf
Use the exact file returned by the previous command instead of editing every file under /etc/mysql.
- Update the datadir setting under [mysqld] to the new path.
[mysqld] datadir = /data/mysql
- Confirm the effective server options now point at the new datadir before startup.
$ my_print_defaults mysqld | grep '^--datadir=' --datadir=/data/mysql
If more than one --datadir line appears, another later option file is still overriding the setting.
- Open the AppArmor alias file used for site-specific path remapping.
$ sudoedit /etc/apparmor.d/tunables/alias
- Add an alias that maps the default data directory to the new path.
alias /var/lib/mysql/ -> /data/mysql/,
The alias lets the packaged AppArmor profile keep referring to /var/lib/mysql while granting access to the new directory.
- Identify the AppArmor database profile file installed by the current package.
$ ls /etc/apparmor.d/usr.sbin.mysqld /etc/apparmor.d/usr.sbin.mariadbd 2>/dev/null /etc/apparmor.d/usr.sbin.mysqld
Current Ubuntu MySQL packages use usr.sbin.mysqld, while current MariaDB packages use usr.sbin.mariadbd.
- Reload the matching AppArmor profile after the alias change.
$ sudo apparmor_parser --replace /etc/apparmor.d/usr.sbin.mysqld
Replace the profile path with /etc/apparmor.d/usr.sbin.mariadbd when that is the file detected on the host.
- Start the database service against the new data directory.
$ sudo systemctl start mysql
Replace mysql with mariadb when the host does not expose the mysql.service compatibility alias.
- Confirm that the service returned to the active state.
$ systemctl is-active mysql active
Replace mysql with mariadb when the host does not expose the mysql.service compatibility alias.
- Verify that the live server now reports the new data directory.
$ sudo mysql --table --execute "SHOW VARIABLES LIKE 'datadir';" +---------------+-------------+ | Variable_name | Value | +---------------+-------------+ | datadir | /data/mysql/| +---------------+-------------+
- Review the recent journal if startup fails or AppArmor denies the new path.
$ sudo journalctl --unit=mysql --no-pager --since "10 minutes ago" ##### snipped ##### apparmor="DENIED" operation="open" profile="usr.sbin.mysqld" name="/data/mysql/ibdata1" pid=12345 comm="mysqld" ##### snipped #####
Replace mysql with mariadb when the host does not expose the mysql.service compatibility alias.
Related: How to view the MySQL or MariaDB server error log
Related: How to disable and remove AppArmor in Ubuntu and Debian - Remove the rollback copy only after normal database access has been confirmed from the new location.
$ sudo rm --recursive --force /var/lib/mysql.old
Deleting the rollback directory is irreversible, so keep a verified backup before running rm.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.
