Обмеження для "Mysql Row size занадто великий"


104

Як я можу змінити ліміт

Розмір рядка занадто великий (> 8126). Зміна деяких стовпців на TEXT або BLOB або використання ROW_FORMAT=DYNAMIC or ROW_FORMAT=COMPRESSEDможе допомогти. У поточному форматі рядків BLOBпрефікс у 768 байт зберігається в рядку.

Таблиця:

id  int(11) No       
name    text    No       
date    date    No       
time    time    No       
schedule    int(11) No       
category    int(11) No       
top_a   varchar(255)    No       
top_b   varchar(255)    No       
top_c   varchar(255)    No       
top_d   varchar(255)    No       
top_e   varchar(255)    No       
top_f   varchar(255)    No       
top_g   varchar(255)    No       
top_h   varchar(255)    No       
top_i   varchar(255)    No       
top_j   varchar(255)    No       
top_title_a varchar(255)    No       
top_title_b varchar(255)    No       
top_title_c varchar(255)    No       
top_title_d varchar(255)    No       
top_title_e varchar(255)    No       
top_title_f varchar(255)    No       
top_title_g varchar(255)    No       
top_title_h varchar(255)    No       
top_title_i varchar(255)    No       
top_title_j varchar(255)    No       
top_desc_a  text    No       
top_desc_b  text    No       
top_desc_c  text    No       
top_desc_d  text    No       
top_desc_e  text    No       
top_desc_f  text    No       
top_desc_g  text    No       
top_desc_h  text    No       
top_desc_i  text    No       
top_desc_j  text    No       
status  int(11) No       
admin_id    int(11) No 

1
Що Noвідображається?
hjpotter92

Неможливо оновити помилку "Розмір рядка занадто великий (> 8126). Можуть допомогти зміни деяких стовпців на TEXT або BLOB або використання ROW_FORMAT = DYNAMIC або ROW_FORMAT = COMPRESSED. У поточному форматі рядка префікс BLOB у 768 байт зберігається в рядку."
Лаша Курт

Чи можете ви додати до своєї публікації якісь інші деталі, принаймні як коментар?
Ейнекі

1
якщо ці дані є в іншій таблиці, розгляньте замість цього використання зовнішнього ключа, це різко зменшить розмір рядка та нормалізує схему вашої бази даних.
didierc

1
@AL: На жаль, ви маєте рацію - голосуйте поруч із іншим
патикритом

Відповіді:


121

Питання задається і на сервері за замовчуванням .

Ви можете ознайомитися з цією статтею, яка багато в чому пояснює розміри рядків MySQL. Важливо зауважити, що навіть якщо ви використовуєте поля TEXT або BLOB, розмір вашого рядка все одно може перевищувати 8K (обмеження для InnoDB), оскільки він зберігає перші 768 байт для кожного поля, вбудованого на сторінку.

Найпростіший спосіб виправити це - використовувати формат файлу Barracuda за допомогою InnoDB. Це в основному позбавляється від проблеми, лише зберігаючи 20-байтний покажчик на текстові дані замість того, щоб зберігати перші 768 байт.


Метод, який працював на ОП, був:

  1. Додайте наступне до my.cnfфайлу під [mysqld]розділом.

    innodb_file_per_table=1
    innodb_file_format = Barracuda
  2. ALTERтаблицю для використання ROW_FORMAT=COMPRESSED.

    ALTER TABLE nombre_tabla
        ENGINE=InnoDB
        ROW_FORMAT=COMPRESSED 
        KEY_BLOCK_SIZE=8;

Існує ймовірність, що вищезгадане досі не вирішує ваші проблеми. Це відома (і перевірена) помилка з двигуном InnoDB , і тимчасовим виправленням на даний момент є відкат до двигуна MyISAM як тимчасового зберігання. Отже, у вашому my.cnfфайлі:

internal_tmp_disk_storage_engine=MyISAM

12
+1 -> Частина innodb_file_per_table є вирішальною і йде рука об руку зі зміною формату на Barracuda. Без цього MySQL мовчки продовжить використовувати антилопу.
Нік

1
@Eduardo я рекомендую спершу створити резервну копію даних. Але так, це можна зробити і на виробництві!
hjpotter92

3
Використовуйте innodb_file_per_table=1для активації цієї опції.
Stijn Geukens

