`BŁĄD 1114 (HY000) tabela… jest pełna” z ustawionym na autodekresie innodb_file_per_table

26

Mam bazę danych MySQL, która zawiera dużą ilość danych (100-200 GB - kilka pomiarów naukowych). Zdecydowana większość danych jest przechowywana w jednej tabeli Sample. Teraz tworzę replikę podrzędną bazy danych i chciałem wykorzystać zalety innodb_file_per_tabletego procesu. Więc ustawiłem innodb_file_per_tablew mojej konfiguracji slave i zaimportowałem zrzut bazy danych. Ku mojemu zaskoczeniu nie udało się

BŁĄD 1114 (HY000) w wierszu 5602: Tabela „Próbka” jest pełna

Plik Sample.ibdma obecnie około 93 GB, a partycja zawiera ponad 600 GB wolnego miejsca, więc nie jest to problem z wolnym miejscem na dysku. Wydaje się, że nie osiąga żadnego limitu systemu plików (używam ext4).

Byłbym wdzięczny za wszelkie pomysły, które mogą być przyczyną lub co należy zbadać.


Aktualizacja: używam mysql Ver 14.14 Distrib 5.1.66, for debian-linux-gnu (x86_64).

SELECT @@datadir; -- returns `/home/var/lib/mysql/`
SHOW VARIABLES LIKE '%innodb_data_file_path%'; -- ibdata1:10M:autoextend 

df -h /home/var/lib/mysql/
768G   31G  699G   5% /home
Petr Pudlák
źródło

Odpowiedzi:

33

FAKTY

Powiedziałeś, że używasz ext4. Limit rozmiaru pliku to 16 TB. Dlatego Sample.ibdnie powinien być pełny.

Mówiłeś swoje innodb_data_file_pathIS ibdata1:10M:autoextend. W związku z tym sam plik ibdata1 nie ma ograniczenia rozmiaru poza systemem operacyjnym.

Dlaczego w ogóle pojawia się ta wiadomość? Zauważ, że komunikat brzmi „Tabela ... jest pełna”, a nie „Dysk ... jest pełny”. Ten warunek pełnej tabeli wynika z logicznego punktu widzenia . Pomyśl o InnoDB. Jakie interakcje mają miejsce?

Domyślam się, że InnoDB próbuje załadować 93 GB danych jako pojedynczą transakcję. Skąd Table is Fullpochodzi wiadomość? Chciałbym spojrzeć na ibdata1, nie pod względem jego fizycznego rozmiaru (który już wykluczyłeś), ale pod kątem osiąganych limitów transakcji.

Co znajduje się w ibdata1, gdy włączona jest opcja innodb_file_per_table i ładujesz nowe dane do MySQL?

  • Słownik danych
  • Podwójny bufor zapisu
    • Siatka bezpieczeństwa zapobiegająca uszkodzeniu danych
    • Pomaga ominąć system operacyjny dla buforowania
  • Wstaw bufor (usprawnia zmiany w indeksach wtórnych)
  • Wycofywanie segmentów
  • Cofnij dzienniki
  • Kliknij tutaj, aby zobaczyć obrazowe przedstawienie ibdata1

Moje podejrzenia mówią mi, że winni są Cofnij Dzienniki i / lub Ponów Dzienniki.

Co to są te dzienniki? Według książki

sxs

Rozdział 10: „Silniki magazynujące” Strona 203 W paragrafach 3,4 podano:

Silnik InnoDB zachowuje dwa typy dzienników: dziennik cofania i dziennik powtarzania. Dziennik cofania służy do wycofywania transakcji, a także do wyświetlania starszych wersji danych dla zapytań działających na wymaganym poziomie izolacji transakcji. Kod obsługujący dziennik cofania można znaleźć w storage / innobase / buf / log / log0log.c .

Celem dziennika ponownych zapisów jest przechowywanie informacji, które zostaną wykorzystane podczas odzyskiwania po awarii. Pozwala procesowi odzyskiwania na ponowne wykonanie transakcji, które mogły lub nie zostały zakończone przed awarią. Po ponownym wykonaniu tych transakcji baza danych jest doprowadzana do spójnego stanu. Kod zajmujący się dziennikiem powtórzeń można znaleźć w storage / innobase / log / log0recv.c .

ANALIZA

W ibdata1 znajduje się 1023 dzienników cofania (patrz Wycofywanie segmentów i cofanie spacji) . Ponieważ dzienniki cofania przechowują kopie danych, które pojawiły się przed ponownym załadowaniem, wszystkie dzienniki cofania 1023 osiągnęły limit. Z innej perspektywy wszystkie dzienniki cofania 1023 mogą być poświęcone jednej transakcji, która ładuje Sampletabelę.

ALE POCZEKAJ...

Prawdopodobnie mówisz „ładuję pustą Sampletabelę”. W jaki sposób zaangażowane są dzienniki cofania? Zanim Sampletabela została załadowana 93 GB danych, była pusta. Reprezentowanie każdego nieistniejącego wiersza musi zajmować trochę miejsca do czyszczenia domu w dziennikach cofania. Wypełnianie 1023 dzienników cofania wydaje się banalne, biorąc pod uwagę ilość napływających danych ibdata1. Nie jestem pierwszą osobą, która to podejrzewa:

Z dokumentacji MySQL 4.1 zwróć uwagę Posted by Chris Calender on September 4 2009 4:25pm:

Zauważ, że w 5.0 (wcześniejszych niż 5.0.85) i 5.1 (wcześniejszych niż 5.1.38) możesz otrzymać błąd „tabela jest pełna” dla tabeli InnoDB, jeśli w InnoDB zabraknie cofnięć (błąd # 18828).

Oto raport o błędzie dla MySQL 5.0: http://bugs.mysql.com/bug.php?id=18828

PROPOZYCJE

Kiedy tworzysz mysqldump Sampletabeli, użyj --no-autocommit

mysqldump --no-autocommit ... mydb Sample > Sample.sql

Spowoduje to wyraźne COMMIT;po każdym INSERT. Następnie załaduj ponownie stół.

Jeśli to nie zadziała ( nie spodoba ci się to ), zrób to

mysqldump --no-autocommit --skip-extended-insert ... mydb Sample > Sample.sql

Dzięki temu każdy WSTAW ma tylko jeden wiersz. Mysqldump będzie znacznie większy (ponad 10 razy większy) i jego przeładowanie może potrwać od 10 do 100 razy dłużej.

W obu przypadkach pozwoli to uniknąć zalania dzienników cofania.

Spróbuj !!!

AKTUALIZACJA 2013-06-03 13:05 EDT

DODATKOWE SUGESTIE

Jeśli tabela systemowa InnoDB (aka ibdata1) osiągnie limit rozmiaru pliku i nie można użyć dzienników cofania, możesz po prostu dodać inny systemowy obszar tabel (ibdata2).

Właśnie zetknąłem się z tą sytuacją zaledwie dwa dni temu. Zaktualizowałem mój stary post tym, co zrobiłem: Zobacz Projektowanie bazy danych - Tworzenie wielu baz danych, aby uniknąć bólu głowy związanego z ograniczeniem rozmiaru tabeli

Zasadniczo musisz zmienić ścieżkę do pliku innodb_data_file_path, aby uwzględnić nowy systemowy plik obszaru tabel. Pozwól mi wyjaśnić, jak:

SCENARIUSZ

Na dysku (ext3) serwer mojego klienta miał:

[root@l*****]# ls -l ibd*
-rw-rw---- 1 s-em7-mysql s-em7-mysql     362807296 Jun  2 00:15 ibdata1
-rw-rw---- 1 s-em7-mysql s-em7-mysql 2196875759616 Jun  2 00:15 ibdata2

Ustawienie było

innodb_data_file_path=ibdata1:346M;ibdata2:500M:autoextend:max:10240000M

Zauważ, że ibdata2wzrosła do 2196875759616, co jest 2145386484M.

Musiałem osadzić rozmiar pliku ibdata2w innodb_data_file_path i dodaćibdata3

innodb_data_file_path=ibdata1:346M;ibdata2:2196875759616;ibdata3:10M:autoextend

Po ponownym uruchomieniu mysqld zadziałało:

[root@l*****]# ls -l ibd*
-rw-rw---- 1 s-em7-mysql s-em7-mysql     362807296 Jun  3 17:02 ibdata1
-rw-rw---- 1 s-em7-mysql s-em7-mysql 2196875759616 Jun  3 17:02 ibdata2
-rw-rw---- 1 s-em7-mysql s-em7-mysql   32315015168 Jun  3 17:02 ibdata3

W ciągu 40 godzin ibdata3wzrosła do 31G. MySQL po raz kolejny działał.

RolandoMySQLDBA
źródło
Zgaduję po imieniu właściciela, że ​​twój klient używał nadchodzącego narzędzia do monitorowania ... Dzięki, wygląda na to, że to również rozwiązało problem.
Steve
Zastanawiam się, czy to nadal problem (mam nadzieję, że nie)
Evan Carroll
3

Miałem ten sam problem i po prostu zrobiłem jedną rzecz i zadziałało.

Wygląda na to, że masz zbyt mały maksymalny rozmiar innodb_data_file_pathw swoim my.cnfpliku konfiguracyjnym. Po prostu zmień poniższy kod -

innodb_data_file_path = ibdata1:10M:autoextend:max:512M

Ważna uwaga Nie można hostować więcej niż 512MBdanych we wszystkich InnoDB tabelach łącznie.

Możesz także przełączyć się na schemat innodb na tabelę za pomocą innodb_file_per_table.

Joomler
źródło