Czy mogę przywrócić pojedynczą tabelę z pełnego pliku mysql mysqldump?

194

Mam kopię zapasową mysqldump mojej bazy danych mysql składającej się ze wszystkich naszych tabel, która ma około 440 MB. Chcę przywrócić zawartość tylko jednej tabeli z mysqldump. czy to możliwe? Teoretycznie mógłbym po prostu wyciąć sekcję, która odbudowuje tabelę, której chcę, ale nawet nie wiem, jak skutecznie edytować dokument tekstowy o takim rozmiarze.

Mobiusa
źródło
2
FWIW, możesz również użyć mydumper . Tworzy to logiczny zrzut, taki jak mysqldump, ale generuje osobne pliki na tabelę i może zarówno zrzucać, jak i ładować wielowątkowo, więc zajmuje to mniej czasu.
Bill Karwin

Odpowiedzi:

289

Możesz spróbować użyć sed, aby wyodrębnić tylko żądaną tabelę.

Powiedzmy, że nazwa Twojej tabeli to, mytablea plik mysql.dump to plik zawierający twój wielki zrzut:

$ sed -n -e '/CREATE TABLE.*`mytable`/,/CREATE TABLE/p' mysql.dump > mytable.dump

Spowoduje to skopiowanie do pliku mytable.dumptego, co znajduje się pomiędzy, CREATE TABLE mytablei następnego CREATE TABLEodpowiadającego następnej tabeli.

Następnie możesz dostosować plik mytable.dumpzawierający strukturę tabeli mytablei dane (lista INSERT).

uloBasEI
źródło
5
To jest nawet ładniejsze niż moja odpowiedź, ponieważ zajmuje się również TWORZENIEM TABELI, ale powinieneś szukać z cudzysłowami, aby nie dostać kolejnej tabeli o nazwie „thisismytabletoo”.
JCCyC
1
Prawdziwe. Nie byłem pewien, czy nazwy tabel we wszystkich zrzutach mysql są zawsze otoczone odwrotnym cytatem, czy też „CREATE TABLE mytable” może być również możliwe. Możemy łatwo dostosować pierwsze wyrażenie regularne, jeśli wiemy, jak wygląda zrzut. Drugim problemem może być sytuacja, gdy tabela mytable nie jest unikalna (jedna w bazie danych db1, a druga w bazie danych db2). Oba zostaną wyeksportowane do pliku mytable.dump. Jeśli tabela nie jest unikalna, możemy użyć tego samego polecenia sed, najpierw z CREATE DATABASE, aby wyodrębnić tylko odpowiednią bazę danych. Następnie użyj polecenia sed z CREATE TABLE.
uloBasEI
13
Słodkie! Pamiętaj, aby dodać DROP TABLE na górze i usunąć DROP TABLE [następna tabela] na dole pliku.
Nathan
20
Aby nie dodawać / usuwać DROP TABLE, bardziej przydatne jest dopasowanie przez Table structure for tablekomentarz, zamiast dopasowania przez CREATE TABLE. Zapewni to, że następna tabela nie zostanie upuszczona, jeśli zapomni się usunąć jej instrukcję DROP TABLE, i umożliwi przesyłanie potokowe w celu przywracania tabeli jednego polecenia (gzip | sed | mysql). Jednak to rozwiązanie zależy od składni komentarzy mysqldump (nie wiem, jak to jest standard).
Olexa
12
Z modyfikacją Olexa jest idealna: sed -n -e '/ Struktura tabeli dla. * `Mytable /, / Struktura tabeli dla / p' whole.sql> mytable.sql
deeenes
120

Użyłem zmodyfikowanej wersji polecenia sed uloBasEI. Zawiera poprzednie polecenie DROP i odczytuje, aż mysql zrzuci dane do twojej tabeli (ODBLOKUJ). Pracowałem dla mnie (re) importowanie wp_users na kilka stron Wordpress.

sed -n -e '/DROP TABLE.*`mytable`/,/UNLOCK TABLES/p' mydump.sql > tabledump.sql
bryn
źródło
3
jest to w rzeczywistości znacznie lepsze rozwiązanie niż to wybrane powyżej. Nie mogę uwierzyć, że to nie było więcej pozytywnych opinii.
RICh
9
Sugeruję dodanie co najmniej zwrotnych cudzysłowów do nazwy tabeli: `mytable`aby uniknąć dopasowania tabel mytable2i tak dalej, jak w moim przypadku.
bartekbrak
3
właśnie uratowałeś mi tyłek
Gabriel Alack,
1
@ user706420 Hmm, czy jesteś pewien, że twój terminal nie był winny? sednie powinien zakłócać kodowania ...
bryn
6
Dla osób z plikami SQL niezawierającymi DROP TABLE(mój zrzut MySQL tego nie miał) może chcieć użyć: sed -n -e '/-- Table structure for table ``<Table Name>/,/UNLOCK TABLES/p' <SQL File> > table.sql Wykorzystuje to komentarze do tabeli podane przed każdą tabelą w zrzutu MySQl i zapewnia, że ​​wiersze takie jak /*!40101 SET @saved_cs_client = @@character_set_client */;dołączą się.
hamx0r
50

