Мне нужно переместить целые таблицы из одной базы данных MySQL в другую. У меня нет полного доступа ко второму, только доступ к phpMyAdmin. Я могу загружать только (сжатые) файлы sql размером менее 2 МБ. Но сжатый вывод mysqldump таблиц первой базы данных превышает 10 МБ.
Есть ли способ разделить вывод mysqldump на файлы меньшего размера? Я не могу использовать split (1), так как не могу вернуть файлы на удаленный сервер (1).
Или есть другое решение, которое я пропустил?
Редактировать
Опция --extended-insert = FALSE для mysqldump, предложенная первым постером, дает файл .sql, который затем может быть разделен на импортируемые файлы, при условии, что split (1) вызывается с подходящей опцией --lines. Методом проб и ошибок я обнаружил, что bzip2 сжимает файлы .sql в 20 раз, поэтому мне нужно было выяснить, сколько строк кода sql соответствует примерно 40 МБ.






Сначала сделайте дамп схемы (она точно умещается в 2 Мб, не так ли?)
mysqldump -d --all-databases
и восстановить его.
После этого выгружайте только данные в отдельных операторах вставки, чтобы вы могли разделить файлы и восстановить их, не объединяя их на удаленном сервере.
mysqldump --all-databases --extended-insert=FALSE --no-create-info=TRUE
Я искал способ включить оператор INSERT для каждой вставленной строки, а не один массивный оператор с множеством кортежей или каждой строкой с использованием VALUES. Флаг --extended-insert=FALSE был тем, что мне было нужно. Благодарность!
Создать таблицу: mysqldump mydatabase mytable -d > mytable-create.sql Данные: mysqldump mydatabase mytable --extended-insert=FALSE --no-create-info=TRUE > mytable-data.sql Затем разделить ее на серию файлов любой длины: split mytable-data.sql -l10000 Теперь вы можете импортировать сначала созданный SQL. Затем каждая из таблиц длиной по 10 000 штук. По умолчанию файлы будут называться xaa, xab, xac ...). Важны они mysql mydatabase < xaa и т. д.
Установка --extended-insert=FALSE сильно сократила для меня время импорта больших таблиц данных. Но я не понимаю, как это помогает. Даже если установлено значение TRUE, все операторы INSERT находятся в одной строке, поэтому вы можете безопасно разделить файл дампа на n строк, и единственное, что вы потеряете, - это блокировка при переключении на импорт дополнительных данных в ту же таблицу из следующей. файл (который вы можете восстановить, просто установив его cat).
Попробуйте csplit (1), чтобы разделить вывод на отдельные таблицы на основе регулярных выражений (я бы подумал, что соответствует границе таблицы).
Вы можете сбрасывать отдельные таблицы с помощью mysqldump, запустив mysqldump database table1 table2 ... tableN
Если ни одна из таблиц не слишком велика, этого будет достаточно. В противном случае вам придется начать разбиение данных на большие таблицы.
Вы говорите, что у вас нет доступа ко второму серверу. Но если у вас есть доступ к первому серверу, где находятся таблицы, вы можете разделить дамп по таблицам:
for T in `mysql -N -B -e 'show tables from dbname'`; \
do echo $T; \
mysqldump [connecting_options] dbname $T \
| gzip -c > dbname_$T.dump.gz ; \
doneЭто создаст файл gzip для каждой таблицы.
Другой способ разделить вывод mysqldump на отдельные файлы - использовать параметр --tab.
mysqldump [connecting options] --tab=directory_name dbname где имя_каталога - имя пустого каталога. Эта команда создает файл .sql для каждой таблицы, содержащий оператор CREATE TABLE, и файл .txt, содержащий данные, которые необходимо восстановить с помощью LOAD DATA INFILE. Однако я не уверен, может ли phpMyAdmin обрабатывать эти файлы с вашим конкретным ограничением.
Хотя это может не напрямую соответствовать потребностям OP, это отличный способ поместить отдельные таблицы в их собственные файлы ... для grep и т. д.
Если во время выполнения этого сценария выполняется запись в какие-либо таблицы, резервное копирование будет в несогласованном состоянии.
Вам не нужен ssh-доступ ни к одному из ваших серверов. Подойдет только клиент mysql [dump]. С помощью mysql [dump] вы можете выгрузить свою базу данных и снова импортировать ее.
На своем ПК вы можете сделать что-то вроде:
$ mysqldump -u originaluser -poriginalpassword -h originalhost originaldatabase | mysql -u newuser -pnewpassword -h newhost новая база данных
и вы сделали. :-)
надеюсь это поможет
Посмотрите SQLDumpSplitter 2, я просто успешно разбил дамп размером 40 МБ. Вы можете получить его по ссылке ниже:
Надеюсь на эту помощь.
SQLDumpSplitter2 может обрабатывать файлы размером только до 2 ГБ (2 147 483 648 байт - я думаю, он использует 32-битное целое число со знаком для размера файла). Было бы здорово изменить это или скомпилировать исходный исходный код для 64-битной версии, но я боюсь, что исходный код, вероятно, будет утерян. В остальном это отличный инструмент. Но многие проблемы с разделением файлов SQL начинаются где-то около 2 ГБ.
Привет, я просто хотел сообщить вам, что теперь доступна переписанная версия этой программы: philiplb.de/sqldumpsplitter3
Поздний ответ, но искал такое же решение и наткнулся на следующий код с веб-сайта ниже:
for I in $(mysql -e 'show databases' -s --skip-column-names); do mysqldump $I | gzip > "$I.sql.gz"; done
http://www.commandlinefu.com/commands/view/2916/backup-all-mysql-databases-to-individual-files
Я бы порекомендовал утилиту bigdump, вы можете скачать ее здесь. http://www.ozerov.de/bigdump.php это замедляет выполнение дампа настолько близко, насколько это возможно к вашему пределу, выполняя целые строки за раз.
Этот сценарий bash разбивает файл дампа одной базы данных на отдельные файлы для каждой таблицы и имена с csplit и присваивает им соответствующие имена:
#!/bin/bash
####
# Split MySQL dump SQL file into one file per table
# based on https://gist.github.com/jasny/1608062
####
#adjust this to your case:
START = "/-- Table structure for table/"
# or
#START = "/DROP TABLE IF EXISTS/"
if [ $# -lt 1 ] || [[ $1 == "--help" ]] || [[ $1 == "-h" ]] ; then
echo "USAGE: extract all tables:"
echo " $0 DUMP_FILE"
echo "extract one table:"
echo " $0 DUMP_FILE [TABLE]"
exit
fi
if [ $# -ge 2 ] ; then
#extract one table $2
csplit -s -ftable $1 "/-- Table structure for table/" "%-- Table structure for table \`$2\`%" "/-- Table structure for table/" "%40103 SET TIME_ZONE=@OLD_TIME_ZONE%1"
else
#extract all tables
csplit -s -ftable $1 "$START" {*}
fi
[ $? -eq 0 ] || exit
mv table00 head
FILE=`ls -1 table* | tail -n 1`
if [ $# -ge 2 ] ; then
# cut off all other tables
mv $FILE foot
else
# cut off the end of each file
csplit -b '%d' -s -f$FILE $FILE "/40103 SET TIME_ZONE=@OLD_TIME_ZONE/" {*}
mv ${FILE}1 foot
fi
for FILE in `ls -1 table*`; do
NAME=`head -n1 $FILE | cut -d$'\x60' -f2`
cat head $FILE foot > "$NAME.sql"
done
rm head foot table*
на основе https://gist.github.com/jasny/1608062
и https://stackoverflow.com/a/16840625/1069083
Следует отметить, что csplit на Mac не работает с этим скриптом, потому что он не поддерживает синтаксис {*}. Нужно запустить его в Linux.
То же самое и во FreeBSD. Но вы можете установить туда порт или пакет sysutils / coreutils, чтобы получить утилиты GNU и вместо этого использовать gcsplit.
Ой, я не могу, чем тебя хватит для этого сценария. У меня был mysqlDump емкостью 3 ТБ, который дважды терпел неудачу, и теперь я могу импортировать его таблицу за таблицей и продолжить с того места, где я оставил, если он не удастся. Тебе прислали много любви.
Да лучше всего. mysqldump не работает с параметром --tab, если база данных находится на другом сервере, кроме localhost. Таким образом, вы можете выгрузить всю базу данных, перенаправить вывод в один файл, а затем разделить таблицы с помощью этого сценария! Но я ищу способ сделать как параметр --tab: разделить структуру как файл sql и данные как данные, разделенные табуляцией txt. Какой-нибудь волшебный сценарий для этого, или я бы создал другой сценарий разделения и преобразования?
Этот сценарий должен это делать:
#!/bin/sh
#edit these
USER = ""
PASSWORD = ""
MYSQLDIR = "/path/to/backupdir"
MYSQLDUMP = "/usr/bin/mysqldump"
MYSQL = "/usr/bin/mysql"
echo - Dumping tables for each DB
databases=`$MYSQL --user=$USER --password=$PASSWORD -e "SHOW DATABASES;" | grep -Ev "(Database|information_schema)"`
for db in $databases; do
echo - Creating "$db" DB
mkdir $MYSQLDIR/$db
chmod -R 777 $MYSQLDIR/$db
for tb in `$MYSQL --user=$USER --password=$PASSWORD -N -B -e "use $db ;show tables"`
do
echo -- Creating table $tb
$MYSQLDUMP --opt --delayed-insert --insert-ignore --user=$USER --password=$PASSWORD $db $tb | bzip2 -c > $MYSQLDIR/$db/$tb.sql.bz2
done
echo
done
Я создал MySQLDumpSplitter.java, который, в отличие от сценариев bash, работает в Windows. Это доступно здесь https://github.com/Verace/MySQLDumpSplitter.
Недавно я создал sqlsplit.com. Попробуйте сами.
ваше приложение отлично работает, но что вы делаете с загруженными файлами?
@ DaniëlTulp Ничего. Загруженные файлы удаляются сразу после разделения и отправки пользователю. github.com/sqlsplit/sqlsplit/blob/master/public/index.php#L3 8
возможно, добавьте заявление о конфиденциальности по этому поводу (также, чтобы соответствовать GDPR, спасибо за приложение, использовал его для восстановления рабочего веб-сайта
@ DaniëlTulp Только что добавлен диалог конфиденциальности.
Вы можете разбить существующий файл по AWK. Это очень быстро и просто
Разобьем дамп таблицы на «таблицы»:
cat dump.sql | awk 'BEGIN {output = "comments"; }
$data ~ /^CREATE TABLE/ {close(output); output = substr(,2,length()-2); }
{ print $data >> output }';
Или вы можете разделить дамп по базе данных
cat backup.sql | awk 'BEGIN {output = "comments";} $data ~ /Current Database/ {close(output);output=;} {print $data>>output}';
Есть отличный скрипт mysqldumpsplitter, который имеет множество опций, когда дело доходит до извлечения из mysqldump.
Я бы скопировал рецепт сюда, чтобы выбрать свой случай из:
1) Extract single database from mysqldump:
sh mysqldumpsplitter.sh --source filename --extract DB --match_str database-nameAbove command will create sql for specified database from specified "filename" sql file and store it in compressed format to database-name.sql.gz.
2) Extract single table from mysqldump:
sh mysqldumpsplitter.sh --source filename --extract TABLE --match_str table-nameAbove command will create sql for specified table from specified "filename" mysqldump file and store it in compressed format to database-name.sql.gz.
3) Extract tables matching regular expression from mysqldump:
sh mysqldumpsplitter.sh --source filename --extract REGEXP --match_str regular-expressionAbove command will create sqls for tables matching specified regular expression from specified "filename" mysqldump file and store it in compressed format to individual table-name.sql.gz.
4) Extract all databases from mysqldump:
sh mysqldumpsplitter.sh --source filename --extract ALLDBSAbove command will extract all databases from specified "filename" mysqldump file and store it in compressed format to individual database-name.sql.gz.
5) Extract all table from mysqldump:
sh mysqldumpsplitter.sh --source filename --extract ALLTABLESAbove command will extract all tables from specified "filename" mysqldump file and store it in compressed format to individual table-name.sql.gz.
6) Extract list of tables from mysqldump:
sh mysqldumpsplitter.sh --source filename --extract REGEXP --match_str '(table1|table2|table3)'Above command will extract tables from the specified "filename" mysqldump file and store them in compressed format to individual table-name.sql.gz.
7) Extract a database from compressed mysqldump:
sh mysqldumpsplitter.sh --source filename.sql.gz --extract DB --match_str 'dbname' --decompression gzipAbove command will decompress filename.sql.gz using gzip, extract database named "dbname" from "filename.sql.gz" & store it as out/dbname.sql.gz
8) Extract a database from compressed mysqldump in an uncompressed format:
sh mysqldumpsplitter.sh --source filename.sql.gz --extract DB --match_str 'dbname' --decompression gzip --compression noneAbove command will decompress filename.sql.gz using gzip and extract database named "dbname" from "filename.sql.gz" & store it as plain sql out/dbname.sql
9) Extract alltables from mysqldump in different folder:
sh mysqldumpsplitter.sh --source filename --extract ALLTABLES --output_dir /path/to/extracts/Above command will extract all tables from specified "filename" mysqldump file and extracts tables in compressed format to individual files, table-name.sql.gz stored under /path/to/extracts/. The script will create the folder /path/to/extracts/ if not exists.
10) Extract one or more tables from one database in a full-dump:
Consider you have a full dump with multiple databases and you want to extract few tables from one database.
Extract single database:
sh mysqldumpsplitter.sh --source filename --extract DB --match_str DBNAME --compression noneExtract all tables
sh mysqldumpsplitter.sh --source out/DBNAME.sql --extract REGEXP --match_str "(tbl1|tbl2)"though we can use another option to do this in single command as follows:
sh mysqldumpsplitter.sh --source filename --extract DBTABLE --match_str "DBNAME.(tbl1|tbl2)" --compression noneAbove command will extract both tbl1 and tbl2 from DBNAME database in sql format under folder "out" in current directory.
You can extract single table as follows:
sh mysqldumpsplitter.sh --source filename --extract DBTABLE --match_str "DBNAME.(tbl1)" --compression none11) Extract all tables from specific database:
mysqldumpsplitter.sh --source filename --extract DBTABLE --match_str "DBNAME.*" --compression noneAbove command will extract all tables from DBNAME database in sql format and store it under "out" directory.
12) List content of the mysqldump file
mysqldumpsplitter.sh --source filename --descAbove command will list databases and tables from the dump file.
Позже вы можете выбрать загрузку файлов: zcat filename.sql.gz | mysql -uUSER -p -h ИМЯ ХОСТА
Кроме того, как только вы извлечете одну таблицу, которая, по вашему мнению, еще больше, вы можете использовать команду разделения linux с количеством строк для дальнейшего разделения дампа.
split -l 10000 filename.sql
Тем не менее, если это вам нужно (приходите чаще), вы можете подумать об использовании mydumper, который фактически создает отдельные дампы, которые вам не нужно разделять!
Я должен дополнить вас в вашем сценарии bash. У меня была огромная резервная копия базы данных, и мне потребовалось около 60 часов, чтобы разделить базу данных. Я волновался, что ваш сценарий может сломаться, но он работал как шарм. Спасибо и продолжайте в том же духе.
Это было так полезно! Спасибо за публикацию
Пояснение к ответу @ Vérace:
Мне особенно нравится интерактивный метод; вы можете разделить большой файл в Eclipse. Я успешно пробовал файл размером 105 ГБ в Windows:
Просто добавьте в свой проект библиотеку MySQLDumpSplitter: http://dl.bintray.com/verace/MySQLDumpSplitter/jar/
Краткое примечание о том, как импортировать:
- In Eclipse, Right click on your project --> Import
- Select "File System" and then "Next"
- Browse the path of the jar file and press "Ok"
- Select (thick) the "MySQLDumpSplitter.jar" file and then "Finish"
- It will be added to your project and shown in the project folder in Package Explorer in Eclipse
- Double click on the jar file in Eclipse (in Package Explorer)
- The "MySQL Dump file splitter" window opens which you can specify the address of your dump file and proceed with split.
Попробуйте это: https://github.com/shenli/mysqldump-hugetable Он сбрасывает данные во множество небольших файлов. Каждый файл содержит меньше или равно MAX_RECORDS записей. Вы можете установить этот параметр в env.sh.
Я написал новую версию SQLDumpSplitter, на этот раз с правильным парсером, позволяющим разделять такие приятные вещи, как INSERT со многими значениями, по файлам, и теперь это мультиплатформенный: https://philiplb.de/sqldumpsplitter3/
Я написал сценарий Python для разделения одного большого файла дампа sql на отдельные файлы, по одному для каждого оператора CREATE TABLE. Он записывает файлы в новую указанную вами папку. Если выходная папка не указана, создается новая папка с тем же именем, что и файл дампа, в том же каталоге. Он работает построчно, без предварительной записи файла в память, поэтому отлично подходит для больших файлов.
https://github.com/kloddant/split_sql_dump_file
import sys, re, os
if sys.version_info[0] < 3:
raise Exception("""Must be using Python 3. Try running "C:\Program Files (x86)\Python37-32\python.exe" split_sql_dump_file.py""")
sqldump_path = input("Enter the path to the sql dump file: ")
if not os.path.exists(sqldump_path):
raise Exception("Invalid sql dump path. {sqldump_path} does not exist.".format(sqldump_path=sqldump_path))
output_folder_path = input("Enter the path to the output folder: ") or sqldump_path.rstrip('.sql')
if not os.path.exists(output_folder_path):
os.makedirs(output_folder_path)
table_name = None
output_file_path = None
smallfile = None
with open(sqldump_path, 'rb') as bigfile:
for line_number, line in enumerate(bigfile):
line_string = line.decode("utf-8")
if 'CREATE TABLE' in line_string.upper():
match = re.match(r"^CREATE TABLE (?:IF NOT EXISTS )?`(?P<table>\w+)` \($", line_string)
if match:
table_name = match.group('table')
print(table_name)
output_file_path = "{output_folder_path}/{table_name}.sql".format(output_folder_path=output_folder_path.rstrip('/'), table_name=table_name)
if smallfile:
smallfile.close()
smallfile = open(output_file_path, 'wb')
if not table_name:
continue
smallfile.write(line)
smallfile.close()
посмотрите на этот Q, если вы ищете, как разбить большой дамп postgresql на файлы меньшего размера