it-swarm-eu.dev

Nejbezpečnější způsob, jak provést mysqldump na živém systému s aktivním čtením a zápisem?

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)

85
user784637

Všechna data jsou InnoDB

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á

Všechna data jsou MyISAM nebo Mix InnoDB/MyISAM

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 !!!

PDATE 2012-06-22 08:12 EDT

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.

90
RolandoMySQLDBA
  • Pro tabulky InnoDB byste měli použít --single-transaction možnost, jak je uvedeno v jiné odpovědi.
  • Pro MyISAM existuje --lock-tables.

Viz oficiální dokumentace zde

4
pesco

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

1

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:

  1. Toto uzamkne vše, pokud máte smíšené tabulky MyISAM/InnoDB.
  2. Během stejné doby zamykání můžete kromě 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.
1
Nicomak

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.

1
Talik Eichinger

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"
0
vadim_hr