2
Це не гарантує вирішення проблеми. Дивіться у цій публікації приклад сценарію, який додає ці налаштування, але все ще може відтворити помилку.
Серін

1
@ user1183352 Оновлено мою відповідь вище. Дякуємо, що нагадали мені знову зануритися в це. :)
hjpotter92

61

Нещодавно я зіткнувся з цією проблемою і вирішив її по-іншому. Якщо ви використовуєте MySQL версії 5.6.20, у системі є відома помилка. Дивіться документи MySQL

Важливо Через помилку № 69477, запис журналів повторень для великих, зовні зберігаються полів BLOB може замінити найсвіжіший контрольний пункт. Щоб вирішити цю помилку, патч, введений у MySQL 5.6.20, обмежує розмір повторного запису, який BLOB пише, на 10% від розміру файлу журналу повтору. У результаті цього обмеження innodb_log_file_size слід встановити значення, яке перевищує 10 разів найбільший розмір даних BLOB, знайдений у рядках ваших таблиць, плюс довжина інших полів змінної довжини (поля типу VARCHAR, VARBINARY та TEXT).

У моїй ситуації стільниковий кримінальний стіл становив близько 16 Мб. Таким чином, я вирішив це шляхом додавання рядка до my.cnf, який забезпечив мені щонайменше 10 разів цю суму, а потім і деяку:

innodb_log_file_size = 256M


Пляма на. Моя помилка "Розмір рядка занадто велика" в longblobполі зникла, як тільки я збільшив innodb_log_file_sizeпараметр. Також бігав 5.6.20.
adamup

Дякую. Запускався домашній 5.6.21, зміна парами вирішила проблему.
наноман

І цю відповідь, і відповідь @ hjpotter92 потрібно було виправити для мене.
Серін

Дякую. Працював 5.6.21, і це рішення допомогло.
п’ятір

Це також не вирішило мого питання. Я розглядаю можливість заміни багатьох моїх полів VARCHAR на ТЕКСТИ, як я бачив у подібних потоках.
PDoria

28

Встановіть наступні файли my.cnf та перезапустіть сервер mysql.

innodb_strict_mode=0

2
innodb_strict_mode=0-> пробілів немає. В іншому випадку перезапуск mariaDB 10.2 призводить до помилки :-P
Pathros

Я не намагався з mariadb, для MySQL не потрібно видаляти пробіли.
Карл

1
Відповідно до документації, відключення суворого режиму лише запобігає появі помилок і попереджень, тому, здається, це не вирішує проблему! download.nust.na/pub6/mysql/doc/innodb-plugin/1.1/en/…
Жоао Тейшейра

2
Це, здається, спрацьовує, і дозвольте мені створювати таблиці без проблем і зберігати дані
Кріс Мюнч

@ João, це робить більше .. dev.mysql.com/doc/refman/8.0/en/…
Карл

24

Якщо ви можете переключити ENGINE і використовувати MyISAM замість InnoDB, це повинно допомогти:

ENGINE=MyISAM

Є два застереження з MyISAM (можливо, більше):

  1. Ви не можете використовувати транзакції.
  2. Ви не можете використовувати обмеження іноземних ключів.

5
Добре, якщо ви не заперечуєте без транзакцій та іноземних ключових обмежень. Але майте на увазі, що ви втрачаєте це під час переходу на MyISAM.
wobbily_col

Ця порада є божевільною - принаймні, ця фраза допоможе нам застерегти! Ключові обмеження транзакцій та foregith - найменша проблема з цим форматом!
Хасан Сиєд

Вибачте, що прийняв цю відповідь. Будь ласка, оновіть, щоб згадати про всі застереження. Хто тільки дотримується цієї поради, переходить у формат, який я ніколи не використовував би в жодній виробничій системі.
Ремко Вендт

2
І MyISAM відходить.
Рік Джеймс

2
працював на мене. У моєму випадку я мав понад 300 полів довжиною приблизно 10. Я не маю жодних стосунків у цій таблиці, тому виправленням MyISAM було виправлення.
Роберт Сейлор

12

Я хотів би поділитися приголомшливою відповіддю, це може бути корисним. Кредити Білла Карвіна дивіться тут /dba/6598/innodb-create-table-error-row-size-too-large

