##概要
RDSにオンプレのMySQLのデータをインポートするために、mysqldumpコマンドの出力を使うことがある。データベース単位でダンプする方法については、ドキュメントにも記載されているが、ちょっとめんどい時がある。
そこで、スクリプトで必要なデータベースを全部持ってくる(mysqlデータベース等が含まれないように)ようにすればいいのだが、viewも持ってきたい!みたいな要件がある場合、RDSでは下記のようなことを考える必要がある。
##簡単な設計メモ
とりあえず今回は、不要なデータベースをダンプする際に外す、DEFINERを変更する二点を検討した。今のところは、これで必要なデータベースを抜き出して、インポートすることができた。
具体的には以下の2つを実装して検証した。
- mysql、information_schema、performance_schema、innodbデータベースをダンプ対象から外す
- DEFINERにCURRENT_USERを指定するようにする。
##ソースコード
ダンプファイルを指定したら、そのファイルに加工されたsqlが出力されるようにしてみた。
# ruby mysql-rds-dump.rb [--dumpfile dumpfile] [-h hostname] [-u username] [-p password] [-s socket]
mysql-rds-dump.rb
require 'optparse'
require 'mysql'
# ruby mysql-rds-dump.rb [--dumpfile dumpfile] [-h hostname] [-u username] [-p password] [-s socket]
ignore_databases = ["mysql", "information_schema", "performance_schema", "innodb"]
options = {}
opt = OptionParser.new
opt.on("-d VALUE", "--dumpfile VALUE", 'dumpfile') do |v|
options[:dumpfile] = v
end
opt.on("-h VALUE", '--hostname VALUE', 'hostname') do |v|
options[:hostname] = v
end
opt.on("-u VALUE", '--username VALUE', 'username') do |v|
options[:username] = v
end
opt.on("-p VALUE", '--password VALUE', 'password') do |v|
options[:password] = v
end
opt.on("-s VALUE", '--socket VALUE', 'socket') do |v|
options[:socket] = v
end
opt.parse!(ARGV)
if File.exist?(options[:dumpfile])
puts "#{options[:dumpfile]} already exists..."
abort
end
con = Mysql.new(options[:hostname], options[:username], options[:password], nil, nil, options[:socket])
res = con.query('SHOW DATABASES')
res.each do |databases|
if !ignore_databases.include?(databases[0])
`mysqldump -h#{options[:hostname]} -u#{options[:username]} -p#{options[:password]} --socket #{options[:socket]} --single-transaction --compress --order-by-primary --no-autocommit --databases #{databases[0]} >> #{options[:dumpfile]}`
end
end
File.open(options[:dumpfile], "r") do |inf|
buf = inf.read
buf.gsub!(/DEFINER=\`.*\`@\`.*\`/, "DEFINER=CURRENT_USER")
File.open(options[:dumpfile], "w") do |outf|
outf.write(buf)
end
end
con.close