如何将mysqldump的输出拆分为较小的文件?

时间:2008-09-25 12:08:06

标签: mysql migration

我需要将整个表从一个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。

18 个答案:

答案 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 /下。剧本   将创建文件夹/ p​​ath / 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

来使用mysqldump转储单个表

如果没有一个表太大,那就足够了。否则,您将不得不开始在较大的表中拆分数据。

答案 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)

查看SQLDumpSplitter 2,我只是用它来成功分割40MB转储。您可以通过以下链接获取:

sqldumpsplitter.com

希望这有帮助。

答案 17 :(得分:0)

尝试使用csplit(1)根据正则表达式将输出切换到各个表中(与我想的表边界相匹配)。