Restoring A MySQL Dump To RDS
I’ve spent some of today migrating a MySQL database instance into RDS from another RDS instance in a separate AWS account as part of a larger piece of work. However, there were a few gotchas that caught me out, so it’s worth keeping the following in mind if you’re having issues.
To avoid needing to keep typing the MySQL password, it’s a good idea to
export MYSQL_PWD=<your password>
A first attempt might be a standard mysqldump
command such as the following:
mysqldump -h <host> -uroot --all-databases > dump.sql
However, in this case the database will contain the mysql
schema, and perhaps others, which you probably won’t need.
You can fix that by being explicit about which tables you are not interested in:
DATABASE_LIST=$(mysql -NBe 'show schemas' -h <host> -uroot | \
egrep -v "information_schema|innodb|mysql|performance_schema" | \
tr "\n" " ");
mysqldump -h <host> -uroot --databases ${DATABASE_LIST} > dump.sql
This is heading in the right direction, but when you restore from this backup you might see an error similar to the one below:
Got error: 1142: SELECT,LOCK TABL command denied to user ‘root’@'localhost’
for table ‘cond_instances’ when using LOCK TABLE
So we need to add the --skip-lock-tables
option.
The next problem came when trying to restore the various triggers, functions and stored procedures in the database. I should RTFM more, but by default triggers are included in a mysqldump, but stored procedures are not. This needs to be made explicit with something like:
mysqldump -h <host> -uroot --skip-lock-tables \
--databases ${DATABASE_LIST} \
--add-drop-database \
--triggers \
--routines \
--events > dump.sql
Great, that should be everything, right? Wrong. MySQL requires certain elevated permissions to perform operations such as creating stored procedures. RDS doesn’t permit the granting of the SUPER privilege. Some of this can be mitigated by adding the following to your RDS Database Parameter Group:
log_bin_trust_function_creators = 1
But that’s only half the battle. The backup file actually contains stored procedure definitions. These definitions
include the user who the stored procedure should be created by, the DEFINER. Since mysqldump
doesn’t handle
migrating users and grants, the DEFINER doesn’t exist at the time of restoring, so an error is raised. We can remove
the DEFINER using sed or Perl and create the stored procedure with the user who is performing the restore.
perl -pe 's/\sDEFINER=`[^`]+`@`[^`]+`//' < dump.sql > dump.fixed.sql
With these adjustments, the backup should restore without error. Of course, the users and their permissions are missing.
We can get a list of all user and host combinations with
mysql -h <host> -uroot -B -N -e "select user, host FROM user"
Then for each of these combinations, we can extract the grants and append them to a file for later import into MySQL:
mysql -h <host> -uroot -B -N -e "SHOW GRANTS FOR ‘<user>’@‘<host>'" >> users.sql
Hope this proves useful to others, but it’ll certainly be a brain dump I’ll refer to in the future.