Databases grow over time, sometimes outgrowing the space on the file system. You can also run into I/O contention when they’re located on the same partition as the rest of the operating system. RAID, network block storage, and other devices can offer redundancy and other desirable features. Whether you’re adding more space, evaluating ways to optimize performance, or looking to take advantage of other storage features, this tutorial will guide you through relocating MySQL’s data directory.
The directions here are suitable for servers that run a single instance of MySQL. If you have multiple instances, the guide How To Move a MySQL Data Directory to a New Location on Ubuntu 16.04 can help you with directions for explicitly changing the location through configuration settings.
To complete this guide, you will need:
An Ubuntu 16.04 server with a non-root user with
sudo privileges. You can learn more about how to set up a user with these privileges in our Initial Server Setup with Ubuntu 16.04 guide.
A MySQL server. If you haven’t already set one up, the How To Install MySQL on Ubuntu 16.04 guide can help you.
A Backup of your databases. Unless you’re working with a fresh installation of MySQL, you should ensure that you have a backup of your data. The guide How To Backup MySQL Databases on an Ubuntu VPS can help you with this.
In this example, we’re moving the data to a block storage device mounted at
/mnt/volume-nyc1-01. You can learn how to set one up in the How To Use Block Storage on DigitalOcean guide.
No matter what underlying storage you use, this guide can help you move the data directory to a new location.
To ensure the integrity of the data, we’ll shut down MySQL:
- sudo systemctl stop mysql
systemctl doesn’t display the outcome of all service management commands, so if you want to be sure you’ve succeeded, use the following command:
- sudo systemctl status mysql
You can be sure it’s shut down if the final line of the output tells you the server is stopped:
Output. . . Jul 18 11:24:20 ubuntu-512mb-nyc1-01 systemd: Stopped MySQL Community Server.
With the server shut down, we’ll move the existing database directory to the new location:
- sudo mv /var/lib/mysql /mnt/volume-nyc1-01/mysql
Next, we’ll create the symbolic link:
- sudo ln -s /mnt/volume-nyc1-01/mysql /var/lib/mysql
With the symlink in place, this seems like the right time to bring up MySQL again, but there’s one more thing to configure before we can do that successfully.
When you move the MySQL directory to a different file system than the MySQL server, you will need to create an AppArmor alias.
To add the alias, edit the AppArmor
- sudo nano /etc/apparmor.d/tunables/alias
At the bottom of the file, add the following alias rule:
. . . [label /etc/apparmor.d/tunables/alias] alias /var/lib/mysql/ -> /mnt/volume-nyc1-01/mysql/, . . .
For the changes to take effect, restart AppArmor:
- sudo systemctl restart apparmor
If you skipped the AppArmor configuration step and tried to start
mysql, you would run into the following error message:
OutputJob for mysql.service failed because the control process exited with error code. See "systemctl status mysql.service" and "journalctl -xe" for details.
The output from both
journalctl concludes with:
OutputJul 18 11:03:24 ubuntu-512mb-nyc1-01 systemd: mysql.service: Main process exited, code=exited, status=1/FAILURE
Since the messages don’t make an explicit connection between AppArmor and the data directory, this error can take some time to figure out. However, a look at the
syslog will show the problem:
- sudo tail /var/log/syslog
OutputNov 24 00:03:40 digitalocean kernel: [ 437.735748] audit: type=1400 audit(1479945820.037:20): apparmor="DENIED" operation="mknod" profile="/usr/sbin/mysqld" name="/mnt/volume-nyc1-01/mysql/mysql.lower-test" pid=4228 comm="mysqld" requested_mask="c" denied_mask="c" fsuid=112 ouid=112
Now we’re ready to start MySQL.
- sudo systemctl start mysql
- sudo systemctl status mysql
Once you’ve restarted MySQL, take the opportunity to ensure that your data is in order and that MySQL is functioning as expected.
In this tutorial, we’ve moved MySQL’s data and used a symlink to make MySQL aware of the new location. We’ve also updated Ubuntu’s AppArmor ACLs to accommodate the adjustment. Although we were using a Block Storage device, the instructions here should be suitable for redefining the location of the data directory regardless of the underlying technology.
This approach is only suitable if you are running a single instance of MySQL. If you need to support multiple MySQL instances running on a single server, How To Move a MySQL Data Directory to a New Location on Ubuntu 16.04 can help you.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
Join our DigitalOcean community of over a million developers for free! Get help and share knowledge in our Questions & Answers section, find tutorials and tools that will help you grow as a developer and scale your project or business, and subscribe to topics of interest.Sign up now
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
This comment has been deleted
Not going to lie. I figured out how to make the mysql data folder onto another disk just today. I just mounted the disk under /var/lib/mysql and it seems to have done the trick. I added the information to the /etc/fstab file and now the disk will be mounted every time. I thought about doing a link to a MySQL Dump but I did not know the full impact of what was going on at the time.
I’ve done something like this by mount bind, and I think there is no need to do additional AppArmor config in this case.