#!/usr/bin/awk -f
BEGIN {
dump_current_db = 0;
num_db = split(databases, db_arr, ",")
for (i = 1; i <= num_db; i++) {
db_arr[i] = "`" db_arr[i] "`";
}
}
/^\-\-/ {
print $0;
if ($2 == "Current" && $3 == "Database:") {
dump_current_db = 0;
for (i = 1; i <= num_db; i++) {
if ($4 == db_arr[i]) {
dump_current_db = 1;
break;
}
}
}
}
/^\/\*.+\*\/;/ { print $0 }
/^$/ { print $0 }
/^[^\-]/ { if (dump_current_db == 1) print $0 }
このawkスクリプトを例えばcut-database.awkとかに保存して、
shell> ./cut-database -v databases=db1,db2,db3... < dump.sql > sub_dump.sqlてな具合にコマンドを起動すれば、目的のデータベースだけを含んだダンプファイルがいっちょあがり。 そもそもmysqldumpコマンドでダンプするときにファイルを分ければ?なんて考える人も居るかも知れないけど、それは出来ない相談だったりする。ロールフォワードリカバリとかを考えてバイナリログと同期をとっておかないといけなかったりするし、そもそもデータベースが複数あるときにはデータベース間でデータが同期していないといけない。ところがデータベースを個別にダンプするとロールフォワードリカバリが出来ないどころか、データが使い物にならないことになってしまう。よって--all-databasesとか--databasesの利用は必須なのである。 そこでもう一つ紹介するのが、mysqldumpコマンドの出力をそのまま別々のファイルに保存するawkスクリプト。
#!/usr/bin/awk -f
function is_new_db(db_name) {
for (i = 1; i <= num_db; i++) {
if (db_name == db[i]) {
return 0;
}
}
return 1;
}
BEGIN {
num_db = 0
num_prelines = 0
num_postlines = 0
current_file = "/dev/null"
}
/^\-\-/ {
if ($2 == "Current" && $3 == "Database:") {
close(current_file);
db_name = $4
gsub("`", "", db_name);
current_file = db_name ".sql";
if (is_new_db(db_name)) {
db[++num_db] = db_name;
print "--\n" $0 "\n--\n" > current_file;
for (i = 1; i <= num_prelines; i++)
print prelines[i] >> current_file;
}
} else if (num_db == 0) {
num_prelines++;
prelines[num_prelines] = $0;
} else if ($2 == "Dump" && $3 == "completed") {
num_postlines++;
postlines[num_postlines] = "";
num_postlines++;
postlines[num_postlines] = $0;
} else {
print $0 >> current_file
}
next;
}
/^\/\*.+\*\/;/ {
if (match($0, "character|collation")) {
print $0 >> current_file;
} else if (match($0, "SET")) {
if (num_db == 0) {
if (match(prelines[num_prelines], "^\-\-")) {
num_prelines++;
prelines[num_prelines] = "";
}
num_prelines++;
prelines[num_prelines] = $0;
} else {
num_postlines++;
postlines[num_postlines] = $0;
}
} else {
print $0 >> current_file;
}
next;
}
{ print $0 >> current_file }
END {
for (i = 1; i <= num_db; i++) {
current_file = db[i] ".sql";
print "" >> current_file
for (j = 1; j <= num_postlines; j++) {
print postlines[j] >> current_file;
}
}
}
このスクリプトを例えばseparate-dump.awkというファイルに保存して実行権限を与えてやれば、
shell> mysqldump -A --single-transaction --master-data=2 --flush-logs | ./separate-dump.awkという具合にこのコマンドを使うことができる。そうするとカレントディレクトリに「データベース名.sql」というファイルにダンプが分けられて保存されるという寸法。
shell> ./separate-dump.awk < dump.sql
なお、このスクリプトの利用は自己責任でお願いします。ライセンスはGPLv3で。何か不具合等があれば直して使って下さい。







1 コメント:
「cut-database.awk」便利です、ありがとうございます。
コメントを投稿