Linux / mysql: czy bezpiecznie jest kopiować pliki db mysql za pomocą komendy cp z jednego db na inny?

11

Większość przewodników zaleca mysqldump i prosty SQL do kopiowania jednej tabeli do innej bazy danych. A co z linuksem powłoki cp? Mogę po prostu zrobić

cp /db1/mytable.frm /db2/mytable.frm

giorgio79
źródło

Odpowiedzi:

21

Kopiowanie jest bardzo proste dla MyISAM i całkowicie ryzykowne (prawie samobójcze) z InnoDB.

Z twojego pytania, które wychowałeś

cp /db1/mytable.frm /db2/mytable.frm

MyISAM

To jest OK do zrobienia. Nie można jednak po prostu przenieść pliku .frm. Musisz przenieść wszystkie elementy. Z twojego pytania weźmy tabelę o nazwie db1.mytable. W normalnej instalacji tabela znajduje się w / var / lib / mysql / db1. Tabela składałaby się z trzech plików.

  • /var/lib/mysql/db1/mytable.frm
  • /var/lib/mysql/db1/mytable.MYD (baza danych tabel)
  • /var/lib/mysql/db1/mytable.MYI (indeksy tabel)

Musisz przenieść wszystkie trzy pliki, aby przenieść jedną tabelę. Jeśli wszystkie tabele używają silnika pamięci MyISAM, możesz zamknąć mysql i skopiować. Jeśli po prostu tworzysz kopię tabeli i umieszczasz ją w innej bazie danych, powinieneś to zrobić za pomocą SQL.

Na przykład, jeśli chcesz skopiować plik db1.mytable do bazy danych db2, wykonaj następujące czynności:

CREATE TABLE db2.mytable LIKE db1.mytable;
ALTER TABLE db2.mytable DISABLE KEYS;
INSERT INTO db2.mytable SELECT * FROM db1.mytable;
ALTER TABLE db2.mytable ENABLE KEYS;

Teraz, jeśli po prostu przenosisz tabelę z db1 na db2, możesz to zrobić:

ALTER TABLE db1.mytable RENAME db2.mytable;

InnoDB

Kopiowanie jest bardzo niebezpieczne ze względu na infrastrukturę, na której działa InnoDB. Istnieją dwie podstawowe infrastruktury: 1) wyłączona tabela_plików_pliku_internatywnego i 2) włączona tabela plików_plików_nodb_pliku

Piętą achillesową InnoDB jest systemowy plik obszaru tabel znany jako ibdata1 (zwykle znajduje się w / var / lib / mysql). Co zawiera ten plik ?

  • Strony danych tabeli
  • Tabele indeksu stron
  • Table MetaData (lista zarządzania identyfikatorami obszaru tabel)
  • Dane MVCC (w celu wsparcia izolacji transakcji i zgodności z ACID )

InnoDB (wyłączony plik_nodb_pliku_peratury)

Przy wyłączonej innodb_file_per_table wszystkie te typy informacji InnoDB są dostępne w ibdata1. Jedynym przejawem dowolnej tabeli InnoDB poza ibdata1 jest plik .frm tabeli InnoDB. Kopiowanie wszystkich danych InnoDB jednocześnie wymaga skopiowania wszystkich plików / var / lib / mysql.

Kopiowanie pojedynczej tabeli InnoDB jest całkowicie niemożliwe. Musisz mysqldump, aby wyodrębnić zrzut tabeli jako logiczną reprezentację danych i odpowiadających im definicji indeksu. Następnie załadujesz ten zrzut do innej bazy danych na tym samym serwerze lub innym serwerze.

InnoDB (włączony plik innodb_file_per_table)

Przy włączonej opcji innodb_file_per_table dane tabeli i jej indeksy znajdują się w folderze bazy danych obok pliku .frm. Na przykład dla tabeli db1.mytable przejawem tej tabeli InnoDB poza ibdata1 byłoby:

  • /var/lib/mysql/db1/mytable.frm
  • /var/lib/mysql/db1/mytable.ibd

Wszystkie metadane dla db1.mytable nadal znajdują się w ibdata1 i nie ma absolutnie żadnej możliwości uniknięcia tego . Ponów dzienniki i dane MVCC również nadal działają z ibdata1.

OSTRZEŻENIE (lub NIEBEZPIECZEŃSTWO, jak powiedziałby Robot w Lost in Space )

