it-swarm.dev

Jak odzyskać tabelę InnoDB, której pliki zostały przeniesione

Mam więc testowy serwer db skonfigurowany w strumieniu replikacji. Nad nazwą pojawił się optymalizator, który szybko zapełnił miejsce w katalogu danych o niewolnikach. Mysql sumiennie tylko czekał na więcej miejsca.

Ten datadir to system plików używany TYLKO jako datadir mysql, więc nie było nic więcej do zwolnienia.

Miałem 4-gigabajtową tabelę testową innodb, która nie była częścią strumienia replikacji, więc pomyślałem, że spróbuję czegoś, aby sprawdzić, czy to zadziała, a będąc środowiskiem testowym, nie martwiłem się zbytnio, gdyby coś poszło nie tak.

Oto kroki, które podjąłem

  1. Opróżniłem stół, który miałem przenieść
  2. Umieściłem na nim blokadę odczytu (mimo że nic do niej nie zapisywało i nie było jej w strumieniu replikacji)
  3. Skopiowałem .frm i .ibd do systemu plików w/wolnym pokoju
  4. Odblokowano stół
  5. Obcięto tę tabelę - zwolniło to wystarczająco dużo miejsca, aby optymalizacja mogła zakończyć się, a replikacja znów zacznie łączyć.
  6. Zatrzymaj mysql slave/shutdown
  7. Skopiuj plik z tmp z powrotem do katalogu danych
  8. Uruchom ponownie mysql

Nic nie pojawia się w dzienniku .err, wszystko wygląda dobrze. Łączę się i używam mydb; i zobacz tabelę, z którą się bałam w tabelach pokazów. Ale jeśli spróbuję

select * from testtable limit 10;

Dostaję błąd

ERROR 1146 (42S02): Table 'mydb.testtable' doesn't exist

Z tego, co do tej pory mogę powiedzieć, mogę dobrze odczytać ze wszystkich innych tabel, a replikacja rozpoczęła tworzenie kopii zapasowej bez żadnych skarg.

Czy jest coś, co mogę zrobić, aby odzyskać od tego momentu? Mogę go odbudować od podstaw, jeśli zajdzie taka potrzeba, ale byłem ciekawy, co inni myślą o tym przedsięwzięciu w ogóle. Czy w serii kroków, które podjąłem, było coś, co doprowadziłoby do bezbłędnych rezultatów?

Co jeśli to nie był serwer testowy, nie mógłbym po prostu „zrobić tego na żywo” i zobaczyć, co się stanie? Jaki byłby najlepszy sposób na tymczasowe zwolnienie miejsca na produkcyjnym niewolniku, gdybym musiał to lubić?

14
atxdba

Najważniejszą rzeczą, o której większość ludzi zapomina o TABLICIE OBCIĄŻENIA, jest to, że TABLICA OBCIĄŻENIA to DDL, a nie DML . W InnoDB metadane w ibdata1 zawierają numerowaną listę tabel InnoDB. Użycie TRUNCATE TABLE powoduje przesunięcie wewnętrznego identyfikatora metadanych tabeli InnoDB. Dzieje się tak, ponieważ TRUNCATE TABLE skutecznie wykonuje następujące czynności:

Przykład: Aby obciąć tabelę InnoDB o nazwie mydb.mytb

USE mydb
CREATE TABLE newtb LIKE mytb;
ALTER TABLE mytb RENAME oldtb;
ALTER TABLE newtb RENAME mytb;
DROP TABLE oldtb;

Nowy mytb miałby zatem inny wewnętrzny identyfikator metadanych.

Po skopiowaniu pliku .ibd w inne miejsce plik .ibd zawiera w sobie oryginalny wewnętrzny identyfikator metadanych. Samo przywrócenie pliku .ibd nie powoduje uzgodnienia wewnętrznego identyfikatora metadanych z identyfikatorem tego w ibdata1.

Co powinieneś zrobić, to:

Skopiuj plik .ibd tabeli InnoDB. Następnie uruchom to

ALTER TABLE tablename DISCARD TABLESPACE;

Aby przywrócić go później, skopiuj plik .ibd z powrotem do datadir, a następnie uruchom

ALTER TABLE tablename IMPORT TABLESPACE;

Pozwoliłoby to zachować wewnętrzny identyfikator metadanych.

Upewnij się, że plik .frm jest zawsze obecny.

Kiedyś pomogłem klientowi przywrócić 30 tabel InnoDB, które ukrywał w ten sam sposób. Musiałem użyć innego serwera DB i grać w niektóre gry z dodawaniem i upuszczaniem tabel InnoDB, aby wyśledzić poprawny wewnętrzny identyfikator metadanych.

Klient znalazł ten artykuł: http://www.chriscalender.com/?tag=innodb-error-tablespace-id-in-file . Wykorzystaliśmy go i bardzo nam pomogło. Mam nadzieję, że Ci to pomoże.

15
RolandoMySQLDBA