Można to zrobić łatwiej? Oto jak to zrobiłem:

Utwórz tymczasową bazę danych (np. Przywróć):

mysqladmin -u root -p utwórz przywracanie

Przywróć pełny zrzut w tymczasowej bazie danych:

mysql -u root -p restore <fulldump.sql

Zrzuć tabelę, którą chcesz odzyskać:

mysqldump restore mytable> mytable.sql

Zaimportuj tabelę do innej bazy danych:

mysql -u root -p baza danych <mytable.sql

Martijn Kools
źródło
2
Tego potrzebuje większość ludzi.
sjas,
2
Zgodnie z tą sugestią edycji powinieneś dodać parametr „--one-database”, aby mieć pewność, że przywrócisz tylko jedną bazę danych i nie zniszczysz wszystkiego innego.
SL Barth - Przywróć Monikę
7
W przypadku naprawdę dużego db może to być bardzo dziwne - przywrócić 150 GB danych dla jednej tabeli 100 MB.
Enyby,
Właśnie uruchomiłem to bez „--one-database” i nadal dobrze scaliłem tabele. Nie usunęło moich istniejących tabel.
Qasim
1
Bardzo zła praktyka! Zrzuciłem kilka baz danych i próbując przywrócić tylko jedną, usunąłem wszystkie pozostałe.
AndreyP
11

Prostym rozwiązaniem byłoby po prostu utworzenie zrzutu tylko tabeli, którą chcesz przywrócić osobno. Aby to zrobić, możesz użyć komendy mysqldump, stosując następującą składnię:

mysqldump -u [user] -p[password] [database] [table] > [output_file_name].sql

Następnie zaimportuj go w normalny sposób, a on zaimportuje tylko zrzuconą tabelę.

Brom558
źródło
9

Tak czy inaczej, każdy proces, który to zrobi, będzie musiał przejść przez cały tekst zrzutu i w jakiś sposób go przeanalizować. Po prostu chciałbym

INSERT INTO `the_table_i_want`

i potokuj wyjście do mysql. Spójrz na pierwszy stół na wysypisku, aby upewnić się, że otrzymujesz INSERT we właściwy sposób.

Edycja: OK, tym razem poprawne formatowanie.

JCCyC
źródło
Jestem głupi, że nie od razu pomyślałem o zrobieniu tego. Wygląda na to, że Grep ratuje mój bekon każdego dnia. Pozostałe dwie sugestie również były super i całkowicie to, co zrobiłbym bez dostępnych cudów grep. Dziękuję wam wszystkim!
Mobius
6
Jeśli uważasz, że kochasz grep, kiedy nauczysz się awk, staniesz się jego szczęśliwym niewolnikiem seksualnym: en.wikipedia.org/wiki/Awk
JCCyC
7