Jeśli zastanawiasz się nad skopiowaniem pliku .frm i .ibd, czeka Cię świat cierpienia. Skopiowanie pliku .frm i .ibd tabeli InnoDB jest dobre tylko wtedy, gdy możesz zagwarantować, że identyfikator obszaru tabel pliku .ibd jest dokładnie zgodny z wpisem id obszaru tabel w metdanych pliku ibdata1.

Napisałem dwa posty w DBA StackExchange na temat tej koncepcji identyfikatora obszaru tabel

Oto doskonały link do tego, jak ponownie podłączyć plik .ibd do ibdata1 w przypadku niedopasowanych identyfikatorów obszaru tabel: http://www.chriscalender.com/?tag=innodb-error-tablespace-id-in-file . Po przeczytaniu tego powinieneś zobaczyć, dlaczego powiedziałem prawie samobójcze.

W przypadku InnoDB wystarczy to zrobić

CREATE TABLE db2.mytable LIKE db1.mytable;
INSERT INTO db2.mytable SELECT * FROM db1.mytable;

zrobić kopię tabeli InnoDB. Jeśli migrujesz go na inny serwer DB, użyj mysqldump.

RolandoMySQLDBA
źródło
4
Inne odpowiedzi mówiły to, więc być może „jest to oczywiste”, ale i tak warto powiedzieć: InnoDB nadal zapisuje pliki, nawet jeśli baza danych jest bezczynna, więc kopiowanie plików podczas działania MySQL jest prawie pewne, że spowoduje uszkodzenie! Możesz zamknąć, zrobić migawkę systemu plików lub użyć Percona XtraBackup, aby obejść ten problem.
Baron Schwartz,
1
Doskonała odpowiedź jak zawsze, @Rolando! Jedyne duże pytanie, jakie mam: dlaczego ktoś chciałby to zrobić, zamiast robić proste zrzuty i importowanie MySQL? Zakładam, że rozmiar bazy danych jest zwykły, ale uważam, że należy to poruszyć.
JakeGould,
1
@JakeGould Ładowanie skryptu mysqldump do mysql wymaga przetworzenia dużej ilości SQL, wstawiania tysięcy wierszy na raz, korzystania z cykli procesorów, rozwijania planów wyjaśniania, przebudowywania indeksów (wstawienia BTree, podziały węzłów liści, klucze równoważenia, skanowanie tabeli dla każdego nie -unique to build) tylko do wyprodukowania tego samego stołu. W przypadku MyISAM po co wymyślać koło? Tylko kopia .frm, .MYDi .MYI.
RolandoMySQLDBA
@JakeGould W przypadku InnoDB skopiowałem bazę danych na żywo, która używała wszystkich InnoDB z rsync. Po skopiowaniu przy użyciu rsync uruchomiłem zamknięcie mysql, wykonałem końcowy rsync i ponownie uruchomiłem mysql bez problemów. Napisałem post jak wcześniej: serverfault.com/questions/288140
RolandoMySQLDBA
8

Kopiowanie całego katalogu danych MySQL jest praktyczną techniką, zakładając, że usługa MySQL jest zatrzymana i chcesz skopiować cały serwer bazy danych.

Jest to przydatna technika do przenoszenia baz danych z dużymi indeksami, a zrzut mysql nie będzie zawierał indeksów, które trzeba będzie zregenerować podczas importu. Uważam tę technikę za przydatną podczas konfigurowania slaveów MySQL.

Kopiowanie pojedynczego pliku zależy od używanego schematu tabeli, ale w większości przypadków nie jest odpowiednim rozwiązaniem.

Coops
źródło
2
Wyjaśniając: nie musisz zatrzymywać usługi per se, jeśli twój system plików jest w stanie, możesz albo wykonać migawkę LVM i wykonać kopię zapasową; lub zamrozić sam system plików.
cienki
Tak długo, jak osoba może jeść przestoje, jest to najłatwiejszy sposób. +1 !!!
RolandoMySQLDBA
2

Użyj xtrabackup w / ow bez innobackupex wrappera, a będziesz dobrze zarówno w bazach danych myisam, jak i innodb. Pamiętaj, że przywracanie baz danych innodb to nie tylko kopiowanie plików, nawet jeśli używasz xtrabackup. Powiedz, jeśli potrzebujesz więcej informacji

Gabor Vincze
źródło
1

Nie, powinieneś wykonać kopię zapasową za pomocą mysqdump i przywrócić za pomocą narzędzia mysql cli, kopiując plik frm, kopiujesz tylko strukturę tabeli, a nie dane w środku, a jeśli jesteś na innodb, skopiuj plik bezpośrednio, to nie jest możliwe.

Najlepszym sposobem jest zrzut i przywrócenie tabeli.

Aleroot
źródło