Вони залежать від формату файлу InnoDB. На даний момент є 2 формати під назвою "Антилопа" та "Барракуда".

Файл центрального простору таблиць (ibdata1) завжди знаходиться у форматі антилопи. Якщо ви використовуєте файл за столом, ви можете змусити окремі файли використовувати формат Barracuda, встановивши innodb_file_format = Barracuda в my.cnf.

Основні моменти:

  1. Одна сторінка даних InnoDB на 16 КБ повинна містити принаймні два рядки даних. Плюс до кожної сторінки є заголовок та колонтитул, що містить контрольні суми сторінки та номер послідовності журналу тощо. Ось де ви отримуєте ліміт трохи менше 8 КБ на рядок.

  2. Типи даних фіксованого розміру, такі як INTEGER, DATE, FLOAT, CHAR, зберігаються на цій основній сторінці даних і рахуються до межі розміру рядка.

  3. Типи даних змінного розміру, такі як VARCHAR, TEXT, BLOB, зберігаються на переливних сторінках, тому вони не враховуються повністю до межі розміру рядка. В Антилопі до 768 байт таких стовпців зберігаються на основній сторінці даних, крім того, що вони зберігаються на сторінці переповнення. Barracuda підтримує динамічний формат рядків, тому він може зберігати лише 20-байтовий покажчик на основній сторінці даних.

  4. Типи даних змінного розміру також мають префікс з 1 або більше байтами для кодування довжини. Формат рядків InnoDB також має масив зміщення поля. Отже, є внутрішня структура, більш-менш задокументована у їхніх вікі.

Barracuda також підтримує ROW_FORMAT = COMPRESSED для отримання додаткової ефективності зберігання даних для переповнення даних.

Я також повинен прокоментувати, що я ніколи не бачив, щоб добре розроблена таблиця перевищувала обмеження розміру рядків. Це сильний "запах коду", що ви порушуєте умови повторюваних груп Першої нормальної форми.


7

У мене було те саме питання, що це вирішило для мене:

ALTER TABLE `my_table` ROW_FORMAT=DYNAMIC;

З Документації на MYSQL :

Формат рядків DYNAMIC підтримує ефективність зберігання всього рядка у вузлі індексу, якщо він підходить (як це роблять формати COMPACT та REDUNDANT), але цей новий формат дозволяє уникнути проблеми заповнення вузлів B-дерева великою кількістю байтів даних довгі колони. Формат DYNAMIC заснований на ідеї, що якщо частина довгого значення даних зберігається поза сторінкою, зазвичай найбільш ефективно зберігати все значення поза сторінкою. У форматі DYNAMIC короткі стовпці, ймовірно, залишатимуться у вузлі B-дерева, мінімізуючи кількість переливних сторінок, необхідних для будь-якого рядка.


... але вам потрібно мати інший формат файлу, так що ви вже на Barracuda? Тому що я отримую помилку при спробі виконання цієї команди, кажучиWarnings from last query: InnoDB: ROW_FORMAT=DYNAMIC requires innodb_file_format > Antelope
Тед

Коли я дозволив HeidiSQL виконувати ту саму команду через вбудований графічний інтерфейс, це якось вдалося, але це зовсім не допомогло, я отримую ту ж помилку,Row size too large (>8126)
Тед

Спробуйте встановити innodb_file_format = Barracuda в my.ini і спробуйте ALTER TABLE my_tableROW_FORMAT = DYNAMIC; знову
multimediaxp

Так, я думаю, що це я зробив врешті-решт, і я думаю, що це вирішило. Але я також змінив багато колонок на ТЕКСТ водночас у відчаї =) Однак, я думаю, що це було саме так.
Тед

Добре !, якщо ви вважаєте, що це хороша відповідь, дайте їй голос і прийміть як дійсну відповідь, дякую!
multimediaxp

5

Затративши години, я знайшов рішення: просто запустіть наступний SQL у своєму адміністраторі MySQL, щоб перетворити таблицю в MyISAM:

USE db_name;
ALTER TABLE table_name ENGINE=MYISAM;

Не дуже допомагає, якщо проблема відбувається в операторі створення таблиці.
Марк Фрейзер

create tableмає той же варіант:CREATE TABLE ... ENGINE=MyISAM ...
xebeche