Powinieneś wypróbować komendę @bryn, ale używając separatora `w przeciwnym razie wypakujesz również tabele posiadające prefiks lub sufiks, zwykle tak robię:

sed -n -e '/DROP TABLE.*`mytable`/,/UNLOCK TABLES/p' dump.sql > mytable.sql

Również do celów testowych możesz zmienić nazwę tabeli przed importem:

sed -n -e 's/`mytable`/`mytable_restored`/g' mytable.sql > mytable_restored.sql

Aby zaimportować, możesz użyć polecenia mysql:

mysql -u root -p'password' mydatabase < mytable_restore.sql
Maxime Biette
źródło
6
  1. Utworzyć kopię zapasową

    $ mysqldump -A | gzip > mysqldump-A.gz
  2. Przywróć pojedynczy stół

    $ mysql -e "truncate TABLE_NAME" DB_NAME
    $ zgrep ^"INSERT INTO \`TABLE_NAME" mysqldump-A.gz | mysql DB_NAME
y.tk
źródło
4

Jednym z możliwych sposobów rozwiązania tego problemu jest przywrócenie do tymczasowej bazy danych i zrzucenie tylko tej tabeli z tymczasowej bazy danych. Następnie użyj nowego skryptu.

Tim Hoolihan
źródło
3
sed -n -e '/-- Table structure for table `my_table_name`/,/UNLOCK TABLES/p' database_file.sql > table_file.sql

Jest to lepsze rozwiązanie niż niektóre z powyższych, ponieważ nie wszystkie zrzuty SQL zawierają DROP TABLEinstrukcję. Ten będzie działał będzie wszelkiego rodzaju zrzuty.

Weston Ganger
źródło
2

To też może pomóc.

# mysqldump -u root -p database0 > /tmp/database0.sql
# mysql -u root -p -e 'create database database0_bkp'
# mysql -u root -p database0_bkp < /tmp/database0.sql
# mysql -u root -p database0 -e 'insert into database0.table_you_want select * from database0_bkp.table_you_want'
Pjl
źródło
2

Tabela powinna prezentować się z taką samą strukturą zarówno w zrzutu, jak i bazie danych.

`zgrep -a ^"INSERT INTO \`table_name" DbDump-backup.sql.tar.gz | mysql -u<user> -p<password> database_name`

lub

`zgrep -a ^"INSERT INTO \`table_name" DbDump-backup.sql | mysql -u<user> -p<password> database_name`
Neminath
źródło
1

Większość współczesnych edytorów tekstu powinna być w stanie obsłużyć plik tekstowy o takim rozmiarze, jeśli twój system sobie z tym poradzi.

W każdym razie musiałem to zrobić bardzo szybko i nie miałem czasu na znalezienie żadnych narzędzi. Założyłem nową instancję MySQL, zaimportowałem całą kopię zapasową, a następnie wyplułem tylko tabelę, którą chciałem.

Następnie zaimportowałem tę tabelę do głównej bazy danych.

To było nudne, ale raczej łatwe. Powodzenia.

Bryan Migliorisi
źródło
1

Możesz użyć edytora vi. Rodzaj:

vi -o mysql.dump mytable.dump

aby otworzyć zarówno cały zrzut, jak mysql.dumpi nowy plik mytable.dump. Znajdź odpowiednią wstawkę do wiersza, naciskając, /a następnie wpisz frazę, na przykład: „wstaw do„ mytable ””, a następnie skopiuj ten wiersz za pomocą yy. Przełącz do następnego pliku przez ctrl+wnastępnie down arrow keywklej skopiowany linię pp. Na koniec zapisz nowy plik, wpisując :wqi całkiem edytor vi przez :q.

Zauważ, że jeśli wyrzucił dane przy użyciu wielu wkładek można skopiować (yank) wszystkie naraz używając Nyyw którym Njest liczba linii do skopiowania.

Zrobiłem to z plikiem o wielkości 920 MB.

mtoloo
źródło
0

Zdobądź przyzwoity edytor tekstu, taki jak Notepad ++ lub Vim (jeśli jesteś już biegły). Wyszukaj nazwę tabeli i powinieneś być w stanie wyróżnić tylko polecenia CREATE, ALTER i INSERT dla tej tabeli. Poruszanie się za pomocą klawiatury zamiast myszy może być łatwiejsze. I upewniłbym się, że jesteś na komputerze z dużą ilością pamięci RAM, aby nie było problemu z załadowaniem całego pliku na raz. Po zaznaczeniu i skopiowaniu potrzebnych wierszy dobrym pomysłem byłoby wykonanie kopii zapasowej tylko skopiowanej części do własnego pliku kopii zapasowej, a następnie zaimportowanie jej do MySQL.

Cameron
źródło
1
Jest to naprawdę bardzo łatwe do zrobienia i zrozumiałe nawet dla początkujących. Nie wiem, dlaczego jest to przegłosowane.
Karl Johan Vallner
0

Fragmenty SQL są blokowane za pomocą „Struktura tabeli dla tabeli my_table” i „Zrzut danych dla tabeli my_table”.

Możesz użyć wiersza poleceń systemu Windows w następujący sposób, aby uzyskać numery wierszy dla różnych sekcji. Dostosuj szukany ciąg według potrzeb.

znajdź / n ”dla tabeli„ ”sql.txt

Zostaną zwrócone:

---------- SQL.TXT

[4384] - Struktura tabeli dla tabeli my_table

[4500] - Zrzut danych dla tabeli my_table

[4514] - Struktura tabeli dla tabeli some_other_table

... itd.

To daje ci numery linii, których potrzebujesz ... teraz, gdybym tylko wiedział, jak ich używać ... badać.

Kuyenda
źródło
0

Wspomniane wcześniej rozwiązania „sed” są fajne, ale jak wspomniano, nie w 100% bezpieczne

  • Możesz mieć komendy INSERT z danymi zawierającymi: ... CREATE TABLE ... (cokolwiek) ... mytable ...

  • lub nawet dokładny ciąg „CREATE TABLE` mytable`; ” jeśli na przykład przechowujesz polecenia DML!

(a jeśli stół jest ogromny, nie chcesz tego sprawdzać ręcznie)

Sprawdziłbym dokładną składnię użytej wersji zrzutu i miałbym bardziej restrykcyjne wyszukiwanie wzorców:

Unikaj „. *” I użyj „^”, aby upewnić się, że zaczniemy od początku linii. I wolałbym wziąć początkowy „DROP”

Podsumowując, działa to dla mnie lepiej:

sed -n -e '/^DROP TABLE IF EXISTS \`mytable\`;/,/^UNLOCK TABLES;/p' mysql.dump > mytable.dump
phil_w
źródło