Porady: czyszczenie silnika pamięci masowej mysql InnoDB?


133

Czy można wyczyścić silnik pamięci masowej mysql innodb, aby nie przechowywał danych z usuniętych tabel?

Czy za każdym razem muszę odbudowywać nową bazę danych?


Co sprawia, że ​​myślisz, że MySQL przechowuje dane z usuniętych tabel?
— Robert Munteanu

1
Jeśli upuszczę całą masę ogromnych tabel, moje pliki pamięci InnoDB się nie zmniejszą
— Bryan Field

2
@RobertMunteanu: patrz bugs.mysql.com/bug.php?id=1341
— maks.

Odpowiedzi:


351

Oto pełniejsza odpowiedź dotycząca InnoDB. To trochę długotrwały proces, ale może być wart wysiłku.

Należy pamiętać, że /var/lib/mysql/ibdata1jest to najbardziej obciążony plik w infrastrukturze InnoDB. Zwykle zawiera sześć rodzajów informacji:

Architektura InnoDB

Architektura InnoDB

Wiele osób tworzy wiele ibdataplików w nadziei na lepsze zarządzanie miejscem na dysku i lepszą wydajność, jednak to przekonanie jest błędne.

Czy mogę biegać OPTIMIZE TABLE?

Niestety, działanie OPTIMIZE TABLEz tabelą InnoDB przechowywaną we współużytkowanym pliku obszaru tabel ibdata1powoduje dwie rzeczy:

  • Sprawia, że ​​dane i indeksy tabeli są ciągłe wewnątrz ibdata1
  • Marki ibdata1rosną, ponieważ sąsiednie danych i indeksów stron są dołączane doibdata1

Możesz jednak oddzielić dane tabeli i indeksy tabel od ibdata1i zarządzać nimi niezależnie.

Czy mogę biegać OPTIMIZE TABLEz innodb_file_per_table?

Załóżmy, że chcesz dodać innodb_file_per_tabledo /etc/my.cnf (my.ini). Czy możesz po prostu uruchomić OPTIMIZE TABLEwszystkie tabele InnoDB?

Dobra wiadomość : Kiedy uruchomisz OPTIMIZE TABLEz innodb_file_per_tablewłączoną, utworzy to .ibdplik dla tej tabeli. Na przykład, jeśli masz tabelę z mydb.mytabledatadir o wartości /var/lib/mysql, zwróci to:

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

.ibdBędą zawierać stron danych i indeksowanie stron dla tej tabeli. Wspaniały.

Złe wieści : wszystko, co zrobiłeś, to wyodrębnienie stron danych i stron indeksu mydb.mytablez miejsca zamieszkania ibdata. Wpis słownika danych dla każdej tabeli, w tym mydb.mytable, nadal pozostaje w słowniku danych (patrz reprezentacja graficzna ibdata1 ). NIE MOŻESZ PO PROSTU SKASOWAĆ W ibdata1TYM PUNKCIE !!! Należy pamiętać, że ibdata1wcale się nie skurczył.

Oczyszczanie infrastruktury InnoDB

