Использование mysqldump для форматирования одной вставки на строку?
Это было задано несколько раз, но я не могу найти решение моей проблемы. В основном при использовании mysqldump, который является встроенным инструментом для инструмента администрирования MySQL Workbench, когда я удаляю базу данных с помощью расширенных вставок, я получаю массивные длинные строки данных. Я понимаю, почему он это делает, поскольку он ускоряет вставку, вставляя данные как одну команду (особенно в InnoDB), но форматирование делает ДЕЙСТВИТЕЛЬНО трудным для просмотра данных в файле дампа или сравнения двух файлов с инструментом diff если вы храните их в управлении версиями и т.д. В моем случае я храню их в управлении версиями, поскольку мы используем файлы дампа для отслеживания нашей тестовой базы данных интеграции.
Теперь я знаю, что могу отключить расширенные вставки, поэтому я получу одну вставку на строку, которая работает, но в любое время, когда вы делаете восстановление с дамп файлом, он будет медленнее.
Моя основная проблема заключается в том, что в OLD-инструменте, который мы использовали (администратор MySQL), когда я дамп файла, он делает в основном то же самое, но он ФОРМАТЫ, что оператор INSERT помещает одну вставку в строку, все еще делая объемные вставки, Поэтому вместо этого:
INSERT INTO `coupon_gv_customer` (`customer_id`,`amount`) VALUES (887,'0.0000'),191607,'1.0300');
вы получите следующее:
INSERT INTO `coupon_gv_customer` (`customer_id`,`amount`) VALUES
(887,'0.0000'),
(191607,'1.0300');
Независимо от того, какие параметры я пытаюсь сделать, похоже, что нет возможности получить такой свалку, что действительно является лучшим из обоих миров. Да, это занимает немного больше места, но в ситуациях, когда вам нужен человек для чтения файлов, это делает его БОЛЬШЕ более полезным.
Мне что-то не хватает, и есть способ сделать это с помощью MySQLDump, или мы все ушли назад, и эта функция в старом (теперь устаревшем) инструменте администратора MySQL больше не доступна?
Ответы
Ответ 1
В стандартном формате mysqldump каждая записываемая запись генерирует отдельную команду INSERT в файле дампа (т.е. файл sql), каждый в своей строке. Это идеально подходит для управления исходным кодом (например, svn, git и т.д.), Поскольку это делает различие и дельта-разрешение намного более тонким и в конечном итоге приводит к более эффективному процессу управления источниками. Тем не менее, для таблиц с большими размерами выполнение всех этих запросов INSERT может сделать восстановление из файла sql непомерно медленным.
Использование опции -extended-insert устраняет проблему с несколькими INSERT, упаковывая все записи в одну команду INSERT на одной строке в файле sql файла. Однако процесс управления источником становится очень неэффективным. Все содержимое таблицы представлено в одной строке в файле sql, и если один символ изменяется в любой точке этой таблицы, элемент управления источником будет отмечать всю строку (т.е. Всю таблицу) как дельта между версиями. И для больших таблиц это отрицает многие преимущества использования формальной системы управления версиями.
В идеале для эффективного восстановления базы данных в sql файле мы хотим, чтобы каждая таблица была представлена одним INSERT. Для эффективного процесса управления версиями в файле sql мы хотим, чтобы каждая запись в этой команде INSERT находилась в отдельной строке.
Моим решением является следующее резервное копирование script:
#!/bin/bash
cd my_git_directory/
ARGS="--host=myhostname --user=myusername --password=mypassword --opt --skip-dump-date"
/usr/bin/mysqldump $ARGS --database mydatabase | sed 's$VALUES ($VALUES\n($g' | sed 's$),($),\n($g' > mydatabase.sql
git fetch origin master
git merge origin/master
git add mydatabase.sql
git commit -m "Daily backup."
git push origin master
В результате получается формат команды INSERT файла sql, который выглядит следующим образом:
INSERT INTO `mytable` VALUES
(r1c1value, r1c2value, r1c3value),
(r2c1value, r2c2value, r2c3value),
(r3c1value, r3c2value, r3c3value);
Некоторые примечания:
- пароль в командной строке... Я знаю, не защищен, разные обсуждения.
- - opt: помимо всего прочего, включается опция - расширенная вставка (т.е. один INSERT для таблицы).
- - skip-dump-date: mysqldump обычно помещает дату/время в файл sql при создании. Это может раздражать контроль источника, когда единственной дельтой между версиями является отметка даты/времени. Система управления версиями ОС и источников будет указывать дату и время на файл и версию. Его действительно не нужно в файле sql.
- Команды git не являются центральными для фундаментального вопроса (форматирование файла sql), но показывает, как я верну свой файл sql в исходный элемент управления, что-то подобное можно сделать с помощью svn. Комбинируя этот формат файла sql с вашим исходным контролем по выбору, вы обнаружите, что когда ваши пользователи обновляют свои рабочие копии, им нужно только перемещать дельта (т.е. Измененные записи) через Интернет, и они могут использовать утилиты diff чтобы легко увидеть, какие записи в базе данных изменились.
- Если вы удаляете базу данных, которая находится на удаленном сервере, если это возможно, запустите этот script на этом сервере, чтобы не удалять все содержимое базы данных по сети с каждым дампом.
- Если возможно, создайте репозиторий управления рабочим источником для ваших файлов sql на том же сервере, на котором вы выполняете этот script; проверьте их в репозитории. Это также поможет предотвратить использование всей базы данных по всей сети с каждым дампом.
Ответ 2
Попробуйте использовать следующий параметр:
- пропускать-расширенная-вставка
Это сработало для меня.
Ответ 3
Как говорили другие, используя sed для замены "), (" небезопасно, поскольку это может отображаться как содержимое в базе данных.
Однако есть способ сделать это:
если ваше имя базы данных является my_database, выполните следующее:
$ mysqldump -u my_db_user -p -h 127.0.0.1 --skip-extended-insert my_database > my_database.sql
$ sed ':a;N;$!ba;s/)\;\nINSERT INTO `[A-Za-z0-9$_]*` VALUES /),\n/g' my_database.sql > my_database2.sql
вы также можете использовать "sed -i" для замены в строке.
Вот что делает этот код:
- - skip-extended-insert создаст один INSERT INTO для каждой строки.
- Теперь мы используем sed для очистки данных. Обратите внимание, что регулярный поиск/замена sed применяется для одной строки, поэтому мы не можем обнаружить символ "\n", поскольку sed работает по одной строке за раз. Вот почему мы ставим ": a; N; $! Ba;" который в основном сообщает sed о поиске многострочной линии и буферизации следующей строки.
Надеюсь, что это поможет
Ответ 4
А как насчет сохранения дампа в файл CSV с помощью mysqldump, используя такую опцию --tab
?
mysqldump --tab=/path/to/serverlocaldir --single-transaction <database> table_a
Это создает два файла:
table_a.sql
, который содержит только оператор создания таблицы; и
table_a.txt
, который содержит данные, разделенные табуляцией.
ВОССТАНОВЛЕНИЕ
Вы можете восстановить свою таблицу с помощью LOAD DATA
:
LOAD DATA INFILE '/path/to/serverlocaldir/table_a.txt'
INTO TABLE table_a FIELDS TERMINATED BY '\t' ...
LOAD DATA обычно в 20 раз быстрее, чем использование операторов INSERT.
Если вам нужно восстановить данные в другую таблицу (например, для проверки или тестирования), вы можете создать "зеркальную" таблицу:
CREATE TABLE table_for_test LIKE table_a;
Затем загрузите CSV в новую таблицу:
LOAD DATA INFILE '/path/to/serverlocaldir/table_a.txt'
INTO TABLE table_for_test FIELDS TERMINATED BY '\t' ...
СРАВНИТЬ
CSV файл является самым простым для сравнения или для поиска внутри, или для не-технических пользователей, которые могут использовать общие инструменты, такие как Excel
, Access
или командную строку (diff
, comm
и т.д.)
Ответ 5
Я боюсь, что это будет невозможно. В старом администраторе MySQL я написал код для демпинга объектов db, который был полностью независим от инструмента mysqldump и, следовательно, предложил ряд дополнительных параметров (например, это форматирование или обратная связь с результатами). В MySQL Workbench было решено использовать инструмент mysqldump, который, помимо того, что был отброшен назад в некоторых отношениях и создает проблемы с версией, имеет преимущество, чтобы всегда оставаться в курсе сервера.
Итак, короткий ответ: форматирование в настоящее время невозможно с помощью mysqldump.
Ответ 6
Я нашел этот инструмент очень полезным для работы с расширенными вставками: http://blog.lavoie.sl/2014/06/split-mysqldump-extended-inserts.html
Он анализирует вывод mysqldump и вставляет строки после каждой записи, но все еще использует более быстрые расширенные вставки. В отличие от sed script, не должно быть риска нарушения строк в неправильном месте, если регулярное выражение встречается внутри строки.
Ответ 7
Попробуйте это:
mysqldump -c -t --add-drop-table=FALSE --skip-extended-insert -uroot -p<Password> databaseName tableName >c:\path\nameDumpFile.sql
Ответ 8
Мне понравилось решение Ace.Di с sed, пока я не получил эту ошибку:
sed: Не удалось перераспределить память
Таким образом, мне пришлось написать небольшой PHP скрипт
mysqldump -u my_db_user -p -h 127.0.0.1 --skip-extended-insert my_database | php mysqlconcatinserts.php > db.sql
PHP скрипт также генерирует новый INSERT для каждых 10.000 строк, чтобы избежать проблем с памятью.
mysqlconcatinserts.php:
#!/usr/bin/php
<?php
/* assuming a mysqldump using --skip-extended-insert */
$last = '';
$count = 0;
$maxinserts = 10000;
while($l = fgets(STDIN)){
if ( preg_match('/^(INSERT INTO .* VALUES) (.*);/',$l,$s) )
{
if ( $last != $s[1] || $count > $maxinserts )
{
if ( $count > $maxinserts ) // Limit the inserts
echo ";\n";
echo "$s[1] ";
$comma = '';
$last = $s[1];
$count = 0;
}
echo "$comma$s[2]";
$comma = ",\n";
} elseif ( $last != '' ) {
$last = '';
echo ";\n";
}
$count++;
}