50

我需要将整个表从一个 MySQL 数据库移动到另一个。我没有对第二个的完全访问权限,只有 phpMyAdmin 访问权限。我只能上传(压缩)小于 2MB 的 sql 文件。但是第一个数据库表的 mysqldump 的压缩输出大于 10MB。

有没有办法将 mysqldump 的输出拆分成更小的文件?我不能使用 split(1),因为我不能 cat(1) 将文件返回到远程服务器上。

还是我错过了另一种解决方案?

编辑

第一张海报建议的 mysqldump 的 --extended-insert=FALSE 选项会生成一个 .sql 文件,然后可以将其拆分为可导入的文件,前提是使用合适的 --lines 选项调用 split(1)。通过反复试验,我发现 bzip2 将 .sql 文件压缩了 20 倍,因此我需要弄清楚有多少行 sql 代码大致对应于 40MB。

4

18 回答 18

44

此 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
        # cut off all other tables
        mv $FILE foot
else
        # cut off the end of each file
        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

于 2012-03-30T19:37:16.673 回答
33

首先转储模式(它肯定适合 2Mb,不是吗?)

mysqldump -d --all-databases 

并恢复它。

之后仅在单独的插入语句中转储数据,因此您可以拆分文件并恢复它们,而无需在远程服务器上连接它们

mysqldump --all-databases --extended-insert=FALSE --no-create-info=TRUE
于 2008-09-25T12:16:05.517 回答
14

有一个出色的mysqldumpsplitter脚本,它在从 mysqldump 中提取时提供了大量选项。

我会在这里复制食谱以选择您的案例:

1)从mysqldump中提取单个数据库:

sh mysqldumpsplitter.sh --source filename --extract DB --match_str database-name

上面的命令将从指定的“文件名” sql 文件为指定的数据库创建 sql,并将其以压缩格式存储到 database-name.sql.gz。

2)从mysqldump中提取单个表:

sh mysqldumpsplitter.sh --source filename --extract TABLE --match_str table-name

上面的命令将从指定的“文件名”mysqldump 文件为指定的表创建 sql,并将其以压缩格式存储到 database-name.sql.gz。

3)从mysqldump中提取匹配正则表达式的表:

sh mysqldumpsplitter.sh --source filename --extract REGEXP --match_str regular-expression

上面的命令将从指定的“文件名”mysqldump 文件中为匹配指定正则表达式的表创建 sql,并将其以压缩格式存储到单独的 table-name.sql.gz。

4)从mysqldump中提取所有数据库:

sh mysqldumpsplitter.sh --source filename --extract ALLDBS

上面的命令将从指定的“文件名”mysqldump 文件中提取所有数据库,并将其以压缩格式存储到单独的 database-name.sql.gz 中。

5)从mysqldump中提取所有表:

sh mysqldumpsplitter.sh --source filename --extract ALLTABLES

上面的命令将从指定的“文件名”mysqldump 文件中提取所有表,并将其以压缩格式存储到单独的 table-name.sql.gz 中。

6)从mysqldump中提取表列表:

sh mysqldumpsplitter.sh --source filename --extract REGEXP --match_str '(table1|table2|table3)'

上面的命令将从指定的“文件名”mysqldump 文件中提取表,并将它们以压缩格式存储到单独的 table-name.sql.gz 中。

7)从压缩的mysqldump中提取数据库:

sh mysqldumpsplitter.sh --source filename.sql.gz --extract DB --match_str 'dbname' --decompression gzip

上述命令将使用 gzip 解压 filename.sql.gz,从“filename.sql.gz”中提取名为“dbname”的数据库并将其存储为 out/dbname.sql.gz

8) 以未压缩格式从压缩的 mysqldump 中提取数据库:

sh mysqldumpsplitter.sh --source filename.sql.gz --extract DB --match_str 'dbname' --decompression gzip --compression none

