按数据库拆分具有多个数据库的 mysqldump 文件
Posted
技术标签:
【中文标题】按数据库拆分具有多个数据库的 mysqldump 文件【英文标题】:Split up a mysqldump file with multiple databases, by database 【发布时间】:2010-12-25 00:10:53 【问题描述】:我有一个包含多个数据库的 mysqldump 文件 (5)。其中一个数据库需要很长时间才能加载,有没有办法按数据库拆分 mysqldump 文件,或者只告诉 mysql 只加载指定的数据库之一?
马尼什
【问题讨论】:
查看适用于 Windows/linux 的解决方案:***.com/questions/132902/… 【参考方案1】:这个 Perl 脚本应该可以解决问题。
#!/usr/bin/perl -w
#
# splitmysqldump - split mysqldump file into per-database dump files.
use strict;
use warnings;
my $dbfile;
my $dbname = q;
my $header = q;
while (<>)
# Beginning of a new database section:
# close currently open file and start a new one
if (m/-- Current Database\: \`([-\w]+)\`/)
if (defined $dbfile && tell $dbfile != -1)
close $dbfile or die "Could not close file!"
$dbname = $1;
open $dbfile, ">>", "$1_dump.sql" or die "Could not create file!";
print $dbfile $header;
print "Writing file $1_dump.sql ...\n";
if (defined $dbfile && tell $dbfile != -1)
print $dbfile $_;
# Catch dump file header in the beginning
# to be printed to each separate dump file.
if (! $dbname) $header .= $_;
close $dbfile or die "Could not close file!"
为包含所有数据库的转储文件运行此命令
./splitmysqldump < all_databases.sql
【讨论】:
经过一段时间处理后,我收到此脚本的错误:不能在 ./splitmysqldump 第 34 行, 第 188681 行使用未定义的值作为符号引用。【参考方案2】:或者,可以将每个数据库直接保存到单独的文件中...
#!/bin/bash
dblist=`mysql -u root -e "show databases" | sed -n '2,$ p'`
for db in $dblist; do
mysqldump -u root $db | gzip --best > $db.sql.gz
done
【讨论】:
使用mysql --batch --skip-column-names
代替 sed
机器可解析的输出。 (reference)【参考方案3】:
这是一篇很棒的博文,我总是会参考mysqldump
来做这种事情。
http://gtowey.blogspot.com/2009/11/restore-single-table-from-mysqldump.html
您可以轻松扩展它以提取单个数据库。
【讨论】:
不鼓励仅提供链接的答案,也请在此处发布链接的要点!【参考方案4】:我一直在研究一个 python 脚本,它将一个大的转储文件拆分成小的转储文件,每个数据库一个。它的名字是 dumpsplit,这里是一个划痕:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys
import re
import os
HEADER_END_MARK = '-- CHANGE MASTER TO MASTER_LOG_FILE'
FOOTER_BEGIN_MARK = '\/\*\!40103 SET TIME_ZONE=@OLD_TIME_ZONE \*\/;'
DB_BEGIN_MARK = '-- Current Database:'
class Main():
"""Whole program as a class"""
def __init__(self,file,output_path):
"""Tries to open mysql dump file to call processment method"""
self.output_path = output_path
try:
self.file_rsrc = open(file,'r')
except IOError:
sys.stderr.write('Can\'t open %s '+file)
else:
self.__extract_footer()
self.__extract_header()
self.__process()
def __extract_footer(self):
matched = False
self.footer = ''
self.file_rsrc.seek(0)
line = self.file_rsrc.next()
try:
while line:
if not matched:
if re.match(FOOTER_BEGIN_MARK,line):
matched = True
self.footer = self.footer + line
else:
self.footer = self.footer + line
line = self.file_rsrc.next()
except StopIteration:
pass
self.file_rsrc.seek(0)
def __extract_header(self):
matched = False
self.header = ''
self.file_rsrc.seek(0)
line = self.file_rsrc.next()
try:
while not matched:
self.header = self.header + line
if re.match(HEADER_END_MARK,line):
matched = True
else:
line = self.file_rsrc.next()
except StopIteration:
pass
self.header_end_pos = self.file_rsrc.tell()
self.file_rsrc.seek(0)
def __process(self):
first = False
self.file_rsrc.seek(self.header_end_pos)
prev_line = '--\n'
line = self.file_rsrc.next()
end = False
try:
while line and not end:
if re.match(DB_BEGIN_MARK,line) or re.match(FOOTER_BEGIN_MARK,line):
if not first:
first = True
else:
out_file.writelines(self.footer)
out_file.close()
if not re.match(FOOTER_BEGIN_MARK,line):
name = line.replace('`','').split()[-1]+'.sql'
print name
out_file = open(os.path.join(self.output_path,name),'w')
out_file.writelines(self.header + prev_line + line)
prev_line = line
line = self.file_rsrc.next()
else:
end = True
else:
if first:
out_file.write(line)
prev_line = line
line = self.file_rsrc.next()
except StopIteration:
pass
if __name__ == '__main__':
Main(sys.argv[1],sys.argv[2])
【讨论】:
【参考方案5】:就像 Stano 建议的那样,最好的办法是在转储时使用类似...
mysql -Ne "show databases" | grep -v schema | while read db; do mysqldump $db | gzip > $db.sql.gz; done
当然,这取决于是否存在带有
的 ~/.my.cnf 文件[client]
user=root
password=rootpass
否则只需在 mysql 和 mysqldump 调用中使用 -u 和 -p 参数定义它们:
mysql -u root -prootpass -Ne "show databases" | grep -v schema | while read db; do mysqldump -u root -prootpass $db | gzip > $db.sql.gz; done
希望对你有帮助
【讨论】:
这是最好的,因为不需要创建任何文件。只需粘贴并更改合适的配置即可运行。最适合寻求快速单班轮解决方案的任何人。【参考方案6】:“mysqldump 文件”只是一个包含 SQL 语句的文本文件。因此,您可以使用任何类型的文本编辑器来将其拆分成您认为合适的方式。
首先进行更具选择性的转储(每个文件只有一个数据库等)可能会更好地为您服务。如果您无权访问原始数据库,也可以进行完全还原,然后再次使用 mysqldump 为各个数据库创建转储。
如果您只想要一个快速而肮脏的解决方案,快速的 google 搜索会产生对 couple tools 的引用,这也可能有用。
【讨论】:
【参考方案7】:我可能会分步进行转储和重新加载:
-
使用 --no-data 对表结构进行转储,每个数据库都有转储。
在新服务器中创建结构
在每个数据库级别使用 --no-create-info 获取表的数据转储
现在,与每个数据库的转储一样,如果某些特定文件很大,我甚至可以使用剪切文件拆分文件。
注意:如果您使用的是 MyISAM 表,您可以在第 4 步中禁用索引评估并稍后重新启用它以加快插入速度。
【讨论】:
以上是关于按数据库拆分具有多个数据库的 mysqldump 文件的主要内容,如果未能解决你的问题,请参考以下文章