Aby zmniejszyć się ibdata1raz na zawsze, wykonaj następujące czynności:

  1. Zrzuć (np. Z mysqldump) wszystkie bazy danych do .sqlpliku tekstowego ( SQLData.sqljest używane poniżej)

  2. Usuń wszystkie bazy danych (z wyjątkiem mysqli information_schema) OSTRZEŻENIE : Zapobiegawczo uruchom ten skrypt, aby upewnić się, że masz wszystkie uprawnienia użytkowników:

    mkdir /var/lib/mysql_grants
    cp /var/lib/mysql/mysql/* /var/lib/mysql_grants/.
    chown -R mysql:mysql /var/lib/mysql_grants
  3. Zaloguj się do mysql i uruchom SET GLOBAL innodb_fast_shutdown = 0;(to całkowicie opróżni wszystkie pozostałe zmiany transakcyjne z ib_logfile0i ib_logfile1)

  4. Zamknij MySQL

  5. Dodaj następujące wiersze do /etc/my.cnf(lub my.iniw systemie Windows)

    [mysqld]
    innodb_file_per_table
    innodb_flush_method=O_DIRECT
    innodb_log_file_size=1G
    innodb_buffer_pool_size=4G

    (Uwaga: niezależnie od tego, do czego masz zestaw innodb_buffer_pool_size, upewnij się, że innodb_log_file_sizejest to 25% innodb_buffer_pool_size.

    Ponadto: innodb_flush_method=O_DIRECTnie jest dostępny w systemie Windows)

  6. Usuń ibdata*i ib_logfile*opcjonalnie możesz usunąć wszystkie foldery z /var/lib/mysqlwyjątkiem /var/lib/mysql/mysql.

  7. Rozpocznij MySQL (Spowoduje to odtworzenie ibdata1[10MB domyślnie] a ib_logfile0i ib_logfile1na każdy 1G).

  8. Import SQLData.sql

Teraz ibdata1będzie nadal rosnąć, ale będzie zawierać tylko metadane tabeli, ponieważ każda tabela InnoDB będzie istnieć poza ibdata1. ibdata1nie będzie już zawierał danych InnoDB i indeksów dla innych tabel.

Na przykład załóżmy, że masz tabelę InnoDB o nazwie mydb.mytable. Jeśli zajrzysz do /var/lib/mysql/mydbśrodka, zobaczysz dwa pliki reprezentujące tabelę:

  • mytable.frm (Nagłówek pamięci masowej)
  • mytable.ibd (Dane tabeli i indeksy)

Dzięki innodb_file_per_tableopcji w /etc/my.cnfmożesz uruchomić, OPTIMIZE TABLE mydb.mytablea plik /var/lib/mysql/mydb/mytable.ibdfaktycznie się zmniejszy.

Robiłem to wiele razy w swojej karierze jako administrator MySQL. W rzeczywistości, gdy to zrobiłem po raz pierwszy, zmniejszyłem plik 50 GB ibdata1 do zaledwie 500 MB!

Spróbuj. Jeśli masz dalsze pytania, po prostu zapytaj. Zaufaj mi; będzie to działać zarówno w perspektywie krótkoterminowej, jak i długoterminowej.

PRZESTROGA

Jeśli w kroku 6, jeśli mysql nie może zostać ponownie uruchomiony z powodu mysqlupuszczenia schematu, spójrz wstecz na krok 2. Wykonałeś fizyczną kopię mysqlschematu. Możesz go przywrócić w następujący sposób:

mkdir /var/lib/mysql/mysql
cp /var/lib/mysql_grants/* /var/lib/mysql/mysql
chown -R mysql:mysql /var/lib/mysql/mysql

Wróć do kroku 6 i kontynuuj

UPDATE 2013-06-04 11:13 EDT

Jeśli chodzi o ustawienie innodb_log_file_size na 25% innodb_buffer_pool_size w kroku 5, ta ogólna reguła jest raczej stara.

Wracając July 03, 2006, Percona miała fajny artykuł, dlaczego wybrać właściwy innodb_log_file_size . Później Nov 21, 2008Percona kontynuowała kolejny artykuł o tym, jak obliczyć właściwy rozmiar w oparciu o szczytowe obciążenie pracą, przy zachowaniu godzinnych zmian .

Od tego czasu napisałem posty w DBA StackExchange na temat obliczania rozmiaru dziennika i odniesienia do tych dwóch artykułów Percona.

Osobiście nadal stosowałbym zasadę 25% przy początkowej konfiguracji. Następnie, ponieważ obciążenie pracą można dokładniej określić w czasie w produkcji, można zmienić rozmiar dzienników podczas cyklu konserwacji w zaledwie kilka minut.


9
Użyłem również opcji innodb_file_per_table ze świetnym efektem, mając 200 baz danych z 200 tabelami każda na jednym serwerze, byłem w stanie połączyć bazy danych z różnicami symbolicznymi na różnych partycjach, tym samym używając więcej buforów IO i wrzecion, które w innym przypadku byłyby dostępne :)
— Dave Rix

2
@SeanDowney BTW pamiętaj, aby podnieść, innodb_open_tablesjeśli to konieczne. Wartość domyślna to 300.
— RolandoMySQLDBA

2
@ giorgio79 musisz ustawić wstawianie zbiorcze na większą wartość. To jest dobra uwaga. Do mojej odpowiedzi dodam istotę Twojego pytania.
— RolandoMySQLDBA

3
W systemach 32-bitowych wartość 4 Gb dla innodb_buffer_pool_size jest niedozwolona. Mysql uruchomi się dyskretnie z wyłączonym innodb, a przywrócone tabele zostaną zmienione na myisam. Użyj nieco mniejszej wartości, aby to naprawić.
— David

5
Mój Boże. Chcę tylko powiedzieć, że to chyba jedna z najlepszych odpowiedzi, jakie kiedykolwiek widziałem na TAK Cholernie dobra robota, sir. Pomogło mi znaleźć rozwiązanie mojego problemu, kiedy otrzymywałem ERROR 2013 (HY000) podczas importowania 154g db. Dzięki za doskonałą odpowiedź!
— Josh Brown

4

Silnik InnoDB nie przechowuje usuniętych danych. Podczas wstawiania i usuwania wierszy niewykorzystane miejsce jest przydzielane w plikach magazynu InnoDB. Z czasem ogólna przestrzeń nie zmniejszy się, ale z czasem „usunięta i zwolniona” przestrzeń zostanie automatycznie ponownie wykorzystana przez serwer DB.

Możesz dalej dostrajać i zarządzać przestrzenią używaną przez silnik poprzez ręczną reorganizację tabel. Aby to zrobić, zrzuć dane z tabel, których dotyczy problem, za pomocą mysqldump, usuń tabele, uruchom ponownie usługę mysql, a następnie utwórz tabele ponownie z plików zrzutu.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.