ОБНОВЛЕНИЕ: tl; dr: Проблема заключалась в том, что MySQL использует TMPDIR
при создании индексов. И у меня TMPDIR
не хватило места на диске.
Оригинал Q:
Я пытаюсь добавить индекс в таблицу InnoDB и получаю table is full error
. У меня достаточно дискового пространства, а в конфигурации MySQL файл на таблицу = 1. Данные таблицы составляют 85 ГБ, и я предполагаю, что индекс будет около 20 ГБ - 30 ГБ, и у меня гораздо больше дискового пространства, чем это. Я также использую ext3, поэтому я не чувствую никаких проблем с ограничением размера файла с точки зрения ОС.
Зарегистрированная ошибка выглядит так:
140616 13:04:33 InnoDB: Error: Write to file (merge) failed at offset 3 1940914176.
InnoDB: 1048576 bytes should have been written, only 970752 were written.
InnoDB: Operating system error number 0.
InnoDB: Check that your OS and file system support files of this size.
InnoDB: Check also that the disk is not full or a disk quota exceeded.
InnoDB: Error number 0 means 'Success'.
InnoDB: Some operating system error numbers are described at
InnoDB: http://dev.mysql.com/doc/refman/5.5/en/operating-system-error-codes.html
140616 13:04:33 [ERROR] /usr/libexec/mysqld: The table 'my_table' is full
Что является причиной этого и как я могу решить?
Создать таблицу:
`CREATE TABLE `my_table` (
`uid_from` bigint(11) NOT NULL,
`uid_to` bigint(11) NOT NULL,
`counter` int(11) NOT NULL,
`updated` date NOT NULL,
PRIMARY KEY (`uid_to`,`uid_from`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8`
Данные равны 87,4 ГБ, и, по моим оценкам, около 1,5B строк.
SHOW GLOBAL VARIABLES LIKE 'tmpdir';
Variable_name Value
tmpdir /tmp
[root@web ~]# df -h /tmp
Filesystem Size Used Avail Use% Mounted on
/dev/xvda1 40G 24G 14G 64% /
Ответы:
Пожалуйста, не обманывайте себя сообщением об ошибке
The table 'my_table' is full
. Этот редкий сценарий не имеет абсолютно никакого отношения к дисковому пространству. Это полное состояние таблицы связано с внутренней сантехникой InnoDB.Во-первых, взгляните на эту диаграмму архитектуры InnoDB
Обратите внимание, что системное табличное пространство (файл ibdata) имеет только 128 сегментов отката и 1023 слота отката на сегмент отката. Это накладывает ограничения на размер отката транзакции. Другими словами, если одному сегменту отката требуется более 1023 слотов для поддержки транзакции, транзакция выполнит это
table is full
условие.Вспомните ресторан Red Lobster в Нью-Джерси . Он может вместить 200 человек. Если ресторан переполнен, ряд людей может выйти на улицу, чтобы ждать. Если люди на линии нетерпеливы, они могут уйти, потому что ресторан переполнен. Очевидно, что решение не состояло бы в том, чтобы сделать Нью-Джерси больше (или получить больше дискового пространства). Решение было бы сделать ресторан Red Lobster больше. Таким образом, вы можете увеличить вместимость до, скажем, до 240. Даже при этом, линия может образоваться снаружи, если более 240 человек решат приехать в Красный Лобстер.
Просто чтобы дать вам пример, у меня был клиент с 2 ТБ системного табличного пространства, и innodb_file_per_table был отключен. (346G для ibdata1, сброс для ibdata2). Я выполнил этот запрос
Затем я вычел InnoDBDataIndexSpace из суммы размеров файлов для ibdata1 и ibdata2. Я получил две вещи, которые потрясли меня
Table is Full
состояниеЭто означает, что 106 ГБ использовалось для внутренней сантехники InnoDB. В то время клиент использовал ext3.
Решением для меня было добавить ibdata3. Я обсуждал это в моем старом посте. Как решить "Таблица ... заполнена" с "innodb_file_per_table"?
Я обсуждал это и в других постах
Mar 31, 2014
: каталог mysql увеличивается до 246G после одного запроса, который не выполнен из-за переполнения таблицыNov 25, 2011
: ОШИБКА 1114 (HY000) в строке 6308 в файле & Таблица user_analysis заполненаИмейте в виду, что это может произойти, даже если была включена innodb_file_per_table . Как? Откат и журналы отмены являются источником неконтролируемых всплесков роста ibdata1 .
ВАШ АКТУАЛЬНЫЙ ВОПРОС
Поскольку вы добавляете индекс к таблице и получаете
Table is Full
, таблица должна быть огромной и не может поместиться в один сегмент отката. Вы должны сделать следующее:ШАГ 01
Получить данные в файл дампа
ШАГ 02
Войдите в MySQL и запустите этот
ШАГ 03
Загрузите таблицу с дополнительным индексом с данными
Это все.
Видите, проблема в том, что ALTER TABLE попытается внедрить все строки в вашей огромной таблице как одну транзакцию. Использование mysqldump вставит данные в таблицу (теперь с новым индексом) тысячи строк за раз, а не все строки в одной транзакции.
Не беспокойтесь о
what if this doesn't work?
Первоначальная таблица будет названаmytable_old
в случае чего-либо. это может служить резервной копией. Вы можете удалить резервную копию, когда вы знаете, что новая таблица работает для вас.Попробуйте!
ОБНОВЛЕНИЕ 2014-06-16 11:13 EDT
Если вы беспокоитесь об огромном сбросе данных, просто распакуйте его.
Вы можете сделать те же шаги, но следующим образом
ШАГ 01
Получить данные в файл дампа
ШАГ 02
Войдите в MySQL и запустите этот
ШАГ 03
Загрузите таблицу с дополнительным индексом с данными
или
ОБНОВЛЕНИЕ 2014-06-16 12:55 ПО ВОСТОЧНОМУ ВРЕМЕНИ
Я просто подумал о другом аспекте в этом вопросе.
Поскольку вы выполняете DDL, а не DML, возможно, это не внутренняя система InnoDB. Поскольку DDL не может выполнить откат для InnoDB , проблема должна быть связана с внешним подключением. Где этот внешний водопровод засорен? Я подозреваю, что временная папка для ОС. Почему?
Видишь
disk quota exceeded
? Куда навязывается эта дисковая квота?Запустите этот запрос
Вы сказали, что это
/var/lib/mysqltmp
Теперь запустите это в ОС
Что-то подсказывает мне, что места для
/var/lib/mysqltmp
не хватает, в конце концов, у вас есть только 14G бесплатно. В глазах DDL (для создания индекса) произошел откат не в файле ibdata1, а вtmpdir
местоположении. Если/var/lib/mysqltmp
нигде не монтируется, то временные данные записываются в корневой раздел. Если/var/lib/mysqltmp
где-то монтируется, то это монтирование заполняется данными строки. В любом случае недостаточно места для завершения DDL.У вас есть два варианта здесь
ОПЦИЯ 1
Вы также можете создать большой диск (возможно, с объемом 100 ГБ) и смонтировать его
/var/lib/mysqltmp
на этом большом диске.ВАРИАНТ № 2
Мои трехэтапные предложения должны работать, даже если у вас ограниченное дисковое пространство
КОММЕНТАРИЙ
Обидно, что сообщение об ошибке, которое вы отправили, говорит
Это означает, что ОС просто отлично. Также не существует никакого связанного номера ошибки для этой ситуации.
Есть еще одна вещь, которую вы должны знать. Документация MySQL говорит, что Быстрое Создание Индекса для InnoDB все еще идет на диск :
ОБНОВЛЕНИЕ 2014-06-16 13:58 ПО ВОСТОЧНОМУ ВРЕМЕНИ
Пожалуйста, убедитесь, что
/mnt/cbsvolume1/var/lib/mysql
100G или более бесплатноисточник