Notes on Moving Large Databases
March 6, 2019
NOTES
- by default, when you do a
mysqldump, it locks the tables. You can change that by passing--lock-tables=falseas a parameter. - take differential backups every day and full backups every week.
- don't have to sit and look at the Terminal screen and wait and wait.. Write a script, run it wth
cron - 36.56 GB database took 21 minues to backup, without any
gzipcompression.. You can use thetimecommand to find out how long it took. The backup file was 21GB in size. - 20.62 GB database took 12 minutes to backup, without any compression. Resulting file was 11 GB in size
- use
rsyncinstead ofscp.scpgets stalled.rsynccopies faster. use the-Pflag to see progress and the ability to pause/resume file transfers - the server where these tests were done had the following specs: 2GB RAM, 2 vCPUs, 160GB HDD, 10MBps network link
Exporting
mysqldump --user=XXX --password=XXX --single-transaction --routines --triggers --quick --all-databases > XXX.sql
--single-transactiononly works with InnoDB, let's you backup data without blocking any applications. The--single-transactionoption and the--lock-tablesoption are mutually exclusive--routinescopies stored procedures and functions--triggersInclude triggers for each dumped table. A trigger is a named database object that is associated with a table, and that activates when a particular event occurs for the table. Some uses for triggers are to perform checks of values to be inserted into a table or to perform calculations on values involved in an update.--quickforces mysqldump to retrieve rows for a table from the server a row at a time rather than retrieving the entire row set and buffering it in memory before writing it out.- To dump large tables, combine the
--single-transactionoption with the--quickoption - To include stored routines and events in a dump made using
--all-databases, use the--routinesand--eventsoptions explicitly. - The
performance_schemadatabase, is not dumped even with the--all-databasesoption. You can mention it explicitly with the--databasesoption. - By default, it'll lock tables when you dump, so be careful of using either
--single-transactionor--skip-lock-tablesoption when moving live databases.
Get only stored procedures and table structure, but no data
Use the --no-data (or -d) flag to not dump table data. It'll only dump the CREATE TABLE statement for the table (for example, to create an empty copy of the table by loading the dump file)
mysqldump --user=XXX --password=XXX --no-data --routines --events XXX > dump-defs.sql
Sizes
| Database Size | Backup Size (.sql) | Compressed Size (.sql.gz) |
|---|---|---|
| 36.56 GB | 21 GB | 4.0 GB |
| 20.62 GB | 11 GB | 2.4 GB |
Creating the backups
# 36.56 GB input > 21 GB output file
time mysqldump -uroot -p --databases foo > bak_foo.sql
Enter password:
real 21m3.347s
user 5m21.110s
sys 1m26.830s
# 20.62 GB input > 11 GB output file
time mysqldump -uroot -p bar > bak_bar.sql
Enter password:
real 12m40.238s
user 2m36.310s
sys 0m37.380s
Compressng the backups
- Using
gzipcompresses the original file. Meaning it won't say the compressed backup.sql.gzas a separate file and you lose the original.sqlfile.
# 11 GB input file > 2.4 GB
time gzip -9 bak_bar.sql
real 20m30.855s
user 17m8.170s
sys 0m14.760s
- Compressing a 36GB
.sqlfile resulted in a 4GB.sql.gzfile
Uncompressing the backups
- 2.4 GB took 2.4 minutes to extract. (An average of 1 GB per minute).
- Uncompressing the backup gets rid of the original
.sql.gzfile.
time gunzip bar.sql.gz
real 2m4.765s
user 1m22.872s
sys 0m12.850s
Importing the backups
The database you import should already exist. When using --databases, CREATE DATABASE and USE statements are included in the output before each new database.
CREATE DATABASE foo;
# uncompressed .sql file
mysql -uroot -p DBNAME < BAKFILE.sql
# compressed .sql.gz file
pv mydump.sql.gz | gunzip | mysql -u root -p
pv lets you monitor the progress of data through a pipe, meaning you'll see a progress bar!
-- Open the console and start the interactive MySQL mode
USE <name_of_your_database>;
SOURCE <path_of_your_.sql>;
Moving /var/lib/mysql
Another way of moving the databases (plus users and permissions), is to sync the entire MySQL data directory (default is /var/lib/mysql defined in /etc/mysql/mysql.conf.d/mysqld.cnf) to the new server.
You can also find out what directory it is with
SELECT @@datadir;
rsync -vPhaze "ssh -i /root/.ssh/id_rsa -p ${REMOTE_PORT}" ${REMOTE_USER}@${REMOTE_HOST}:/var/lib/mysql/ /var/lib/mysql/ &>> ${LOGFILE}
Here's a [bash script][1] for achieving this that also logs the progress. Run this script via Cron so that you don't end up being stuck sitting in front of a Terminal
crontab -e