Databases·9 min read·

Move the MariaDB Datadir to a Dedicated Disk

Move the MariaDB datadir onto a dedicated High-Speed SSD volume with a clean stop, copy, permission fix, and a systemd-aware restart you can reverse.

NB

Netbay Engineering

Netbay Engineering

On this page

The default datadir on Ubuntu is /var/lib/mysql on the root filesystem. That is fine until the root volume is the smallest disk on the VPS and InnoDB, binlogs, and dumps start sharing it with logs and the application. Moving the datadir onto a dedicated High-Speed SSD volume is the standard fix. It is also one of the easier ways to lose a database if you copy while mysqld is running, leave AppArmor pointing at the old path, or start the service before permissions are right.

The sequence is stop, copy, re-point, confine, start, confirm. Never rsync a live InnoDB directory and hope redo will sort it out.

Attach, format, and mount the new volume first

Add a second disk to the VPS, partition it, and put a filesystem on it. ext4 is the boring, correct choice for a single datadir. Mount it at a stable path such as /mnt/mysql-data. Put the mount in /etc/fstab by UUID so a reboot does not return an empty directory and a failed InnoDB start.

bash
sudo lsblk
sudo mkfs.ext4 -L mysqldata /dev/sdb1
sudo mkdir -p /mnt/mysql-data
echo 'UUID=paste-the-uuid-here /mnt/mysql-data ext4 defaults,noatime 0 2' | sudo tee -a /etc/fstab
sudo mount /mnt/mysql-data
df -h /mnt/mysql-data

noatime avoids extra writes. Do not enable discard tricks you have not measured. Confirm the volume is the High-Speed SSD you attached, not a leftover loop device.

If AppArmor is enforcing (it is, on Ubuntu), MariaDB is only allowed to write the paths in its profile. A new datadir that the profile does not list will fail with mysterious permission errors in journalctl even when chmod looks correct. Plan to update the profile in the same change window.

Stop, copy, re-point, then start once

Take a dump first. A datadir move is a physical copy; a dump is the escape hatch if the copy is wrong. Then stop the service so InnoDB can shut down cleanly.

bash
sudo systemctl stop mariadb
sudo rsync -aHAX --numeric-ids /var/lib/mysql/ /mnt/mysql-data/
sudo chown -R mysql:mysql /mnt/mysql-data
sudo chmod 750 /mnt/mysql-data

-aHAX preserves permissions, ACLs, and sparse files. --numeric-ids avoids mapping mysql to the wrong uid if you ever copy between images. Count files on both sides. The ibdata1, ib_logfile*, mysql/, and your database directories all have to be there.

Point MariaDB at the new path with a drop-in, not by editing a packaged file that apt will replace:

ini
# /etc/mysql/mariadb.conf.d/96-datadir.cnf
[mysqld]
datadir = /mnt/mysql-data

Update AppArmor. The typical Ubuntu profile is /etc/apparmor.d/usr.sbin.mariadbd or usr.sbin.mysqld. Add the new path with r, w, k, and a trailing rule for the directory contents. Then:

bash
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.mariadbd
sudo systemctl start mariadb
sudo systemctl is-active mariadb
mariadb -e "SHOW VARIABLES LIKE 'datadir'; SHOW ENGINE INNODB STATUS;"

If the unit fails, read journalctl -u mariadb -n 80 before you start editing randomly. The usual three: AppArmor denied, datadir not owned by mysql, or fstab did not mount and you started against an empty directory. An empty datadir will initialize a new, blank instance and look like "my data vanished." That is why you confirm the mount before start, and why you keep the old /var/lib/mysql until you have survived a reboot.

Survive a reboot before you delete the old copy

Reboot the VPS. Confirm /mnt/mysql-data is mounted, mariadb is active, datadir is the new path, and a COUNT on a known table matches the dump. Only then rename /var/lib/mysql to /var/lib/mysql.bak. Keep the bak for a few days. Disk space is cheaper than a restore.

Binlogs can stay on the root volume or move with the datadir; do not split them across filesystems unless you have a reason. If log_error still points at /var/log/mysql, leave it. Logs on the root volume make it easier to diagnose a datadir disk that will not mount.

systemd ProtectHome and ProtectSystem in override units can also block a custom path. If you added hardening drop-ins, ReadWritePaths must include /mnt/mysql-data.

Do this in a window. The copy time is your downtime for a physical move, unless you built a replica and switched. For a 20 GB datadir on High-Speed SSD the copy is usually minutes, not hours, but measure once with rsync -a --dry-run and a stopwatch on a similar size before you promise the business a number.

move datadir without a blank instance dump first escape hatch stop mysqld clean InnoDB rsync -aHAX mysql:mysql AppArmor new path rules reboot test then drop bak empty mount plus start = new blank datadir confirm UUID in fstab and SHOW VARIABLES datadir keep /var/lib/mysql.bak until after reboot

A dedicated High-Speed SSD for the datadir is extra room and a cleaner failure domain, not a different backup story. Stop, copy, confine, reboot, then delete the old tree. When you need a second disk on a Lucknow VPS, attach it from the Netbay dashboard and follow the same sequence — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance