Błąd rozmiaru wiersza w MySQL

11

Korzystam z serwera MySQL na moim Macbooku (do testowania). Wersja jest 5.6.20 od Homebrew. Zacząłem napotykać błędy „Zbyt duży rozmiar wiersza” i udało mi się zredukować to do tego przypadku testowego. Stół:

mysql> describe test;
+-------+----------+------+-----+---------+----------------+
| Field | Type     | Null | Key | Default | Extra          |
+-------+----------+------+-----+---------+----------------+
| id    | int(11)  | NO   | PRI | NULL    | auto_increment |
| stuff | longtext | YES  |     | NULL    |                |
+-------+----------+------+-----+---------+----------------+

Status tabeli:

mysql> show table status where Name = 'test';
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
| Name | Engine | Version | Row_format | Rows | Avg_row_length | Data_length | Max_data_length | Index_length | Data_free | Auto_increment | Create_time         | Update_time | Check_time | Collation       | Checksum | Create_options | Comment |
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+
| test | InnoDB |      10 | Compact    |    1 |          16384 |       16384 |               0 |            0 |   5242880 |              2 | 2014-08-28 23:51:12 | NULL        | NULL       | utf8_general_ci |     NULL |                |         |
+------+--------+---------+------------+------+----------------+-------------+-----------------+--------------+-----------+----------------+---------------------+-------------+------------+-----------------+----------+----------------+---------+

Występuje błąd, gdy próbuję wstawić wiersz do tabeli, w której stuffkolumna ma więcej niż 5033932 bajtów.

mysql> select length(stuff) from test;
+---------------+
| length(stuff) |
+---------------+
|       5033932 |
+---------------+

mysql> update test set stuff = concat(stuff, 'a');
ERROR 1118 (42000): Row size too large (> 8126). Changing some columns to TEXT or BLOB or using ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSED may help. In current row format, BLOB prefix of 768 bytes is stored inline.

Szukałem tego błędu, większość odpowiedzi wymaga posiadania zbyt wielu kolumn TEKSTOWYCH, a każda z nich ma wbudowane 768 bajtów. Jak widać, w moim przypadku tak nie jest. Ponadto liczba 5033932 pozostaje taka sama, niezależnie od liczby kolumn, które mam w tabeli. W mojej oryginalnej aplikacji było pięć kolumn, a aktualizacje nadal nie powiodły się, gdy rozmiar kolumny przekroczył 5033932.

Widziałem też, jak ludzie rozwiązują ten problem, zmieniając formaty wierszy, które spróbuję za chwilę, ale chciałbym dokładnie zrozumieć, co powoduje ten błąd.

Z góry dziękuję!

geoffliu
źródło

Odpowiedzi:

12

Zmiana informacji o wersji 5.6.20:

Ponowne zapisywanie dziennika dla dużych, przechowywanych zewnętrznie pól BLOB może zastąpić najnowszy punkt kontrolny. Łatka 5.6.20 ogranicza rozmiar dziennika ponownych zapisów BLOB do 10% wielkości pliku dziennika ponownych operacji. Łatka 5.7.5 rozwiązuje problem bez narzucania ograniczeń. W przypadku MySQL 5.5 błąd pozostaje znanym ograniczeniem.

W wyniku wprowadzonego limitu zapisu BLOB dziennika wprowadzonego dla MySQL 5.6, rozmiar innodb_log_file_sile powinien zostać ustawiony na wartość większą niż 10-krotność największego rozmiaru danych BLOB znalezionego w wierszach twoich tabel plus długość innych pól o zmiennej długości (VARCHAR, VARBINARY i pola typu TEKST). Niezastosowanie się do tego może spowodować błędy „Zbyt duży rozmiar wiersza”.

(moje podkreślenie)

Domyślna wartość innodb_log_file_sizeto 50331648, co oznacza, że ​​największa wartość BLOB / TEXT, którą można utworzyć, niezależnie od typu danych, jest zbliżona do 5033164, a odkryłeś, że dokładna wartość to 5033932. Przypuszczam, że wewnętrznie obliczenia obejmują pewien współczynnik krówki.

Musisz więc zwiększyć, innodb_log_file_sizejeśli chcesz przechowywać większe dane BLOB / TEXT. Na szczęście zmiana rozmiaru pliku dziennika jest dużo łatwiejsza w 5.6 niż we wcześniejszych wersjach InnoDB. Po prostu dodaj wiersz w pliku my.cnf z nową wartością i zrestartuj mysqld.

Bill Karwin
źródło
małe powiadomienie, musisz zrestartować lub zatrzymać i zacząć od nowa, aby pozwolić na zmianę, przeładowanie nie działa
Hieu Vo 16'15
1
Ten limit rozmiaru ponownych operacji został zmniejszony do 10% całkowitej łącznej wielkości pliku plik_wpisu_log (plik_pliku_wpisu * rozmiar pliku innodb_log_pliku_w_grupie) z mysql 5.6.22. A longblob może mieć maksymalną długość 4294967295 (2 ^ 32-1) znaków, tj. Około 4 GB. Aby przechowywać tę wartość longblob, powinniśmy mieć co najmniej 40 GB połączonego rozmiaru pliku dziennika_wpisu_pliku_w_dod (rozmiar pliku dziennika_wpisu * plik_logu_wpisu_wpisu_inodb_logu)
kasi