Alle MySQL-Tabellen automatisch in separate Dateien kopieren?


72

Ich möchte Dumps jeder MySQL-Tabelle in separate Dateien bekommen. Das Handbuch gibt an, dass die Syntax hierfür lautet

mysqldump [options] db_name [tbl_name ...]

Dies zeigt an, dass Sie die Tabellennamen vorher kennen. Ich könnte das Skript einrichten, das jetzt jeden Tabellennamen kennt, aber sagen, ich füge später eine neue Tabelle hinzu und vergesse, das Dump-Skript zu aktualisieren. Dann fehlen mir Dumps für einen oder mehrere Tische.

Gibt es eine Möglichkeit, jede vorhandene Tabelle automatisch in eine separate Datei zu kopieren? Oder muss ich ein Skript-Fu machen? Fragen Sie die Datenbank ab, rufen Sie alle Tabellennamen ab und sichern Sie sie nach Namen.

Welche Skriptsprachen können auf eine MySQL-Datenbank zugreifen, wenn ich die Script-Fu-Route gehe?

Antworten:


63

Das Befehlszeilenprogramm mysqldump erledigt dies für Sie - obwohl die Dokumente diesbezüglich sehr unklar sind.

Eine Sache zu beachten ist, dass ~ / output / dir von dem Benutzer, der mysqld besitzt, beschreibbar sein muss. Unter Mac OS X:

sudo chown -R _mysqld:_mysqld ~/output/dir
mysqldump --user=dbuser --password --tab=~/output/dir dbname

Nachdem Sie die obigen Schritte ausgeführt haben, verfügen Sie über eine Datei tablename.sql, die das Schema jeder Tabelle enthält (Anweisung create table), und eine Datei tablename.txt, die die Daten enthält.

Wenn Sie nur einen Speicherauszug mit Schema wünschen, fügen Sie das Flag --no-data hinzu:

mysqldump --user=dbuser --password --no-data --tab=~/output/dir dbname

8
Nun, ich möchte wirklich, dass die Tabellendaten-Dumps auch SQL-Einfügungen sind: Þ
user151841

2
mysqlimportkann verwendet werden, um die resultierenden Daten-TXT-Dateien zu importieren. Auch Tabellennamen, die einen Punkt enthalten, (.)z. B.:, my.tableFühren nur zu einer gleichnamigen Datendatei (ohne Erweiterung .txt). dev.mysql.com/doc/refman/5.0/en/… Außerdem scheint dies die einzige Möglichkeit zu sein, eine --single-transactionTabelle pro Datei-Dump durchzuführen .
Will B.

4
Beachten Sie, dass diese Lösung die FILEBerechtigung auf dem Server erfordert und die Dateien auf die Festplatte auf dem Server schreibt.
Christopher Schultz

--tab generiert keine Einfügungen, die erforderlich wären, wenn Sie Datenbanken auf zwei Computern manuell verbinden möchten, zum Beispiel
Mladen Adamovic

74

Hier ist ein Skript, das Tabellendaten als SQL-Befehle in separate, komprimierte Dateien speichert. Es erfordert nicht, auf dem MySQL-Server-Host zu sein, das Kennwort im Skript nicht fest zu codieren und ist nur für eine bestimmte Datenbank, nicht für alle Datenbanken auf dem Server:

#!/bin/bash

# dump-tables-mysql.sh
# Descr: Dump MySQL table data into separate SQL files for a specified database.
# Usage: Run without args for usage info.
# Author: @Trutane
# Ref: http://stackoverflow.com/q/3669121/138325
# Notes:
#  * Script will prompt for password for db access.
#  * Output files are compressed and saved in the current working dir, unless DIR is
#    specified on command-line.

