2012-12-27 12 views
9

Piszę skrypt powłoki, aby wykonać mysqldump.Jak zablokować wszystkie tabele w jednym mysql db?

mysqldump -u$BACKUP_USER -p$BACKUP_PASS --flush-logs --lock-tables $DB_NAME > $SQL_FILE 

Magazyn mojego db SILNIK to MyISAM. Więc nie mogę użyć opcji --single-transaction. The --lock-tables blokuje tylko jedną tabelę w postępie mysqldump. Istnieje wiele baz danych w mojej instancji MySQL, nie chcę używać --lock-all-tables, spowoduje to zablokowanie wszystkich baz danych uruchomionych na moim serwerze. Więc, jak zablokować wszystkie tabele w JEDNEJ bazie danych mysql w sametime, więc mogę ją zrzucić?

+1

'' -lock-tables' powinno zablokować wszystkie stoły do ​​zrzucenia przed ich zrzuceniem. Co sprawia, że ​​myślisz, że tego nie robi? – cdhowie

+0

Mam test w mysql 5.1, kiedy używam --lock-tables w mysqldump, nadal mogę wstawić dane do tabeli bazy danych $ DB_NAME. – KeepZero

Odpowiedz

4

Powinieneś zajrzeć do tej opcji.

FLUSH TABLES WITH READ LOCK

Zamyka wszystkie otwarte tabele i zamki Wszystkie tabele dla wszystkich baz danych z globalnej blokady odczytu. Jest to bardzo wygodny sposób, aby uzyskać kopie ...

http://dev.mysql.com/doc/refman/5.0/en/flush.html

+0

'FLUSH TABLES WITH READ LOCK' – Benjamin

+0

Powoduje to * globalną * blokadę odczytu, a nie tylko tabele w jednej bazie danych. –

6

Nie najładniejszy rozwiązanie zdecydowanie, ale to działa. Miałem taką samą potrzebę i oto moje rozwiązanie, nieco zmodyfikowane, aby pasowało do twoich nazw zmiennych. Zakładam, że korzystasz z MySQL na Linuksie, ponieważ opiera się on w dużym stopniu na semantyce BASH powłoki. Jeśli jesteś w systemie Windows, prawdopodobnie to nie zadziała.

# Mysql script to lock all tables in one DB 
# (such as to get a consistent export dump of one database) 

MYSQLCMD="mysql -u$BACKUP_USER -p$BACKUP_PASS -A" 

function lock_db { 
    [ -e "/tmp/mysql-db-lock-${1}" ] && rm "/tmp/mysql-db-lock-${1}" 
    mkfifo "/tmp/mysql-db-lock-${1}" 
    (
    (
     echo "SELECT CONCAT('LOCK TABLES ' 
      , GROUP_CONCAT(CONCAT('\`',table_name,'\`'),' WRITE') 
      , ';' 
      ) AS \"-- Statement to lock tables\" 
     FROM information_schema.tables 
     WHERE table_schema='${1}' 
     ORDER BY table_name; 
     " | $MYSQLCMD 
     echo "\! cat '/tmp/mysql-db-lock-${1}' >/dev/null" 
     echo 'UNLOCK TABLES;' 
    ) | $MYSQLCMD -D"${1}" 
    rm "/tmp/mysql-db-lock-${1}" 
) & 
} 

function unlock_db { 
    >"/tmp/mysql-db-lock-${1}" 
} 

# Lock one database, all tables 
lock_db $DB_NAME 

# Verify locks have been placed 
echo "SHOW OPEN TABLES WHERE in_use != 0" | $MYSQLCMD 

# Do whatever here that you needed the locked db for 
mysqldump -u$BACKUP_USER -p$BACKUP_PASS $DB_NAME > $SQL_FILE 

# Release locks 
unlock_db $DB_NAME 

# Verify locks released 
echo "SHOW OPEN TABLES WHERE in_use != 0" | $MYSQLCMD 
+0

Użytkownik wybiera każdą z tabel z bazy danych. Może to być lepsze niż "FLUSH TABLES WITH READ LOCK", który blokuje wszystkie tabele we wszystkich bazach danych, ale wydaje się, że twoje rozwiązanie kończy się niepowodzeniem z bazą danych zawierającą wiele tabel (przynajmniej dla mnie). Zmieniłem go za pomocą "TABELE FLUSH WITH READ LOCK" (który blokuje wszystkie tabele we wszystkich bazach danych) i usunąłem pierwszy potok do $ MYSQLCMD. – OderWat

+0

AKTUALIZACJA: użyłem "SET SESSION group_concat_max_len = 8192;" przed pierwszym ECHO, ponieważ to właśnie było przyczyną problemu! TY dla ciebie fajny scenariusz! – OderWat

+0

Przygotuj się, jeśli chcesz. –

2

Oto jak to zrobiłem. Powinien działać we wszystkich przypadkach, ponieważ używa 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 !" 

Skorupa sleep komenda jest tylko, aby upewnić się, że zadanie tło uruchamiając polecenie blokowania mysql jest wykonywana przed rozpoczęciem mysqldump. Możesz zmniejszyć to do 1 sekundy i nadal powinno być dobrze. Zwiększ ją do 30 sekund i spróbuj wstawić wartości do dowolnej tabeli od innego klienta w ciągu tych 30 sekund, gdy zobaczysz, że jest zablokowana.

Istnieją 2 zalety korzystania z tej ręcznego blokowania tła, zamiast przy użyciu mysqldump opcje --single-transaction i --lock-tables:

  1. Blokuje wszystko, jeśli mają mieszane tabel MyISAM/InnoDB.
  2. Możesz wykonywać inne polecenia oprócz mysqldump w tym samym okresie blokowania. Jest to użyteczne, na przykład, podczas konfigurowania replikacji na węźle głównym, ponieważ musisz uzyskać pozycję dziennika binarnego z SHOW MASTER STATUS; dokładnie w stanie utworzonego zrzutu (przed odblokowaniem bazy danych), aby móc utworzyć urządzenie podrzędne replikacji .
+0

Powoduje to również * globalną * blokadę we wszystkich bazach danych, nawet podczas tworzenia kopii zapasowej pojedynczej bazy danych. –

Powiązane problemy