如何处理mysqldump创建的巨大行长度

8yparm6h  于 2023-03-22  发布在  Mysql
关注(0)|答案(8)|浏览(269)

我在一个cron作业中使用mysqldump来备份一个超过200万行的数据库。
它创建一个文本文件,可用于从命令行恢复数据记录。
我认为在恢复之前编辑转储文件是一种非常有用的方法,可以快速更改值和表或列名-至少在我了解更多信息并对使用ALTER和UPDATE进行操作充满信心之前。
编辑大型文本文件并不困扰我,但我惊讶地发现,在一个250兆的数据库转储中,只有大约300行。每行大约800 k个字符长。
是否有其他方法可以更好地控制行长度来生成转储?
还是应该使用sed或Perl等工具对转储进行后处理?

vmpqdwk3

vmpqdwk31#

默认情况下,mysqldump只为每个表生成一个INSERT命令,导致每个被转储的表都有一行(很长)插入数据。这主要是因为“批处理”插入比为每个表中的每个记录生成单独的INSERT查询快得多。
所以,这并不是说mysqldump创建了任意长的线,你可以强加一些其他的截止长度。
如果将INSERT分解为多行非常重要,可以使用以下命令表示:

mysqldump --extended-insert=FALSE --complete-insert=TRUE ...

但是,请注意,在这种格式下恢复表将花费更长的时间。

f1tvaqid

f1tvaqid2#

我今天浏览了MySQL的源代码来寻找解决这个问题的方法。最大行长度是由变量opt_net_buffer_length强制执行的,它应该与MySQL服务器的缓冲区大小相匹配。它非常大。
但无论如何,这是一个选择,所以只要这样做:

mysqldump --net_buffer_length=5000 ...

最小值为4096。

aurhwmvo

aurhwmvo3#

我在MySQL论坛上找到了一个答案,它最终表明在每个INSERT组之后添加'\n'是不可能的,单独使用mysqldump,而不修改源代码:
扩展格式不能100%正确解析基于逗号或括号,你会计数字段。最好的解决方案,修复mysqldump输出linebreak。
非常微小的变更:在第3506行,可以看到行结束逗号的输出位置:
fputc(',',md_result_file); /* Always row break */
只需在3506行之后立即插入这一行:
fputc('\n',md_result_file); /* Lon Binder says wrap that line! */
重新编译并完成。
@see http://forums.mysql.com/read.php?28,420002,426110#msg-426110
感谢Lon B!

  • (我已经包含了MySQL论坛的内容,以防论坛消失。
iq3niunx

iq3niunx4#

此标志也适用于:

mysqldump --skip-extended-insert

就像--extended-insert=FALSE一样。

polhcujo

polhcujo5#

使用正则表达式来分割行是不够的,您需要一个能够正确理解引号和转义字符的解析器。
我只是写了一个解析器,因为我找不到一个:http://blog.lavoie.sl/2014/06/split-mysqldump-extended-inserts.html

cwtwac6a

cwtwac6a6#

如果您已经有一个行很长的SQL转储,并且希望轻松读取它,可以使用

cat dump.sql  | sed 's$VALUES ($VALUES\n($g' | sed 's$),($),\n($g' | less

cat dump.sql  | sed 's$VALUES ($VALUES\n($g' | sed 's$),($),\n($g' | grep something
lx0bsm1f

lx0bsm1f7#

我是这样解决这个问题的:
1.我要求mysqldump --skip-extended-insert每行生成一个INSERT INTO

INSERT INTO `action_events` VALUES (1,'8cecd83d-76b7-44d3-ad6a-5ad3ff6410dd');
INSERT INTO `action_events` VALUES (2,'8cecd8ba-465c-4d2e-b9f0-caf504817e3a');
INSERT INTO `action_events` VALUES (3,'8cecd961-03d1-461f-8425-067c1d01d238');
INSERT INTO `action_events` VALUES (4,'8cf08433-f262-443c-90d1-629dcd11c5aa');
INSERT INTO `xx` VALUES (5,'8cf08433-f262-443c-90d1-629dcd11c5aa');
INSERT INTO `yy` VALUES (6,'8cf08433-f262-443c-90d1-629dcd11c5aa');

1.使用awk,我用逗号连接连续的行和INSERT INTO

INSERT INTO `action_events` VALUES
(1,'8cecd83d-76b7-44d3-ad6a-5ad3ff6410dd'),
(2,'8cecd8ba-465c-4d2e-b9f0-caf504817e3a'),
(3,'8cecd961-03d1-461f-8425-067c1d01d238'),
(4,'8cf08433-f262-443c-90d1-629dcd11c5aa');
INSERT INTO `xx` VALUES
(5,'8cf08433-f262-443c-90d1-629dcd11c5aa');
INSERT INTO `yy` VALUES
(6,'8cf08433-f262-443c-90d1-629dcd11c5aa');

下面是脚本join-insert-into

#!/bin/bash

# 1. print $0
# 2. print INSERT INTO
# 3. print (1,2,3),
# 4. print (1,2,3);
awk '
    BEGIN { FS = "\n"; OFS = ""; max_allowed_packet = 25*1024*1024; }
    END { if (prev_values) print prev_values ";" }
    {
        if (match($0, /^INSERT INTO [^ ]+ VALUES /)) {
            table = substr($0, RSTART, RLENGTH - 1)
            values = substr($0, RLENGTH + 1, length($0) - RLENGTH - 1)
            if (prev_table != table) {
                if (prev_values) {
                    print prev_values ";"
                }
                print table
                packet = length(table) + 1
            }
            else {
                packet += length(prev_values) + 2
                if (packet >= max_allowed_packet) {
                    print prev_values ";"
                    print table
                    packet = length(table) + 1
                }
                else {
                    print prev_values ","
                }
            }
            prev_table = table
            prev_values = values
        }
        else {
            if (prev_values) {
                print prev_values ";"
                prev_table = null
                prev_values = null
            }
            print $0
        }
    }
'

它可以这样使用:

# https://stackoverflow.com/a/34670902/1478566
MYSQL_PWD="$DB_PASSWORD" mysqldump \
    --no-tablespaces --quick --skip-extended-insert \
    -h$DB_HOST --port=${DB_PORT:-3306} \
    -u$DB_USERNAME $DB_DATABASE "$@" | join-insert-into
wooyq4lh

wooyq4lh8#

使用python对转储文件进行后处理。您可能比perl或sed更高兴。
如果你运行的是Linux,你已经安装好了,如果你运行的是Windows,安装程序是很容易的。
在此之前,你要学习使用SQL UPDATE和SQL ALTER,你会很高兴用正确的方法来做事情。

相关问题