MySQL Backups

18 October 2016

MySQL is pretty nice for a free, Open Source RDBMS. Before trying any kind of management, you should totally have a .my.cnf file in your ~. Put your username and password for localhost there, and then remove read permissions from everyone but yourself. This file specifies the default options to use with MySQL command line tools, making them much easier to work with, and avoiding having to repeatedly type in your password or accidentally letting it end up in a history file somewhere.

[client]
user=root
password=letmein

Flexible backups with mysqldump

The mysqldump tool is fairly straightforward, but you’re likely not using it to it’s full potential.

To make working with your export easier (making structure adjustments and such), it’s often useful to export the schema and data separately. A --no-data dump will include table schemas and view declarations, while a --no-create-info backup will only include table data.

mysqldump --no-data dbname | gzip > dbname-schema.sql.gz
mysqldump --no-create-info dbname | gzip > dbname.sql.gz

If you plan on changing your column ordering or adding columns from your schema file, your inserts in the data backup will no longer import correctly. To work around this, you can use the --complete-insert flag, which includes column names in the inserts, ensuring they restore properly as long as all the columns backed up are still present in the new table.

mysqldump --complete-insert --no-create-info dbname | gzip > dbname.sql.gz

Restoring views to a new server can fail if the view’s DEFINER is not a user on the new system. If you’re going to be importing the database on a different system with potentially different users, you can use grep to filter out the DEFINER rows, ensuring views import without errors.

mysqldump --no-data dbname | grep -v "50013 DEFINER" | gzip > dbname-schema.sql.gz

I pretty much always pipe mysqldump through gzip since there’s no good reason to keep an uncompressed export sitting around. Restoring gzipped backups is very simple to do in-place with the help of zcat.

zcat dbname-schema.sql.gz | mysql dbname
zcat dbname.sql.gz | mysql dbname

If you’ve got any stored procedures, triggers, or functions in your database, these will only be backed up if you use the --routines flag. I prefer to keep these in another file.

mysqldump --routines --no-data --no-create-info dbname | gzip > dbname-routines.sql.gz

If you’re using BLOB columns with unfiltered data, you may run into issues restoring backups of that data. To work around this, you can store those in hexadecimal which, while larger by default, shouldn’t take up too much more space once gzipped. Enable hex encoding with the --hex-blob flag.

mysqldump --hex-blob --no-create-info dbname | gzip > dbname.sql.gz

If your database consists entirely of InnoDB tables, you have the option of using a transactional backup, which ensures data integrity without requiring table-level locks! This can be enabled with the --single-transaction flag, but keep in mind any non-InnoDB tables will not be locked, and may be backed up inconsistently.

mysqldump --single-transaction --no-create-info dbname | gzip > dbname.sql.gz

Multi-threaded backups with mydumper

If all you’re looking for is a crazy-fast backup of a large database’s structure and data, you should be using the amazing mydumper tool, which uses a multi-threaded approach, backing up each table in a separate thread.

It’s fairly straightforward to use. Let’s do a gzip-compressed single-database backup.

mydumper -c -B dbname -d export_dir

Restoring a mydumper backup is quite simple

myloader -d export_dir

Mydumper also has powerful options like regex table name matching and row-count file splitting. Read the man page for details on everything mydumper and mysqldump can do.