3

Я зіткнувся з цим питанням, коли я намагався відновити резервну копію mysql бази даних з іншого сервера. Що вирішило цю проблему для мене, було додавання певних налаштувань до my.conf (як, наприклад, у питаннях вище) та додатково зміна файлу резервної копії sql:

Крок 1: додайте або відредагуйте наступні рядки в my.conf:

innodb_page_size=32K
innodb_file_format=Barracuda
innodb_file_per_table=1

Крок 2 додайте ROW_FORMAT = DYNAMIC до таблиці створення оператора у файлі резервного копіювання sql для таблиці, яка викликає цю помилку:

DROP TABLE IF EXISTS `problematic_table`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `problematic_table` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
  ...
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 ROW_FORMAT=DYNAMIC;

важлива зміна вище - ROW_FORMAT = DYNAMIC; (це не було включено до файлу резервної копії оригінального sql)

джерело, яке допомогло мені вирішити цю проблему: MariaDB та InnoDB MySQL Row розмір занадто великий


1
Рядки, описані в кроці 1, не повинні мати місця. Рядок innodb_page_size=32Kне працював, оскільки спричинив помилку при перезапуску MariaDB 10.2 в моєму випадку. Натомість я додав innodb_strict_mode=0рядок, як описано тут
Pathros

1
дякую за відгук Pathros, я оновив свою відповідь і видалив пробіли з кроку1.
матяш

Примітка для MySQL <= 5.7.5: 32K не вірна опція для innodb_page_size. Дивіться: dev.mysql.com/doc/refman/5.6/en/…
Dub Nazar

Крім того, ви повинні відтворити весь ваш mysql-сервер для scracth, оскільки для зміни innodb_page_sizeпотрібен ibdata*відпочинок, що є руйнівною операцією. Перегляньте свій системолог для отримання додаткової інформації
Matija Nalis

2

Інші відповіді стосуються заданого питання. Я торкнуся основної причини: погана конструкція схеми.

Не грайте масив через стовпці. Тут у вас є 3 * 10 стовпців, які слід перетворити на 10 рядків із 3 стовпців у новій таблиці (плюс idтощо)

Ваш Mainстіл матиме тільки

id  int(11) No       
name    text    No       
date    date    No       
time    time    No       
schedule    int(11) No       
category    int(11) No       
status  int(11) No       
admin_id    int(11) No 

Ваш додатковий стіл ( Top) мав би

id  int(11) No          -- for joining to Main
seq TINYINT UNSIGNED    -- containing 1..10
img   varchar(255)    No       
title varchar(255)    No       
desc  text    No    
PRIMARY KEY(id, seq)    -- so you can easily find the 10 top_titles

Там було б 10 (або менше? Або більше?) Рядки в Topдля кожного id.

Це усуває вашу первісну проблему та очищає схему. (Це не «нормалізація», як обговорювалося в деяких коментарях.)

Є НЕ переключитися на MyISAM; воно відходить.
Не хвилюйся ROW_FORMAT.

Вам потрібно буде змінити свій код, щоб зробити JOINта обробити кілька рядків замість кількох стовпців.


1

Я використовую MySQL 5.6 на AWS RDS. Я оновив наступне в групі параметрів.

innodb_file_per_table=1
innodb_file_format = Barracuda

Мені довелося перезавантажити екземпляр БД, щоб зміни групи параметрів були чинними.

Також ROW_FORMAT = COMPRESSED не підтримувався. Я використовував DYNAMIC, як показано нижче, і він працював чудово.

ALTER TABLE nombre_tabla ENGINE=InnoDB ROW_FORMAT=DYNAMIC KEY_BLOCK_SIZE=8

1

Максимальний розмір рядка для таблиці InnoDB, який застосовується до даних, що зберігаються локально на сторінці бази даних, становить трохи менше половини сторінки для 4 КБ, 8 КБ, 16 КБ і 32 КБ.

Для сторінок 16 Кбіт (за замовчуванням) ми можемо розрахувати:

Slightly less than half a page 8126 / Number of bytes to threshold for overflow 767 = 10.59 fields of 767 bytes maximum

В основному, ви можете максимально збільшити ряд з:

  • 11 варчарських полів> 767 символів (latin1 = 1 байт на char) або
  • 11 полів варчара> 255 символів (utf-8 у mysql = 3 байти на графік).

Пам'ятайте, що вона переливається на сторінку, що переповнюється, лише якщо поле> 767 байт. Якщо занадто багато полів у 767 байтів, воно буде перебиватися (виходячи за межі макс. Не звичайно з Latin1, але дуже можливо з utf-8, якщо розробники не обережні.

У цьому випадку я думаю, що ви, можливо, зможете підняти innodb_page_size до 32 кб.

в my.cnf:

innodb_page_size=32K

Список літератури:


0

Я також зіткнувся з тією ж проблемою. Я вирішую проблему, виконавши наступний sql:

ALTER ${table} ROW_FORMAT=COMPRESSED;

Але я думаю, що вам слід знати про зберігання рядків .
Є два види стовпців: стовпчик змінної довжини (наприклад, VARCHAR, VARBINARY, BLOB і TEXT) та стовпчик із фіксованою довжиною . Вони зберігаються на різних типах сторінок.

Стовпці змінної довжини - виняток із цього правила. Стовпці, такі як BLOB та VARCHAR, які занадто довгі для розміщення на сторінці B-дерева, зберігаються на окремо виділених сторінках диска, що називаються сторінками переповнення. Ми називаємо такі стовпці стовпцями поза сторінками. Значення цих стовпців зберігаються у окремо пов'язаних списках переливних сторінок, і кожен такий стовпець має власний список однієї або декількох сторін, що переповнюються. У деяких випадках все або префікс великого значення стовпця зберігається у B-дереві, щоб уникнути марно зберігання та усунення необхідності читати окрему сторінку.

і коли метою встановлення ROW_FORMAT є

Коли створюється таблиця з ROW_FORMAT = DYNAMIC або ROW_FORMAT = COMPRESSED, InnoDB може зберігати великі значення стовпців змінної довжини (для типів VARCHAR, VARBINARY, BLOB і TEXT) повністю поза сторінкою, з кластерним записом індексу, що містить лише 20- байт-вказівник на сторінку, що переповнюється.

Хочете дізнатися більше про DYNAMIC та COMPRESSED Row формати


0

Якщо це відбувається на SELECT з багатьма стовпцями, причиною може бути те, що mysql створює тимчасову таблицю. Якщо ця таблиця занадто велика, щоб вмістити її в пам’яті, вона використовуватиме її типовий формат таблиці темп за замовчуванням, який є InnoDB, для зберігання її на диску. У цьому випадку застосовуються обмеження розміру InnoDB.

Потім у вас є 4 варіанти:

  1. змінити обмеження розміру рядків innodb, як зазначено в іншому дописі, що вимагає повторної ініціалізації сервера.
  2. змініть ваш запит, щоб він включав менше стовпців, або уникати його створення тимчасової таблиці (тобто видалення порядку та обмеження пропозицій).
  3. зміна max_heap_table_size на велику, щоб результат вписався в пам'ять і не потрібно записувати на диск.
  4. змінити формат таблиці за замовчуванням на MYISAM, це я і зробив. Зміни в my.cnf:

    internal_tmp_disk_storage_engine=MYISAM

Перезавантажте mysql, працює запит.


0

Ось проста порада для всіх, хто цікавиться:

Після оновлення з Debian 9 до Debian 10 з 10.3.17-MariaDB, у мене є деякі помилки в базах даних Joomla:

[Попередження] InnoDB: Неможливо додати поле fieldдо таблиці database.tableоскільки після його додавання розмір рядка дорівнює 8742, що перевищує максимально дозволений розмір (8126) для запису на сторінці аркуша покажчика.

На всякий випадок я встановив innodb_default_row_format = DYNAMIC у /etc/mysql/mariadb.conf.d/50-server.cnf (це було за замовчуванням у будь-якому випадку)

Крім того, я використовував phpmyadmin для запуску "Оптимізувати таблицю" для всіх таблиць у базі даних Joomla. Я думаю, що настільний відпочинок, зроблений phpmyadmin в цьому процесі, допоміг. Якщо у вас інстальовано phpmyadmin, це зробити лише кілька кліків.


Якщо ви користувач Joomla, приходьте до нас на Joomla Stack Exchange - ми завжди можемо використовувати нових учасників.
mickmackusa
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.