[ $# -lt 3 ] && echo "Usage: $(basename $0) <DB_HOST> <DB_USER> <DB_NAME> [<DIR>]" && exit 1

DB_host=$1
DB_user=$2
DB=$3
DIR=$4

[ -n "$DIR" ] || DIR=.
test -d $DIR || mkdir -p $DIR

echo -n "DB password: "
read -s DB_pass
echo
echo "Dumping tables into separate SQL command files for database '$DB' into dir=$DIR"

tbl_count=0

for t in $(mysql -NBA -h $DB_host -u $DB_user -p$DB_pass -D $DB -e 'show tables') 
do 
    echo "DUMPING TABLE: $DB.$t"
    mysqldump -h $DB_host -u $DB_user -p$DB_pass $DB $t | gzip > $DIR/$DB.$t.sql.gz
    tbl_count=$(( tbl_count + 1 ))
done

echo "$tbl_count tables dumped from database '$DB' into dir=$DIR"

1
Die beste Lösung imo ... Ich verwende eine modifizierte Version dieses Skripts, mit der das Kennwort als env-Variable übergeben werden kann. Wenn jemand diese Funktionalität benötigt: sprunge.us/fBDL?bash
Florian Fida

1
Imho beste Lösung auch: + mysqldump --extended-insert = FALSE -u "$ mysql_user" -p "$ mysql_user_pw" "$ db" $ t \ | gzip> "$ tables_dump_dir / $ t.sql.gz" etwas langsamer, funktioniert aber mit allen Daten und Zeilendatenlängen ...
Yordan Georgiev

Danke! Ich habe Ihre Idee verwendet, um ein Sicherungsskript zu generieren, das alle Datenbanken
sichert

8
Leider kann dies nicht als einzelne Transaktion durchgeführt werden, sodass Sie nicht unbedingt eine Reihe von Dateien erhalten, die ohne FK-Fehler neu geladen werden können.
Christopher Schultz

wahrscheinlich möchten Sie einige weitere Argumente wiemysqldump --extended-insert=FALSE --order-by-primary --complete-insert
Mladen Adamovic

20

Sie können dies erreichen, indem Sie:

  1. Holen Sie sich die Liste der Datenbanken in MySQL
  2. Dump jede Datenbank mit mysqldump
# Optional variables for a backup script
MYSQL_USER="root"
MYSQL_PASS="something"
BACKUP_DIR=/srv/backup/$(date +%Y-%m-%dT%H_%M_%S);
test -d "$BACKUP_DIR" || mkdir -p "$BACKUP_DIR"
# Get the database list, exclude information_schema
for db in $(mysql -B -s -u $MYSQL_USER --password=$MYSQL_PASS -e 'show databases' | grep -v information_schema)
do
  # dump each database in a separate file
  mysqldump -u $MYSQL_USER --password=$MYSQL_PASS "$db" | gzip > "$BACKUP_DIR/$db.sql.gz"
done

2
@IgorLadela Ich habe Zitate um "$ db" hinzugefügt, versuchen Sie das.
Elias Torres Arroyo

8
Die Frage war, jede Tabelle in einer separaten Datei zu haben, nicht jede Datenbank in einer separaten Datei.
Flimm

4
nicht genau das, was in Frage gestellt wurde, aber genau das , wonach ich gesucht habe :-)
ospf

erfasst keine Trigger und gespeicherten Prozeduren, ist kein Dump pro Tabelle.
Ken Ingram

Fügen Sie einfach Prozeduren und Trigger hinzu --routinesund --triggerserfassen Sie sie.
Mpen

7

Hier ist der entsprechende Import.

#!/bin/bash

# import-files-mysql.sh
# Descr: Import separate SQL files for a specified database.
# Usage: Run without args for usage info.
# Author: Will Rubel
# Notes:
#  * Script will prompt for password for db access.

