Il modo più sicuro per eseguire mysqldump su un sistema live con letture e scritture attive?


78

Non sono sicuro che sia vero, ma ricordo di aver letto se si esegue il seguente comando in Linux

mysqldump -u username -p database_name > backup_db.sql

mentre le letture e le scritture vengono eseguite su un database, il dump può contenere errori.

Esistono opzioni particolari nel comando mysqldumpper assicurarsi che ciò avvenga in modo sicuro su un sistema live? Sto bene con letture / scritture disabilitate per i nostri utenti per alcuni secondi (Il database <50 MB)

Risposte:


82

Tutti i dati sono InnoDB

Questo è ciò che ti darà un'istantanea puntuale nel tempo dei dati:

mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql

--single-transactionproduce un checkpoint che consente al dump di acquisire tutti i dati prima del checkpoint mentre riceve le modifiche in entrata. Tali modifiche in entrata non diventano parte del dump. Ciò garantisce lo stesso point-in-time per tutte le tabelle.

--routines scarica tutte le procedure e le funzioni memorizzate

--triggers scarica tutti i trigger per ogni tabella che li ha

Tutti i dati sono MyISAM o Mix di InnoDB / MyISAM

Dovrai imporre un blocco di lettura globale, eseguire mysqldump e rilasciare il blocco globale

mysql -uuser -ppass -Ae"FLUSH TABLES WITH READ LOCK; SELECT SLEEP(86400)" &
sleep 5
mysql -uuser -ppass -ANe"SHOW PROCESSLIST" | grep "SELECT SLEEP(86400)" > /tmp/proclist.txt
SLEEP_ID=`cat /tmp/proclist.txt | awk '{print $1}'`
echo "KILL ${SLEEP_ID};" > /tmp/kill_sleep.sql
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql
mysql -uuser -ppass -A < /tmp/kill_sleep.sql

Provaci !!!

AGGIORNAMENTO 2012-06-22 08:12 EDT

Dato che hai <50 MB di dati totali, ho un'altra opzione. Invece di avviare un comando SLEEP in background per mantenere il blocco di lettura globale per 86400 sec (quello 24 ore) solo per ottenere l'ID del processo e uccidere all'esterno, proviamo a impostare un timeout di 5 secondi in mysql piuttosto che nel sistema operativo:

SLEEP_TIMEOUT=5
SQLSTMT="FLUSH TABLES WITH READ LOCK; SELECT SLEEP(${SLEEP_TIMEOUT})"
mysql -uuser -ppass -Ae"${SQLSTMT}" &
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql

Questo è un approccio più pulito e semplice per database molto piccoli.


1
5 secondi è solo precauzionale. Puoi provare valori più bassi.
RolandoMySQLDBA,

1
Rolando - è ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during queryprevisto un messaggio di errore?
user784637,

1
Tutti i dati di MySQL sono usciti nel mysqldump?
RolandoMySQLDBA il

1
Non sono sicuro del messaggio di errore. Questa è solo un'ipotesi, ma potrebbe derivare dallo script a una riga che uccide la chiamata alla funzione SLEEP definita dall'utente menzionata nel secondo script.
RolandoMySQLDBA il

1
Prova il mio nuovo suggerimento e vedi se va bene. Speriamo che non ci siano messaggi di errore.
RolandoMySQLDBA

2
  • Per le tabelle InnoDB, è necessario utilizzare l' --single-transactionopzione, come indicato in un'altra risposta.
  • Per MyISAM c'è --lock-tables.

Vedi la documentazione ufficiale qui


1

Se si desidera eseguire questa operazione per MyISAM o tabelle miste senza tempi di inattività dal blocco delle tabelle, è possibile impostare un database slave e scattare le istantanee da lì. La configurazione del database slave, sfortunatamente, causa un certo tempo di inattività per esportare il database live, ma una volta in esecuzione, dovresti essere in grado di bloccare le sue tabelle ed esportare usando i metodi che altri hanno descritto. Quando ciò accade, resterà indietro rispetto al master, ma non impedirà al master di aggiornare le sue tabelle e raggiungerà non appena il backup sarà completo.


1

Ecco come l'ho fatto. Dovrebbe funzionare in tutti i casi poiché utilizza FLUSH TABLES WITH READ LOCK.

#!/bin/bash

DB=example
DUMP_FILE=export.sql

# Lock the database and sleep in background task
mysql -uroot -proot $DB -e "FLUSH TABLES WITH READ LOCK; DO SLEEP(3600);" &
sleep 3

# Export the database while it is locked
mysqldump -uroot -proot --opt $DB > $DUMP_FILE

# When finished, kill the previous background task to unlock
kill $! 2>/dev/null
wait $! 2>/dev/null

echo "Finished export, and unlocked !"

Il sleepcomando shell è solo per assicurarsi che l'attività in background che esegue il comando di blocco mysql sia eseguita prima dell'avvio di mysqldump. Potresti ridurlo a 1 secondo e dovrebbe comunque andare bene. Aumentalo a 30 secondi e prova a inserire valori in qualsiasi tabella da un altro client durante quei 30 secondi vedrai che è bloccato.

Ci sono 2 vantaggi nell'uso di questo blocco manuale in background, invece di usare le mysqldumpopzioni --single-transactione --lock-tables:

  1. Questo blocca tutto, se hai mischiato le tabelle MyISAM / InnoDB.
  2. È possibile eseguire altri comandi oltre a mysqldumpdurante lo stesso periodo di blocco. È utile, ad esempio, quando si configura la replica su un nodo master, poiché è necessario ottenere la posizione del registro binario SHOW MASTER STATUS;nello stato esatto del dump creato (prima di sbloccare il database), per poter creare uno slave di replica.


0

se si dispone di una tabella MYISAM molto grande e è necessario eseguire il dump della tabella senza blocco ed evitare un carico elevato del server, è possibile utilizzare il seguente script.

#!/bin/sh

my_user="user"
my_password="password"
my_db="vpn"
my_table="traffic"
my_step=100000

read -p "Dumping table ${my_db}.${my_table} to ${my_table}.sql?" yn
case $yn in
    [Yy]* ) break;;
    * ) echo "User cancel."; exit;;
esac

my_count=$(mysql $my_db -u $my_user -p$my_password -se "SELECT count(*) FROM $my_table")
my_count=$(($my_count + 0))

if [ ! $my_count ]
then
    echo "No records found"
    exit
fi

echo "Records in table ${my_db}.${my_table}: ${my_count}"

echo "" > $my_table.sql

max_progress=60

for (( limit=0; limit<=$my_count; limit+=$my_step )); do
    progress=$((max_progress * ( limit + my_step) / my_count))

    echo -ne "Dumping ["
    for ((i=0; i<$progress; i ++)); do
        echo -ne "#"
    done
    for ((; i<$max_progress; i ++)); do
        echo -ne "."
    done

    mysqldump -u $my_user -p$my_password --complete-insert --no-create-info --opt --where="1 limit $limit , $my_step" $my_db $my_table >> $my_table.sql
    echo "" >> $my_table.sql

    echo -ne "] $((100 * ( limit + my_step ) / my_count)) %"
    echo -ne "\r"

    sleep 1

done

echo -ne "\n"
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.