Nejsem si jistý, jestli je to pravda, ale pamatuji si čtení, pokud spustíte následující příkaz v Linuxu
mysqldump -u username -p database_name > backup_db.sql
zatímco probíhá čtení a zápis do databáze, výpis může obsahovat chyby.
Existují v příkazu mysqldump
zvláštní možnosti, jak zajistit, aby se to na živém systému provádělo bezpečně? Jsem v pořádku, protože čtení a zápisy jsou pro naše uživatele na několik sekund deaktivovány (databáze <50 MB)
Takto získáte přesný snímek dat v čase:
mysqldump -uuser -ppass --single-transaction --routines --triggers --all-databases > backup_db.sql
--single-transaction
vytvoří kontrolní bod, který umožňuje výpisu zachytit všechna data před kontrolním bodem při přijímání příchozích změn. Tyto příchozí změny se nestanou součástí výpisu. To zajišťuje stejný čas v čase pro všechny tabulky.
--routines
vypíše všechny uložené procedury a uložené funkce
--triggers
vypíše všechny spouštěče pro každou tabulku, která je má
Budete muset uložit globální zámek pro čtení, provést mysqldump a uvolnit globální zámek
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
Pokusit se !!!
Protože máte <50 MB celkových dat, mám jinou možnost. Namísto spuštění příkazu SLEEP na pozadí, který drží globální zámek čtení po dobu 86400 s (24 hodin), jen abych získal ID procesu a zabil venku, zkusme nastavit 5sekundový časový limit v mysql místo v OS:
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
Jedná se o čistší a jednodušší přístup pro velmi malé databáze.
--single-transaction
možnost, jak je uvedeno v jiné odpovědi.--lock-tables
.Návrh oficiální dokumentace mysql je, že byste měli mít hlavní „M1“ databázi a slave „S1“ databázi, která je popsána v „scénáři 2: Zálohování pouze pro čtení Slave“ Zálohování Master nebo Slave tím, že je určen pouze ke čtení
Databázi slave byste měli nastavit pouze pro čtení a provést tuto akci
Takhle jsem to udělal. Měl by fungovat ve všech případech, protože používá 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 !"
Příkaz Shell sleep
slouží pouze k zajištění toho, aby byla úloha na pozadí, na které je spuštěn příkaz zamykání mysql, spuštěna před spuštěním mysqldump. Dalo by se to snížit na 1 sekundu a mělo by to být v pořádku. Zvyšte ji na 30 sekund a zkuste vložit hodnoty do jakékoli tabulky od jiného klienta během těchto 30 sekund, uvidíte, že je uzamčena.
Při použití tohoto ručního zamykání na pozadí existují dvě výhody, namísto použití možností mysqldump
options --single-transaction
a --lock-tables
:
mysqldump
provádět i další příkazy. Je to užitečné například při nastavování replikace na hlavním uzlu, protože musíte získat pozici binárního protokolu pomocí SHOW MASTER STATUS;
v přesném stavu výpisu, který jste vytvořili (před odemknutím databáze), abyste mohli vytvořit replikační slave.Pokud to chcete udělat pro MyISAM nebo smíšené tabulky bez jakýchkoli prostojů při zamykání tabulek, můžete nastavit podřízenou databázi a odtud snímky odebrat. Nastavení databáze otroků bohužel způsobuje nějaký výpadek exportu živé databáze, ale jakmile je spuštěna, měli byste mít možnost uzamknout její tabulky a exportovat pomocí metod, které ostatní popsali. Když se to stane, bude to zpoždění za hlavním, ale nezabrání hlavnímu aktualizovat jeho tabulky a dohoní, jakmile bude záloha dokončena.
pokud máte velmi velkou tabulku MYISAM a potřebujete ji vypsat bez zámku a zabránit vysoké zátěži serveru, můžete použít následující skript.
#!/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"