上面的命令将使用 gzip 解压缩 filename.sql.gz 并从“filename.sql.gz”中提取名为“dbname”的数据库并将其存储为普通 sql out/dbname.sql

9)从不同文件夹的mysqldump中提取所有表:

sh mysqldumpsplitter.sh --source filename --extract ALLTABLES --output_dir /path/to/extracts/

上述命令将从指定的“文件名”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

上面的命令将从当前目录中文件夹“out”下的 sql 格式的 DBNAME 数据库中提取 tbl1 和 tbl2。

您可以按如下方式提取单个表:

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,它实际上会创建您不需要拆分的单独转储!

于 2015-02-25T12:49:00.373 回答
12

您说您无权访问第二台服务器。但是,如果您对表所在的第一台服务器具有 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 语句,以及一个 .txt 文件,其中包含要使用 LOAD DATA INFILE 恢复的数据。不过,我不确定 phpMyAdmin 是否可以根据您的特定限制处理这些文件。

于 2008-09-25T16:15:19.530 回答
10

迟到的回复,但正在寻找相同的解决方案,并从以下网站发现以下代码:

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

于 2011-01-22T03:39:41.713 回答
3

我最近创建了sqlsplit.com。试试看。

于 2014-08-03T13:04:56.413 回答
3

我写了一个新版本的 SQLDumpSplitter,这次使用了一个合适的解析器,允许像 INSERTs 这样的好东西被分割到文件中,它现在是多平台的:https ://philiplb.de/sqldumpsplitter3/

于 2018-12-28T01:54:55.823 回答
2

您不需要 ssh 访问您的任何一个服务器。只是一个 mysql[dump] 客户端就可以了。使用 mysql[dump],您可以转储数据库并再次导入。

在您的 PC 中,您可以执行以下操作:

$ mysqldump -u originaluser -poriginalpassword -h originalhost originaldatabase | mysql -u newuser -pnewpassword -h newhost newdatabase

你就完成了。:-)

希望这可以帮助

于 2009-10-07T15:08:59.663 回答
1

您可以通过运行 mysqldump 转储单个表mysqldump database table1 table2 ... tableN

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

于 2008-09-25T12:20:14.120 回答
1

我会推荐实用程序 bigdump,你可以在这里获取它。http://www.ozerov.de/bigdump.php 这会错开转储的执行,尽可能接近您的极限,一次执行整行。

于 2011-02-19T13:47:35.057 回答
1

您可以通过 AWK 拆分现有文件。它非常快速和简单

让我们按 'tables' 拆分表转储:

cat dump.sql | awk 'BEGIN {output = "comments"; }
$data ~ /^CREATE TABLE/ {close(output); output = substr($3,2,length($3)-2); }
{ print $data >> output }';

或者您可以按“数据库”拆分转储

cat backup.sql | awk 'BEGIN {output="comments";} $data ~ /Current Database/ {close(output);output=$4;} {print $data>>output}';
于 2014-11-02T09:16:52.640 回答
1

试试这个:https ://github.com/shenli/mysqldump-hugetable 它将数据转储到许多小文件中。每个文件包含少于或等于 MAX_RECORDS 条记录。您可以在 env.sh 中设置此参数。

于 2015-11-21T02:52:13.803 回答
1

我编写了一个 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()
于 2019-10-04T19:53:40.447 回答
0

尝试 csplit(1) 根据正则表达式将输出切割成单个表(匹配我认为的表边界)。

于 2008-09-25T12:18:52.033 回答
0

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

sqldumpsplitter.com

希望这有帮助。

于 2010-06-16T20:30:23.650 回答
0

这个脚本应该这样做:

#!/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
于 2012-11-16T00:49:15.040 回答
0

我创建了 MySQLDumpSplitter.java,与 bash 脚本不同,它可以在 Windows 上运行。它可以在这里https://github.com/Verace/MySQLDumpSplitter获得。

于 2014-02-07T21:27:03.920 回答
0

澄清@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.
于 2015-06-22T19:39:41.210 回答