Давным-давно (кажется, в прошлую среду) попался ко мне в руки дамп базы данных MySQL, который следовало немедленно развернуть на моей машине. Зачем это было нужно и откуда взялся дамп, рассказывать не буду, вряд ли это кому-то интересно. Важно то, что дамп был от MySQL 4.1.22 и снят он был при помощи одного широко известного инструмента (версии 5.23).
Разворачиваться у меня он решительно отказался... 
 

...
Error occured at:2016-02-12 10:28:24
Line no.:65
Error Code: 2013 - Lost connection to MySQL server during query

Ошибка, по обыкновению, была довольно невнятна, но поскольку предварялась она длинным (слишком длинным) SQL-запросом, её причина была очевидна. Дабы уменьшить количество insert-ов (бесспорно, благое начинание), SQLyog «склеивает» их, примерно следующим образом:

insert into abc(a, b, c) values (1,2,3),(4,5,6),(7,8,9),...

Когда данных много, полученный гигантский запрос разбивается на куски, но как-то так получается, что размер этих кусков (~ 1 мегабайта) всё ещё остаётся слишком большим. Я не нашёл у SQLyog рукоятку управления, позволяющую сделать снятый дамп более вменяемым (возможно, плохо искал), да и в любом случае, исходный дамп (тот, о котором идёт речь в этой статье) снимал не я и с ним надо было что-то делать. В общем, долго сказка сказывается, но само дело делается значительно быстрее:

while (<>) {
    chomp;
    if (length($_) < 4096) {
        print "$_\n";
    } else {
        if (/^(insert.*values\s+)\((.*)\);$/) {
            my $hd = $1; my $tx = '';
            my @bd = split(/\),\(/, $2);
            foreach $st (@bd) {
               if ($tx) {
                   $tx .= ',(' . $st . ')';
               } else {
                   $tx = $hd . '(' . $st . ')';
               }
               if (length($tx) > 4096) {
                   print "$tx;\n";
                   $tx = '';
               }
            }
            if ($tx) {
                print "$tx;\n";
            }
        }
    }
}

Любимый Perl не подвёл меня и в этот раз. Возможно, код можно было написать и как-то поэлегантнее, но меня вполне устраивает, как он работает. Длинные insert-ы разбиваются на куски размером около 4 килобайт (возможно можно и больше, не экспериментировал). Кому надо — берите и пользуйтесь.

Комментарии (8)