[ $# -lt 3 ] && echo "Usage: $(basename $0) <DB_HOST> <DB_USER> <DB_NAME> [<DIR>]" && exit 1

DB_host=$1
DB_user=$2
DB=$3
DIR=$4

DIR=$DIR/*


echo -n "DB password: "
read -s DB_pass
echo
echo "Importing separate SQL command files for database '$DB' into '$DB'"

file_count=0


for f in $DIR

do 
    echo "IMPORTING FILE: $f"

    gunzip -c $f | mysql -h $DB_host -u $DB_user -p$DB_pass $DB

    (( file_count++ ))
done

echo "$file_count files importing to database '$DB'"

1
Nicht nur Code-Dump; Bitte erläutern Sie, was der Code bewirkt.
Rgettman

So verwenden Sie es: ./import-files-mysql.sh host_name dbname db ./, Ich gehe davon aus, dass sich alle Ihre gz-Dateien im aktuellen Ordner befinden. Bitte ersetzen Sie Ihre db-Anmeldedaten entsprechend. Das Skript fordert Sie auf, das Passwort danach einzugeben der Befehl.
Dylan B

3
#!/bin/bash

for i in $(mysql -uUser -pPASSWORD DATABASE -e "show tables;"|grep -v Tables_in_);do mysqldump -uUSER -pPASSWORD DATABASE $i > /backup/dir/$i".sql";done

tar -cjf "backup_mysql_"$(date +'%Y%m%d')".tar.bz2" /backup/dir/*.sql

1
Fügen Sie den Schlüssel -B hinzu, um Tabellen im nicht tabellarischen Ausgabeformat ohne Rahmen zu drucken
Vasin Yuriy

2

Es sieht so aus, als hätten alle hier vergessen, autocommit=0;SET unique_checks=0;SET foreign_key_checks=0;dass dies den Importprozess beschleunigen soll ...

#!/bin/bash
MYSQL_USER="USER"
MYSQL_PASS="PASS"

if [ -z "$1" ]
  then
    echo "Dumping all DB ... in separate files"
    for I in $(mysql -u $MYSQL_USER --password=$MYSQL_PASS -e 'show databases' -s --skip-column-names); 
    do 
      echo "SET autocommit=0;SET unique_checks=0;SET foreign_key_checks=0;" > "$I.sql"
      mysqldump -u $MYSQL_USER --password=$MYSQL_PASS $I >> "$I.sql"; 
      echo "SET autocommit=1;SET unique_checks=1;SET foreign_key_checks=1;commit;" >> "$I.sql"
      gzip "$I.sql"
    done
    echo "END."
else
      echo "Dumping $1 ..."
      echo "SET autocommit=0;SET unique_checks=0;SET foreign_key_checks=0;" > "$1.sql"
      mysqldump -u $MYSQL_USER --password=$MYSQL_PASS $1 >> "$1.sql"; 
      echo "SET autocommit=1;SET unique_checks=1;SET foreign_key_checks=1;commit;" >> "$1.sql"
      gzip "$1.sql"
fi

1

Wenn Sie alle Tabellen aus allen Datenbanken sichern möchten, kombinieren Sie einfach die Antwort von Elias Torres Arroyo und Trutane: Wenn Sie Ihr Passwort nicht auf dem Terminal angeben möchten, speichern Sie Ihr Passwort einfach in einer zusätzlichen Konfigurationsdatei (chmod 0600) - siehe Start von Mysqldump durch Cron- und Passwortsicherheit

#!/bin/bash

# this file
# a) gets all databases from mysql
# b) gets all tables from all databases in a)
# c) creates subfolders for every database in a)
# d) dumps every table from b) in a single file

    # this is a mixture of scripts from Trutane (http://stackoverflow.com/q/3669121/138325) 
    # and Elias Torres Arroyo (https://stackoverflow.com/a/14711298/8398149)

# usage: 
# sk-db.bash parameters
# where pararmeters are:

# d "dbs to leave"
# t " tables to leave"
# u "user who connects to database"
# h "db host"
# f "/backup/folder"



user='root'
host='localhost'
backup_folder=''
leave_dbs=(information_schema mysql)
leave_tables=()
while getopts ":d:t:u:h:f:" opt; do
  case $opt in
    d) leave_dbs=( $OPTARG )
    ;;
    t) leave_tables=( $OPTARG )
    ;;
    u) user=$OPTARG
    ;;
    h) host=$OPTARG
    ;;
    f) backup_folder=$OPTARG
    ;;

    \?) echo "Invalid option -$OPTARG" >&2
    ;;
  esac
done
echo '****************************************'
echo "Database Backup with these options"
echo "Host $host"
echo "User $user"
echo "Backup in $backup_folder"
echo '----------------------------------------'
echo "Databases to emit:"
printf "%s\n" "${leave_dbs[@]}"
echo '----------------------------------------'
echo "Tables to emit:"
printf "%s\n" "${leave_tables[@]}"
echo '----------------------------------------'


BACKUP_DIR=$backup_folder/$(date +%Y-%m-%dT%H_%M_%S);
CONFIG_FILE=/root/db-config.cnf

function contains() {
    local n=$#
    local value=${!n}
    for ((i=1;i < $#;i++)) {
        if [ "${!i}" == "${value}" ]; then
            echo "y"
            return 0
        fi
    }
    echo "n"
    return 1
}


test -d "$BACKUP_DIR" || mkdir -p "$BACKUP_DIR"
# Get the database list, exclude information_schema
database_count=0
tbl_count=0

for db in $(mysql --defaults-extra-file=$CONFIG_FILE -B -s -u $user -e 'show databases' )
do
    if [ $(contains "${leave_dbs[@]}" "$db") == "y" ]; then
        echo "leave database $db as requested"
    else

       # dump each database in a separate file
       (( database_count++ ))
       DIR=$BACKUP_DIR/$db
       [ -n "$DIR" ] || DIR=.

       test -d $DIR || mkdir -p $DIR

       echo
       echo "Dumping tables into separate SQL command files for database '$db' into dir=$DIR"

       for t in $(mysql --defaults-extra-file=$CONFIG_FILE -NBA -h $host -u $user -D $db -e 'show tables')
       do
           if [ $(contains "${leave_tables[@]}" "$db.$t") == "y" ]; then
               echo "leave table $db.$t as requested"
           else
               echo "DUMPING TABLE: $db.$t"
  #            mysqldump --defaults-extra-file=$CONFIG_FILE -h $host -u $user $db $t  > $DIR/$db.$t.sql
               tbl_count=$(( tbl_count + 1 ))
           fi
       done

       echo "Database $db is finished"
       echo '----------------------------------------'

    fi
done
echo '----------------------------------------'
echo "Backup completed"
echo '**********************************************'

Und das hat auch geholfen:

Überprüfen Sie, ob das Bash-Array einen Wert enthält

Arrays in Bash

benannte Argumente im Skript


0

Ich bin kein Bash-Meister, aber ich würde es einfach mit einem Bash-Skript machen. Ohne MySQL zu treffen, können Sie mit Kenntnis des Datenverzeichnisses und des Datenbanknamens einfach nach allen .frm-Dateien (eine für jede Tabelle in dieser Datenbank / diesem Verzeichnis) nach einer Liste von Tabellen suchen.

Ich bin mir sicher, dass es Möglichkeiten gibt, es schlanker zu machen und Argumente oder so weiter zu akzeptieren, aber das hat bei mir gut funktioniert.

tables_in_a_db_to_sql.sh

#!/bin/bash

database="this_is_my_database"
datadir="/var/lib/mysql/"
datadir_escaped="\/var\/lib\/mysql\/"

all_tables=($(ls $datadir$database/*.frm | sed s/"$datadir_escaped$database\/"/""/g | sed s/.frm//g))

for t in "${all_tables[@]}"; do
        outfile=$database.$t.sql
        echo "-- backing up $t to $outfile"
        echo "mysqldump [options] $database $t > $outfile"
        # mysqldump [options] $database $t > $outfile
done

Füllen Sie die [Optionen] und die gewünschte Outfile-Konvention nach Bedarf aus und kommentieren Sie die letzte mysqldump-Zeile aus.


Dieser Code, wenn ich laufe, zeigt diesen Fehler msg: Syntaxfehler: "(" unerwartet (möglicherweise seine Zeile Nr.: 9) .jeder Vorschlag
Syed Ahmed

0

Für Windows-Server können Sie eine Batchdatei wie folgt verwenden:

set year=%DATE:~10,4%
set day=%DATE:~7,2%
set mnt=%DATE:~4,2%
set hr=%TIME:~0,2%
set min=%TIME:~3,2%

IF %day% LSS 10 SET day=0%day:~1,1%
IF %mnt% LSS 10 SET mnt=0%mnt:~1,1%
IF %hr% LSS 10 SET hr=0%hr:~1,1%
IF %min% LSS 10 SET min=0%min:~1,1%

set backuptime=%year%-%mnt%-%day%-%hr%-%min%
set backupfldr=C:\inetpub\wwwroot\backupfiles\
set datafldr="C:\Program Files\MySQL\MySQL Server 5.5\data"
set zipper="C:\inetpub\wwwroot\backupfiles\zip\7za.exe"
set retaindays=21

:: Switch to the data directory to enumerate the folders
pushd %datafldr%

:: Get all table names and save them in a temp file
mysql --skip-column-names --user=root --password=mypassword mydatabasename -e "show tables" > tables.txt

:: Loop through all tables in temp file so that we can save one backup file per table
for /f "skip=3 delims=|" %%i in (tables.txt) do (
  set tablename = %%i
  mysqldump --user=root --password=mypassword mydatabasename %%i > "%backupfldr%mydatabasename.%backuptime%.%%i.sql"
)
del tables.txt

:: Zip all files ending in .sql in the folder
%zipper% a -tzip "%backupfldr%backup.mydatabasename.%backuptime%.zip" "%backupfldr%*.sql"

echo "Deleting all the files ending in .sql only"
del "%backupfldr%*.sql"

echo "Deleting zip files older than 21 days now"
Forfiles /p %backupfldr% /m *.zip /d -%retaindays% /c "cmd /c del /q @path"

Planen Sie es dann mit dem Windows Task Scheduler.

Wenn Sie bestimmte Tabellen in Ihrer Sicherung ausschließen möchten, beachten Sie, dass Sie in der Anweisung "show tables" eine where-Klausel verwenden können, der Spaltenname jedoch von Ihrem Datenbanknamen abhängt.

Wenn Ihr Datenbankname beispielsweise "blah" lautet, lautet Ihr Spaltenname in der Ergebnismenge " show tables " "tables_in_blah". Das heißt, Sie könnten eine where-Klausel hinzufügen, die dieser ähnelt:

show tables where tables_in_blah <> 'badtable'

oder

show tables where tables_in_blah like '%goodtable%'

-2

Siehe folgenden Artikel von Pauli Marcus:

So teilen Sie einen SQL-Datenbankspeicherauszug in tabellenweise Dateien auf

Das Aufteilen einer SQL-Datei, die eine gesamte Datenbank enthält, in Tabellen-Dateien ist ganz einfach: Überprüfen Sie die SQL-Datei auf das Auftreten von DROP TABLE. Generieren Sie den Dateinamen aus dem Tabellennamen, der in der Anweisung DROP TABLE enthalten ist. Echo die Ausgabe in eine Datei. Hier ist ein kleines Skript, das eine SQL-Datei als Eingabe erwartet:

#!/bin/bash

file=$1 # the input file
directory="$file-splitted" # the output directory
output="$directory/header" # the first file containing the header
GREP="DROP TABLE" # what we are looking for

mkdir $directory # create the output directory

while read line
do
   # if the current line contains the wanted statement
   if [ $(echo "$line" | grep -c "$GREP") == "1" ]
   then
      # extract the file name
      myfile=$(echo $line | awk '{print $5}' | sed -e 's/`//g' -e 's/;//g')
      # set the new file name
      output="$directory/$myfile"
   fi
       echo "$line" >> $output # write to file
done < $file

Was ist, wenn eine Zeile die Zeichenfolge enthält DROP TABLE? Dies ist keine sichere Lösung.
Flimm
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.