Использование 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++;
}