我需要将整个表从一个MySQL数据库移动到另一个MySQL数据库。我没有完全访问第二个,只有phpMyAdmin访问。我只能上传(压缩)小于2MB的sql文件。但是第一个数据库表的mysqldump的压缩输出大于10MB。
有没有办法将mysqldump的输出拆分成较小的文件?我不能使用split(1),因为我不能将文件cat(1)重新放回远程服务器上。
还是我错过了另一种解决方案吗?
修改
第一张海报建议的mysqldump的--extended-insert = FALSE选项产生一个.sql文件,然后可以将其拆分为可导入文件,前提是使用合适的--lines选项调用split(1)。经过反复试验,我发现bzip2将.sql文件压缩了20倍,所以我需要弄清楚有多少行sql代码大致相当于40MB。
答案 0 :(得分:34)
此bash脚本将一个数据库的转储文件拆分为每个表的单独文件,并使用csplit命名,并相应地命名它们:
#!/bin/bash
####
# Split MySQL dump SQL file into one file per table
# based on https://gist.github.com/jasny/1608062
####
#adjust this to your case:
START="/-- Table structure for table/"
# or
#START="/DROP TABLE IF EXISTS/"
if [ $# -lt 1 ] || [[ $1 == "--help" ]] || [[ $1 == "-h" ]] ; then
echo "USAGE: extract all tables:"
echo " $0 DUMP_FILE"
echo "extract one table:"
echo " $0 DUMP_FILE [TABLE]"
exit
fi
if [ $# -ge 2 ] ; then
#extract one table $2
csplit -s -ftable $1 "/-- Table structure for table/" "%-- Table structure for table \`$2\`%" "/-- Table structure for table/" "%40103 SET TIME_ZONE=@OLD_TIME_ZONE%1"
else
#extract all tables
csplit -s -ftable $1 "$START" {*}
fi
[ $? -eq 0 ] || exit
mv table00 head
FILE=`ls -1 table* | tail -n 1`
if [ $# -ge 2 ] ; then
mv $FILE foot
else
csplit -b '%d' -s -f$FILE $FILE "/40103 SET TIME_ZONE=@OLD_TIME_ZONE/" {*}
mv ${FILE}1 foot
fi
for FILE in `ls -1 table*`; do
NAME=`head -n1 $FILE | cut -d$'\x60' -f2`
cat head $FILE foot > "$NAME.sql"
done
rm head foot table*
基于https://gist.github.com/jasny/1608062
和https://stackoverflow.com/a/16840625/1069083
答案 1 :(得分:29)
首先转储架构(它肯定适合2Mb,不是吗?)
mysqldump -d --all-databases
并恢复它。
之后只将数据转储到单独的insert语句中,这样就可以拆分文件并将其恢复,而无需在远程服务器上连接它们
mysqldump --all-databases --extended-insert=FALSE --no-create-info=TRUE
答案 2 :(得分:11)
您说您无权访问第二台服务器。但是,如果您具有对表所在的第一台服务器的shell访问权限,则可以按表拆分转储:
for T in `mysql -N -B -e 'show tables from dbname'`; \
do echo $T; \
mysqldump [connecting_options] dbname $T \
| gzip -c > dbname_$T.dump.gz ; \
done
这将为每个表创建一个gzip文件。
将mysqldump的输出拆分为单独文件的另一种方法是使用--tab选项。
mysqldump [connecting options] --tab=directory_name dbname
其中 directory_name 是空目录的名称。 此命令为每个表创建一个.sql文件,其中包含CREATE TABLE语句,以及一个包含要使用LOAD DATA INFILE还原的数据的.txt文件。我不确定phpMyAdmin是否可以使用您的特定限制来处理这些文件。
答案 3 :(得分:9)
迟到的回复,但正在寻找相同的解决方案,并从以下网站获得以下代码:
for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip > "$I.sql.gz"; done
http://www.commandlinefu.com/commands/view/2916/backup-all-mysql-databases-to-individual-files
答案 4 :(得分:4)
我最近创建了sqlsplit.com。尝试一下。
答案 5 :(得分:4)
有一个非常好的mysqldumpsplitter脚本,它提供了大量的选项,用于从mysqldump中提取。
我会在这里复制食谱,从中选择你的案例:
1)从mysqldump中提取单个数据库:
sh mysqldumpsplitter.sh --source filename --extract DB --match_str database-name
上面的命令将为指定的数据库创建sql "文件名" sql文件并以压缩格式存储到 数据库name.sql.gz。
2)从mysqldump中提取单个表:
sh mysqldumpsplitter.sh --source filename --extract TABLE --match_str table-name
上面的命令将为指定的表创建sql "文件名" mysqldump文件并以压缩格式存储到 数据库name.sql.gz。
3)从mysqldump中提取与正则表达式匹配的表:
sh mysqldumpsplitter.sh --source filename --extract REGEXP --match_str regular-expression
上面的命令将为匹配指定常规的表创建sqls 表达式来自指定"文件名" mysqldump文件并将其存储在 压缩格式为单个table-name.sql.gz。
4)从mysqldump中提取所有数据库:
sh mysqldumpsplitter.sh --source filename --extract ALLDBS
上面的命令将从指定的"文件名"中提取所有数据库。 mysqldump文件并以压缩格式存储到个人 数据库name.sql.gz。
5)从mysqldump中提取所有表:
sh mysqldumpsplitter.sh --source filename --extract ALLTABLES
上面的命令将从指定的" filename"中提取所有表。 mysqldump文件并以压缩格式存储到个人 表name.sql.gz。
6)从mysqldump中提取表格列表:
sh mysqldumpsplitter.sh --source filename --extract REGEXP --match_str '(table1|table2|table3)'
上面的命令将从指定的"文件名"中提取表格。 mysqldump文件并以压缩格式存储到个人 表name.sql.gz。
7)从压缩的mysqldump中提取数据库:
sh mysqldumpsplitter.sh --source filename.sql.gz --extract DB --match_str 'dbname' --decompression gzip
上面的命令将使用gzip,extract解压缩filename.sql.gz 数据库名为" dbname"来自" filename.sql.gz" &安培;把它存储为 出/ dbname.sql.gz
8)在未压缩的压缩文件中从压缩的mysqldump中提取数据库 格式:
sh mysqldumpsplitter.sh --source filename.sql.gz --extract DB --match_str 'dbname' --decompression gzip --compression none
上面的命令将使用gzip和extract解压缩filename.sql.gz 数据库名为" dbname"来自" filename.sql.gz" &安培;将它存储为普通的sql 出/ dbname.sql
9)从不同文件夹中的mysqldump中提取alltables:
sh mysqldumpsplitter.sh --source filename --extract ALLTABLES --output_dir /path/to/extracts/
上面的命令将从指定的" filename"中提取所有表。 mysqldump文件并以压缩格式将表提取到个人 文件,table-name.sql.gz存储在/ path / to / extracts /下。剧本 将创建文件夹/ path / to / extracts /如果不存在。
10)在完全转储中从一个数据库中提取一个或多个表:
考虑到你有一个包含多个数据库的完整转储 从一个数据库中提取几个表。
提取单个数据库:
sh mysqldumpsplitter.sh --source filename --extract DB --match_str DBNAME --compression none
提取所有表
sh mysqldumpsplitter.sh --source out/DBNAME.sql --extract REGEXP --match_str "(tbl1|tbl2)"
虽然我们可以使用其他选项在单个命令中执行此操作,如下所示:
sh mysqldumpsplitter.sh --source filename --extract DBTABLE --match_str "DBNAME.(tbl1|tbl2)" --compression none
上面的命令将从DBNAME数据库中提取tbl1和tbl2 文件夹下的sql格式" out"在当前目录中。
您可以按如下方式提取单个表格:
sh mysqldumpsplitter.sh --source filename --extract DBTABLE --match_str "DBNAME.(tbl1)" --compression none
11)从特定数据库中提取所有表:
mysqldumpsplitter.sh --source filename --extract DBTABLE --match_str "DBNAME.*" --compression none
上面的命令将从sql中的DBNAME数据库中提取所有表 格式并存储在" out" 。目录
12)列出mysqldump文件的内容
mysqldumpsplitter.sh --source filename --desc
上面的命令将列出转储文件中的数据库和表。
您可以稍后选择加载文件:zcat filename.sql.gz | mysql -uUSER -p -hHOSTNAME
一旦你提取了你认为仍然更大的单个表,你可以使用带有行数的linux split命令来进一步拆分转储。
split -l 10000 filename.sql
那就是说,如果这是你的需要(经常出现),你可以考虑使用mydumper实际创建你不需要拆分的单个转储!
答案 6 :(得分:2)
您不需要对任一服务器进行ssh访问。只需一个mysql [dump]客户端就可以了。 使用mysql [dump],您可以转储数据库并再次导入它。
在您的电脑中,您可以执行以下操作:
$ mysqldump -u originaluser -poriginalpassword -h originalhost originaldatabase | mysql -u newuser -pnewpassword -h newhost newdatabase
你已经完成了。 : - )
希望这会有所帮助
答案 7 :(得分:1)
您可以通过运行mysqldump database table1 table2 ... tableN
如果没有一个表太大,那就足够了。否则,您将不得不开始在较大的表中拆分数据。
答案 8 :(得分:1)
我会推荐实用程序bigdump,你可以在这里抓住它。 http://www.ozerov.de/bigdump.php 这会使转储的执行错开,尽可能接近你的限制,一次执行整行。
答案 9 :(得分:1)
对@Vérace答案的澄清:
我特别喜欢互动方式;您可以在Eclipse中拆分大文件。我在Windows中成功尝试了105GB文件:
只需将MySQLDumpSplitter库添加到您的项目中: http://dl.bintray.com/verace/MySQLDumpSplitter/jar/
关于如何导入的快速说明:
- In Eclipse, Right click on your project --> Import
- Select "File System" and then "Next"
- Browse the path of the jar file and press "Ok"
- Select (thick) the "MySQLDumpSplitter.jar" file and then "Finish"
- It will be added to your project and shown in the project folder in Package Explorer in Eclipse
- Double click on the jar file in Eclipse (in Package Explorer)
- The "MySQL Dump file splitter" window opens which you can specify the address of your dump file and proceed with split.
答案 10 :(得分:0)
这个script应该这样做:
#!/bin/sh
#edit these
USER=""
PASSWORD=""
MYSQLDIR="/path/to/backupdir"
MYSQLDUMP="/usr/bin/mysqldump"
MYSQL="/usr/bin/mysql"
echo - Dumping tables for each DB
databases=`$MYSQL --user=$USER --password=$PASSWORD -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema)"`
for db in $databases; do
echo - Creating "$db" DB
mkdir $MYSQLDIR/$db
chmod -R 777 $MYSQLDIR/$db
for tb in `$MYSQL --user=$USER --password=$PASSWORD -N -B -e "use $db ;show tables"`
do
echo -- Creating table $tb
$MYSQLDUMP --opt --delayed-insert --insert-ignore --user=$USER --password=$PASSWORD $db $tb | bzip2 -c > $MYSQLDIR/$db/$tb.sql.bz2
done
echo
done
答案 11 :(得分:0)
我编写了一个Python脚本,将一个大型sql转储文件拆分为单独的文件,每个CREATE TABLE语句一个。它将文件写入您指定的新文件夹。如果未指定输出文件夹,它将在同一目录中创建一个与转储文件同名的新文件夹。它可以逐行运行,而无需先将文件写入内存,因此非常适合大型文件。
https://github.com/kloddant/split_sql_dump_file
import sys, re, os
if sys.version_info[0] < 3:
raise Exception("""Must be using Python 3. Try running "C:\\Program Files (x86)\\Python37-32\\python.exe" split_sql_dump_file.py""")
sqldump_path = input("Enter the path to the sql dump file: ")
if not os.path.exists(sqldump_path):
raise Exception("Invalid sql dump path. {sqldump_path} does not exist.".format(sqldump_path=sqldump_path))
output_folder_path = input("Enter the path to the output folder: ") or sqldump_path.rstrip('.sql')
if not os.path.exists(output_folder_path):
os.makedirs(output_folder_path)
table_name = None
output_file_path = None
smallfile = None
with open(sqldump_path, 'rb') as bigfile:
for line_number, line in enumerate(bigfile):
line_string = line.decode("utf-8")
if 'CREATE TABLE' in line_string.upper():
match = re.match(r"^CREATE TABLE (?:IF NOT EXISTS )?`(?P<table>\w+)` \($", line_string)
if match:
table_name = match.group('table')
print(table_name)
output_file_path = "{output_folder_path}/{table_name}.sql".format(output_folder_path=output_folder_path.rstrip('/'), table_name=table_name)
if smallfile:
smallfile.close()
smallfile = open(output_file_path, 'wb')
if not table_name:
continue
smallfile.write(line)
smallfile.close()
答案 12 :(得分:0)
我编写了新版本的SQLDumpSplitter,这次使用了适当的解析器,允许将诸如具有多个值的INSERT之类的好东西拆分到文件中,并且它现在是多平台的:https://philiplb.de/sqldumpsplitter3/
答案 13 :(得分:0)
试试这个:https://github.com/shenli/mysqldump-hugetable 它会将数据转储到许多小文件中。每个文件包含更少或相等的MAX_RECORDS记录。您可以在env.sh中设置此参数。
答案 14 :(得分:0)
您可以通过AWK拆分现有文件。这非常古怪而简单
让我们通过“表格”拆分表转储。 :
cat dump.sql | awk 'BEGIN {output = "comments"; }
$data ~ /^CREATE TABLE/ {close(output); output = substr($3,2,length($3)-2); }
{ print $data >> output }';
或者您可以通过数据库&#39;
拆分转储cat backup.sql | awk 'BEGIN {output="comments";} $data ~ /Current Database/ {close(output);output=$4;} {print $data>>output}';
答案 15 :(得分:0)
我创建了MySQLDumpSplitter.java,它与bash脚本不同,适用于Windows。它的 这里有https://github.com/Verace/MySQLDumpSplitter。
答案 16 :(得分:0)
答案 17 :(得分:0)
尝试使用csplit(1)根据正则表达式将输出切换到各个表中(与我想的表边界相匹配)。