Давным-давно (кажется, в прошлую среду) попался ко мне в руки дамп базы данных 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 килобайт (возможно можно и больше, не экспериментировал). Кому надо — берите и пользуйтесь.
ссылка на оригинал статьи https://habrahabr.ru/post/277101/
Добавить комментарий