RussianLDP Рейтинг@Mail.ru
WebMoney: 
WMZ Z294115950220 
WMR R409981405661 
WME E134003968233 
YandexMoney: 
41001198119846 
E-gold:
5128052

Глава 16. Механизм хранения InnoDB

16.1. Введение в InnoDB

InnoDB механизм хранения общего назначения, который балансирует высокую надежность и высокую производительность. В MySQL 8.0 механизм хранения по умолчанию. Если Вы не сконфигурировали иной механизм хранения значения по умолчанию, CREATE TABLE без предложения ENGINE= создает таблицу InnoDB.

Главные преимущества InnoDB

Главные преимущества InnoDB:

Table 16.1. Особенности механизма хранения InnoDB

Пределы хранения 64TBТранзакцииДа Блокировка степени детализации Строка
MVCCДа Поддержка геоданныхДа Индексирование геоданныхДа
Индексы B-treeДа Индексы T-treeНет Индексы HashНет
Полнотекстовый поиск ДаКластеризируемый индекс ДаКэширование данных Да
Кэширование индексовДа Сжатие данныхДа ШифрованиеДа
Поддержка базы данных кластера НетРепликацияДа Внешние ключиДа
Резервное копирование/восстановление момента времени ДаКэш запросов ДаСтатистика обновления словаря данных Да

Чтобы сравнить особенности InnoDB с другими механизмами хранения, предоставленными MySQL, см. главу 17.

Улучшения InnoDB и новые особенности

Для информации об улучшениях InnoDB и новых особенностях в MySQL 8.0 обратитесь к:

Дополнительная информация о InnoDB и ресурсы

16.1.1. Выгода от использования таблиц InnoDB

Если Вы используете таблицы MyISAM, Вы можете счесть InnoDB выгодными по следующим причинам:

  • Если Ваш сервер отказывает из-за аппаратных средств или проблемы программного обеспечения, независимо от того, что происходило в базе данных в то время, Вы не должны сделать ничего специального после перезапуска базы данных. InnoDB автоматически завершает любые изменения, которые были переданы перед временем катастрофического отказа, и отменяет любые изменения, которые были в процессе, но не завершены. Только перезапустите сервер и продолжите работу.

  • Механизм хранения InnoDB поддерживает свой собственный буферный пул, так что хранит таблица кэшей и индексирлванные данные в основной памяти, пока к данным получают доступ. Часто используемые данные обработаны непосредственно в памяти. Этот кэш относится ко многим типам информации и ускоряет обработку. На специализированных серверах базы данных до 80% физической памяти часто назначаются на буферный пул InnoDB.
  • Если Вы разделяете связанные данные на различные таблицы, Вы можете настроить внешние ключи, которые проводят в жизнь ссылочную целостность. Обновите или удалите данные, и связанные данные в других таблицах обновлены или удалены автоматически. Попытайтесь вставить данные во вторичную таблицу без соответствующих данных в основной таблице, и неправильные данные будут блокированы автоматически.
  • Если данные становятся поврежденными на диске или в памяти, механизм контрольной суммы предупреждает Вас прежде, чем Вы будете использовать это.
  • Когда Вы разрабатываете свою базу данных с соответствующими столбцами первичного ключа для каждой таблицы, операции, вовлекающие те столбцы, автоматически оптимизированы. Это очень быстро, чтобы сослаться на столбцы первичного ключа в WHERE, ORDER BY, GROUP BY и join.
  • Вставки, обновления и удаления оптимизированы автоматическим механизмом, названным буферизацией изменения. InnoDB не только позволяет параллельное чтение и запись к той же самой таблице, это кэширует измененные данные, чтобы упростить дисковый ввод/вывод.
  • Исполнительная выгода не ограничена гигантскими таблицами с продолжительными запросами. То, когда к тем же самым строкам получают доступ много раз из таблицы, особенность, названная адаптивным хеш-индексом, предназначенная, чтобы сделать эти поиски еще быстрее, как будто они вышли из хэш-таблицы.
  • Вы можете сжать таблицы и связанный индекс.
  • Вы можете создать и удалить индексы с намного меньшим воздействием на работу и доступность.
  • Усечение табличного пространства file-per-table очень быстро, и может освободить дисковое пространство для операционной системы к повторному использованию, вместо того, чтобы освободить пространство в пределах system tablespace, которое только InnoDB может снова использовать.
  • Расположение хранения для табличных данных более эффективно для BLOB и длинных текстовых полей с форматом строки DYNAMIC.
  • Вы можете контролировать внутренние работы механизма хранения, запрашивая таблицы INFORMATION_SCHEMA .
  • Вы можете контролировать исполнительные детали механизма хранения, запрашивая таблицы Performance Schema.
  • Вы можете свободно смешать InnoDB с таблицами других механизмов хранения MySQL, даже в пределах того же самого запроса. Например, Вы можете использовать join, чтобы объединить данные от InnoDB и MEMORY.
  • InnoDB был разработан для эффективности центрального процессора и максимальной производительности, обрабатывая большие объемы данных.
  • Таблицы InnoDB могут обработать большие количества данных, даже на операционных системах, где размер файла ограничен 2GB.

Для InnoDB-специфичных методов тюнинга, которые Вы можете применить в своем коде программы, см. раздел 9.5.

16.1.2. Лучшие методы для таблиц InnoDB

Этот раздел описывает лучшие методы использования таблиц InnoDB.

  • Определение первичного ключа для каждой таблицы, используя наиболее часто запрашиваемый столбец или столбцы, или значения auto-increment, если нет никакого очевидного первичного ключа.

  • Использование join везде, где данные вытягивают из многих таблиц, основанных на идентичных значениях идентификаторов. Для быстрой работы объединения определите внешние ключи на столбцах соединения и объявите те столбцы с тем же самым типом данных в каждой таблице. Добавление внешних ключей гарантирует, что столбцы, на которые ссылаются, индексированы, что может улучшить работу. Внешние ключи также размножаются, удаляются или обновляются ко всем затронутым таблицам, и предотвращают вставку данных в дочерней таблице, если соответствующие ID не присутствуют в родительской таблице.
  • Выключение autocommit.
  • Группировка наборов связанных операций DML в транзакции, заключая их в скобки с START TRANSACTION и COMMIT. В то время как Вы не хотите передавать транзакции слишком часто, Вы также не хотите выпускать огромные пакеты INSERT, UPDATE или DELETE, которые работают в течение многих часов.
  • Не использование LOCK TABLES . InnoDB может обработать многократные сеансы чтения и записи той же самой таблицы сразу, не жертвуя надежностью или высокой производительностью. Чтобы получить исключительный доступ на запись к ряду строк, используют SELECT ... FOR UPDATE , чтобы заблокировать только строки, которые Вы намереваетесь обновить.
  • Включение опции innodb_file_per_table, чтобы поместить данные и индексы для отдельных таблиц в отдельные файлы, вместо единственного гигантского system tablespace. Эта установка позволяет использовать некоторые из других функций, такие как табличное сжатие и быструю обрезку.

    Опция innodb_file_per_table включена по умолчанию в MySQL 5.6.6.

  • Оценка, извлекают ли Ваши данные и образцы доступа выгоду из сжатых таблиц InnoDB (ROW_FORMAT=COMPRESSED в запросе CREATE TABLE). Вы можете сжать таблицы InnoDB, не жертвуя способностью чтения-записи.
  • Выполнение Вашего сервера с опцией --sql_mode=NO_ENGINE_SUBSTITUTION , если есть проблема с механизмом, определенным в параметре ENGINE= запроса CREATE TABLE.

16.1.3. Проверка, что InnoDB механизм хранения по умолчанию

Чтобы проверить, что InnoDB механизм хранения по умолчанию, используйте команду SHOW ENGINES , чтобы рассмотреть различные механизмы хранения MySQL. Ищите DEFAULT в строке InnoDB. Альтернативно, запросите из INFORMATION_SCHEMA таблицу ENGINES.

16.1.4. Тестирование и сопоставительный анализ с InnoDB

Если InnoDB не механизм хранения по умолчанию, Вы можете определить, работают ли Ваш сервер базы данных или приложения правильно с InnoDB перезапуская сервер с опцией --default-storage-engine=InnoDB, определенной в командной строке или с default-storage-engine=innodb в разделе [mysqld] конфигурационного файла my.cnf.

Если Вы не принимали преднамеренное решение относительно механизма хранения, и Вы только хотите посмотреть, как определенные таблицы работают, когда они создаются под InnoDB, скомандуйте ALTER TABLE table_name ENGINE=InnoDB; для каждой таблицы. Или, чтобы выполнить испытательные запросы, не нарушая оригинальную таблицу, сделайте копию:

CREATE TABLE InnoDB_Table (...) ENGINE=InnoDB AS SELECT * FROM MyISAM_Table;

Проверьте полный жизненный цикл приложения от установки, посредством тяжелого использования и перезапуска сервера. Уничтожьте процесс сервера в то время, как база данных занята, чтобы моделировать перебой в питании и проверить, что данные восстановлены успешно, когда Вы перезапускаете сервер.

Проверьте любые конфигурации репликации, особенно если Вы используете различные версии MySQL и опции на ведущем устройстве и ведомых устройствах.

16.2. InnoDB и модель ACID

Модель ACID ряд принципов проектирования баз данных, которые подчеркивают аспекты надежности, которые важны для коммерческой информации и приложений критического назначения. MySQL включает такие компоненты, как механизм хранения InnoDB, которые придерживаются близко к ACID, чтобы данные не были повреждены и результаты не искажены исключительными условиями, такими как катастрофические отказы программного обеспечения и сбои аппаратных средств. Когда Вы полагаетесь на ACID, Вы не должны повторно изобрести колесо проверки последовательности и механизмы восстановления катастрофического отказа. В случаях, где у Вас есть дополнительные гарантии программного обеспечения, ультранадежные аппаратные средства или приложение, которое может терпеть небольшое количество потерь данных, Вы можете скорректировать настройки MySQL, чтобы обменять часть надежности ACID для большей работы или пропускной способности.

Следующие разделы обсуждают, как MySQL, в особенности механизм хранения InnoDB, взаимодействует с категориями ACID:

  • A: атомность.

  • C: последовательность.
  • I:: изоляция.
  • D: длительность.

Атомность

Атомность аспект ACID, главным образом, вовлекает InnoDB транзакции. Связанные особенности MySQL включают:

  • Autocommit.

  • Команду COMMIT.
  • Команду ROLLBACK.
  • Рабочие данные от таблиц INFORMATION_SCHEMA.

Последовательность

Последовательность аспект ACID, главным образом, вовлекает внутреннюю обработку InnoDB, чтобы защитить данные от катастрофических отказов. Связанные особенности MySQL включают:

Изоляция

Изоляция аспект ACID, главным образом, вовлекает InnoDB транзакции, в особенности уровень изоляции, который относится к каждой транзакции. Связанные особенности MySQL включают:

  • Autocommit.

  • Команду SET ISOLATION LEVEL.
  • Низкоуровневые детали InnoDB блокировки. Во время исполнительной настройки Вы смотрите эти детали через таблицы INFORMATION_SCHEMA .

Длительность

Длительность аспект ACID вовлекает характеристики программного обеспечения MySQL, взаимодействующие с Вашей особой конфигурацией аппаратных средств. Из-за многих возможностей в зависимости от способностей Вашего центрального процессора, сети и устройств хранения данных, этот аспект наиболее сложен, чтобы обеспечить конкретные советы. Связанные особенности MySQL включают:

  • InnoDB буфер doublewrite, управляемый параметром innodb_doublewrite.

  • Опция innodb_flush_log_at_trx_commit.
  • Опция sync_binlog .
  • Опция innodb_file_per_table.
  • Буфер записи в устройстве хранения данных, таком как дисковод, SSD или RAID.
  • Поддержанный батареей кэш в устройстве хранения данных.
  • Операционная система, под которой работает MySQL, в особенности поддержка системного вызова fsync().
  • Защита по питанию ко всем компьютерным серверам и устройствам хранения данных, которые выполняют серверы MySQL и хранят данные MySQL.
  • Ваша стратегия резервирования, такая как частота и типы резервных копий.
  • Для распределенных приложений особые характеристики информационных центров, где аппаратные средства для серверов MySQL расположены, и сетевые соединения между информационными центрами.

16.3. Мультиверсии InnoDB

InnoDB мультиверсионный механизм хранения: это хранит информацию о старых версиях измененных строк, чтобы поддерживать транзакционные функции, такие как параллелизм и отмену. Эта информация хранится в табличном пространстве в структуре данных, названной сегмент отмены (после аналогичной структуры данных в Oracle). InnoDB использует информацию в сегменте отмены, чтобы выполнить операции отмены, необходимые в работе. Это также использует информацию, чтобы создать более ранние версии строки для последовательного чтения.

Внутренне InnoDB добавляют три поля к каждой строке, сохраненной в базе данных. Поле 6-byte DB_TRX_ID указывает на операционный идентификатор для последней транзакции, которая вставила или обновила строку. Кроме того, удаление обработано внутренне как обновление, где специальный бит в строке установлен, чтобы отметить ее как удаленную. Каждая строка также содержит 7 байтов DB_ROLL_PTR указателя пересчета. Он указывает на запись журнала отмены, записанную в сегмент отмены. Если строка была обновлена, запись журнала отмены содержит информацию, необходимую, чтобы восстановить контент строки прежде, чем это было обновлено. 6 байтов DB_ROW_ID содержит ID строки, который увеличивается монотонно, по мере вставки новых строк. Если InnoDB производит кластеризируемый индекс автоматически, индексирование содержит значения идентификаторов строки. Иначе столбец DB_ROW_ID не появляется ни в каком индексе.

Отмена входит в систему, сегмент отмены разделен на журналы отмены вставки и обновления. Журналы отмены вставки необходимы только в операционной отмене и могут быть стерты, как только транзакция передана. Журналы отмены обновления используются также в последовательных чтениях, но от них можно отказаться только после того, как нет никакой транзакции, к которой InnoDB назначил снимок, который в последовательном чтении мог нуждаться в информации в журнале отмены обновления, чтобы создать более раннюю версию строки базы данных.

Передавайте свои транзакции регулярно, включая те транзакции, которые используют только последовательные чтения. Иначе InnoDB не сможет отказаться от данных журналов отмены обновления, и сегмент отмены может стать слишком большим, заполняя Ваше табличное пространство.

Физический размер записи журнала отмены в сегменте отмены как правило меньше чем соответствующая вставленная или обновленная строка. Вы можете использовать эту информацию, чтобы вычислить пространство, необходимое для Вашего сегмента отмены.

В мультиверсионной схеме InnoDB строка физически немедленно не удалена из базы данных, когда Вы удаляете это запросом SQL. InnoDB физически удаляет соответствующую строку и индексные записи только когда отказывается от записи журнала отмены обновления, записанной для удаления. Эту работу удаления называют чисткой и она довольно быстра, обычно берет тот же самый порядок времени, как запрос SQL, который сделал удаление.

Если Вы вставляете и удаляете строки в небольших пакетах на приблизительно том же самом уровне в таблице, поток чистки может начать отставать, и таблица может стать больше и больше из-за стертых строк, делая работу с диском очень медленной. В таком случае приостановите новые операции строк и выделите больше ресурсов потоку чистки, настраивая переменную innodb_max_purge_lag . См. раздел 16.13.

Мультиверсии и вторичный индекс

InnoDB multiversion concurrency control (MVCC) обрабатывает вторичный индекс по-другому, чем кластеризируемый. Записи в кластеризируемом индексе обновлены оперативнее, и их скрытые системные записи журнала отмены указывают на столбцы, от которых могут быть восстановлены более ранние версии записи. В отличие от кластеризируемого индекса, записи вторичного индекса не содержат скрытые системные столбцы.

Когда столбец вторичного индекса обновлен, старые записи вторичного индекса, отмеченные как удаленные, удаляются, новые вставлены и отмеченные как удаленные в конечном счете очищены. Когда запись вторичного индекса отмечена как удаленная или индексная страница обновлена более новой транзакцией, InnoDB ищет запись базы данных в кластеризируемом индексе. Там запись DB_TRX_ID проверена и правильная версия получена от журнала отмены, если запись была изменена после того, как транзакция чтения была начата.

Если запись вторичного индекса помечена для удаления или индексная страница обновлена более новой транзакцией, метод индексного покрытия не используется. Вместо этого, чтобы возвратить значения из индекса структуры InnoDB ищет запись в кластеризируемом индексе.

Однако, если оптимизация index condition pushdown (ICP) разрешена, и часть выражения WHERE может быть оценена, используя только поля индекса, сервер MySQL передает эту часть WHERE механизму хранения, где это оценено, используя индексирование. Если никакие записи соответствия не найдены, поиск по кластеризируемому индексу не проводится. Если соответствие найдено, даже среди отмеченных для удаления, InnoDB ищет запись в кластеризируемом индексе.

16.4. Архитектура InnoDB

Этот раздел обеспечивает введение в главные компоненты архитектуры механизма хранения InnoDB.

16.4.1. Буферный пул

Буферный пул область в основной памяти, где InnoDB кэширует таблицы и индексы, с которыми работает. Буферный пул позволяет часто используемым данным быть обработанными непосредственно в памяти, что ускоряет обработку. На специализированных серверах базы данных до 80% физической памяти часто назначаются буфрному пулу InnoDB.

Для эффективности большого объема операций чтения буферный пул разделен на страницы, которые могут потенциально содержать много строк. Для эффективности управления кэшем буферный пул осуществлен как связанный список страниц, данные, которые редко используются, удаляются из кэша, используя вариант алгоритма LRU.

Подробности в разделе 16.6.3.

16.4.2. Буфер изменения

Буфер изменения специальная структура данных, которая кэширует изменения в страницах вторичного индекса, когда затронутые страницы не находятся в буферному пуле. Буферизованные изменения, которые могут следовать из операций INSERT, UPDATE или DELETE (DML), слиты позже, когда страницы загружены в буферный пул другими операциями чтения.

В отличие от кластеризируемого индекса, вторичный индекс обычно групповой, и вставки во вторичный индекс происходят в относительно случайном порядке. Точно так же удаления и обновления могут затронуть вторичные индексные страницы, которые рядом не расположены в индексном дереве. Слияние кэшируемых изменений идет в более позднее время, когда затронутые страницы считаны в буферный пул другими операциями, это позволяет избегать существенного ввода/вывода произвольного доступа, который был бы обязан читать вторичные индексные страницы с диска.

Периодически чистка, которая работает, когда система главным образом неактивна, или во время медленного завершения работы, пишет обновленные индексные страницы на диск. Работа чистки может записать дисковые блоки для серии индексируемых значений более эффективно, чем если бы каждое значение было немедленно написано на диск.

Буферное слияние изменения может занять несколько часов, когда есть много вторичных индексов, чтобы обновить, и много затронутых строк. В это время дисковый ввод/вывод увеличен, что может вызвать существенное замедление для запросов к диску. Слияние буферных изменений может также продолжить происходить после того, как транзакция передана. Фактически, слияние буферных изменений может продолжить происходить после завершения работы сервера и перезапуска (см. раздел 16.20.2 ).

В памяти буфер изменения занимает часть буферного пула InnoDB. На диске буфер изменения часть системного табличного пространства, так что индексные изменения остаются буферизованными между перезапусками базы данных.

Типом данных, кэшируемых в буфере изменения, управляет параметр конфигурации innodb_change_buffering. Плдробности в разделе 16.6.4. Вы можете также сконфигурировать максимальный размер буфера изменения. Для получения дополнительной информации см. раздел 16.6.4.1.

Контроль буфера изменения

Следующие опции доступны для контроля буфера изменения:

  • InnoDB Standard Monitor включает информацию о статусе для буфера изменения. Чтобы смотреть данные монитора, скомандуйте SHOW ENGINE INNODB STATUS.

    mysql> SHOW ENGINE INNODB STATUS\G
    

    Буферная информация о статусе изменения расположена под заголовком INSERT BUFFER AND ADAPTIVE HASH INDEX и выглядит так:

    -------------------------------------
    INSERT BUFFER AND ADAPTIVE HASH INDEX
    -------------------------------------
    Ibuf: size 1, free list len 0, seg size 2, 0 merges
    merged operations:
     insert 0, delete mark 0, delete 0
    discarded operations:
     insert 0, delete mark 0, delete 0
    Hash table size 4425293, used cells 32, node heap has 1 buffer(s)
    13577.57 hash searches/s, 202.47 non-hash searches/s
    

    Подробности в разделе 16.16.3.

  • Таблица INFORMATION_SCHEMA.INNODB_METRICS обеспечивает большинство точек данных, найденных в InnoDB Standard Monitor плюс другие точки данных. Чтобы рассмотреть буферные метрики изменения и описание каждой, дайте следующий запрос:
    mysql> SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS
                     WHERE NAME LIKE '%ibuf%'\G
    

    Подробности об использовании таблицы INNODB_METRICS см. в разделе 16.14.6.

  • Таблица INFORMATION_SCHEMA.INNODB_BUFFER_PAGE обеспечивает метаданные о каждой странице в буферном пуле, включая индекс буфера изменений и бит-карту страниц буфера изменений. Буферные страницы изменения идентифицированы PAGE_TYPE. IBUF_INDEX тип страницы для буферных индексных страниц и IBUF_BITMAP бит-карты страниц буфера изменений.

    Запрос таблицы INNODB_BUFFER_PAGE может потребовать существенной работы. Чтобы избежать воздействовать на работу, воспроизведите проблему, которую Вы хотите исследовать, и выполните Ваши запросы на испытательном экземпляре.

    Например, Вы можете запросить таблицу INNODB_BUFFER_PAGE , чтобы определить приблизительное количество страниц IBUF_INDEX и IBUF_BITMAP как процент полных буферных страниц пула.

    SELECT (SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE
            WHERE PAGE_TYPE LIKE 'IBUF%') AS change_buffer_pages,
            (SELECT COUNT(*) FROM INFORMATION_SCHEMA.INNODB_BUFFER_PAGE) AS
             total_pages,
            (SELECT ((change_buffer_pages/total_pages)*100)) AS
             change_buffer_page_percentage;
    +---------------------+-------------+-------------------------------+
    | change_buffer_pages | total_pages | change_buffer_page_percentage |
    +---------------------+-------------+-------------------------------+
    | 25                  | 8192        | 0.3052                        |
    +---------------------+-------------+-------------------------------+
    

    Для информации о других данных, обеспеченных таблицей INNODB_BUFFER_PAGE , см. раздел 22.30.1. Для связанной информации об использовании см. раздел 16.14.5.

  • Performance Schema предоставляет инструментовку ожидания mutex для буфера изменений усовершенствованного исполнительного контроля. Чтобы рассмотреть инструментовку буфера изменения, примените следующий запрос:
    mysql> SELECT * FROM performance_schema.setup_instruments
                       WHERE NAME LIKE '%wait/synch/mutex/innodb/ibuf%';
    +-------------------------------------------------------+---------+-------+
    | NAME                                                  | ENABLED | TIMED |
    +-------------------------------------------------------+---------+-------+
    | wait/synch/mutex/innodb/ibuf_bitmap_mutex             | YES     | YES   |
    | wait/synch/mutex/innodb/ibuf_mutex                    | YES     | YES   |
    | wait/synch/mutex/innodb/ibuf_pessimistic_insert_mutex | YES     | YES   |
    +-------------------------------------------------------+---------+-------+
    

    Для информации о контроле ожиданий InnoDB mutex см. раздел 16.15.2.

16.4.3. Адаптивный хеш-индекс

Адаптивный хеш-индекс (AHI) позволяет InnoDB выступить больше как база данных в памяти на системах с соответствующими комбинациями рабочей нагрузки и вполне достаточной памяти для буферного пула, не жертвуя никакими особенностями или надежностью. Эта опция активирована опцией innodb_adaptive_hash_index или выключена при старте сервера параметром --skip-innodb_adaptive_hash_index.

Основанный на наблюдаемом образце поисков, MySQL создает хеш, индексиря использование префикса ключа индекса. Префикс ключа может быть любой длины, и может случиться так, что только некоторые из значений в B-дереве появляются в хеш-индексе. Хеш-индекс создан по требованию для тех страниц индекса, к которым часто получают доступ.

Если таблица почти полностью расположена в основной памяти, хеш-индекс может ускорить запросы, включая прямой поиск любого элемента, разворачивая значение в своего рода указатель. InnoDB имеет механизм, который отслеживает поиски в индексе. Если InnoDB находит, которые запросы могли получить пользу из создания хеш-индекса, это делается автоматически.

С некоторыми рабочими нагрузками ускорение от хеш-индекса очень перевешивает дополнительную работу, чтобы контролировать индекные поиски и поддерживать структуру. Иногда блокировка чтения-записи, которая контролирует доступ к адаптивному хешу может стать источником проблем при тяжелых рабочих нагрузках, таких как многократные параллельные соединения. Запросы с операторами LIKE и подстановочными знаками % также имеют тенденцию не извлекать выгоду из AHI. Для рабочих нагрузок, где адаптивный хеш не нужен, выключение его уменьшает ненужную работу. Поскольку трудно предсказать заранее, является ли эта особенность подходящей для особой системы, считайте рабочие точки отсчета с включенным и отключенным хэшем, используя реалистическую рабочую нагрузку. Архитектурные изменения в MySQL 5.6 и выше делают больше рабочих нагрузок подходящими для того, чтобы запретить адаптивный хеш, чем в более ранних выпусках, хотя это все еще включено по умолчанию.

Адаптивный хеш индекс разделен. Каждый индекс связан с определенным разделением, и каждое разделение защищено отдельным замком. Разделением управляет опция innodb_adaptive_hash_index_parts. По умолчанию это 8. Максимум 512.

Хеш-индекс всегда создается основанный на существующем индексе B-tree для таблицы. InnoDB может создать хеш-индекс на префиксе любой длины ключа, определенного для B-дерева, в зависимости от образца поисков, который InnoDB наблюдает для индекса B-дерева. Хеш-индекс может быть частичным, покрывая только те страницы индексирования, к которым часто получают доступ.

Вы можете контролировать использование адаптивного хеш-индекса и утверждение для его использования в разделе SEMAPHORES вывода команды SHOW ENGINE INNODB STATUS . Если Вы видите, что много потоков ждут на RW-замке, создаваемом в btr0sea.c, тогда могло бы быть полезно отключить адаптивную хеш-индексацию.

Подробности в разделе 9.3.8.

16.4.4. Буфер журнала Redo

Буфер журнала Redo область памяти, которая хранит данные, которые записаны в журнал redo. Размер буфера журнала, определен опцией innodb_log_buffer_size. Буфер журнала периодически сбрасывается к файлу системного журнала на диске. Большой буфер позволяет большим транзакциям работать без потребности записать журнал на диск прежде, чем транзакции передадут. Таким образом, если у Вас есть транзакции, которые обновляют, вставляют или удаляют много строк, увеличение буфера экономит дисковый ввод/вывод.

Опция innodb_flush_log_at_trx_commit управляет, как содержание буфера журнала записано в файл системного журнала. Опция innodb_flush_log_at_timeout управляет тем, как часто буфер сбрасывается на диск.

16.4.5. Системное табличное пространство

Системное табличное пространство InnoDB содержит словарь данных (метаданные для объектов InnoDB), область хранения для буфера doublewrite, буфер изменения и журнал отмены. Системное табличное пространство также содержит таблицу и индексные данные для любых создаваемых пользователем таблиц, которые составлены в системном табличном пространстве. Системное табличное пространство считают совместно используемым табличным пространством, так как оно совместно использовано многими таблицами.

Системное табличное пространство представлено одним или более файлами с данными. По умолчанию, один системный файл с данными, названный ibdata1, создается в каталоге MySQL data. Размером и числом системных файлов с данными управляет опция innodb_data_file_path.

Подробности в разделах 16.6.1 и 16.7.1.

16.4.6. Буфер Doublewrite

Буфер doublewrite это область хранения, расположенная в системном табличном пространстве, где InnoDB пишет страницы, которые сбрасываются из буферного пула InnoDB прежде, чем страницы будут записаны их надлежащим позициям в файле с данными. Только после сброса и записи в буфер doublewrite, InnoDB запишет страницы на их надлежащие позиции. Если есть катастрофический отказ операционной системы, подсистемы хранения или процесса mysqld в середине записи страницы, InnoDB может позже найти хорошую копию страницы в буфере doublewrite во время восстановления катастрофического отказа.

Хотя данные всегда пишутся дважды, буфер doublewrite не требует вдвое большего количества ввода/вывода или вдвое большего количества операций ввода/вывода. Данные записаны в буфер doublewrite непосредственно как большой последовательный кусок одним вызовом fsync().

Буфер doublewrite включен по умолчанию в большинстве случаев. Чтобы отключить буфер doublewrite, надо установить опцию innodb_doublewrite в 0.

Если системные файлы табличного пространства (файлы ibdata ) расположены на устройствах Fusion-io, которые поддерживают атомную запись буфер doublewrite автоматически отключен, и атомная запись Fusion-io используются для всех файлов с данными. Поскольку буферная установка doublewrite глобальна, буферизация doublewrite также отключена для файлов с данными, находящихся на не Fusion-io аппаратных средствах. Эта функция поддерживается только на аппаратных средствах Fusion-io и включена только для Fusion-io NVMFS в Linux. Чтобы в полной мере воспользоваться этой особенностью рекомендуется установка innodb_flush_method в O_DIRECT.

16.4.7. Журнал отмены

Журнал отмены (или сегмент отмены) является областью хранения, которая хранит копии данных, измененных активными транзакциями. Если другая транзакция должна видеть оригинальные данные (как часть последовательной работы чтения), неизмененные данные получены от этой области хранения. По умолчанию эта область физически часть системного табличного пространства. Однако, журналы отмены могут также находиться в отдельных табличных пространствах отмены. Для получения дополнительной информации см. разделы 16.7.7 и 16.3.

InnoDB поддерживает 128 журналов отмены. Однако, 32 из 128 журналов отмены зарезервированы для временных табличных транзакций. Каждой транзакции, которая обновляет временную таблицу (исключая транзакции только для чтения) назначают два журнала отмены, один просто отмены, второй с поддержкой redo. Транзакции только для чтения получают один журнал отмены, поскольку транзакциям только для чтения разрешают изменить только временные таблицы.

Это оставляет 96 доступных журналов отмены, каждый из которых поддерживает до 1023 параллельных изменяющих данные транзакций, для полного предела приблизительно 96k параллельных изменяющих данные транзакций. 96K предела предполагает, что транзакции не изменяют временные таблицы. Если все изменяющие данные транзакции также изменяют временные таблицы, полный предел составляет приблизительно 32k параллельных транзакций изменения данных. Для получения дополнительной информации о журналах отмены, которые сохранены для временных табличных транзакций, см. раздел 16.4.11.1.

Опция innodb_undo_logs определяет число журналов отмены, используемых InnoDB.

16.4.8. Табличные пространства File-Per-Table

Табличное пространство File-Per-Table однотабличное пространство, которое создается в его собственном файле с данными, а не в системном табличном пространстве. Таблицы составлены в табличных пространствах file-per-table, когда включена опция innodb_file_per_table. Иначе таблицы InnoDB составлены в системном табличном пространстве. Каждое табличное пространство file-per-table представлено файлом данных .ibd, который создается в каталоге базы данных по умолчанию.

Табличные пространства per-table допускают форматы строк DYNAMIC и COMPRESSED, которые поддерживают функции, такие как хранение вне страницы для данных переменной длины и табличное сжатие. Для информации об этих особенностях и о других преимуществах табличных пространств file-per-table см. раздел 16.7.4.

16.4.9. Общие табличные пространства

Совместно используемое InnoDB табличное пространство создано с помощью CREATE TABLESPACE . Общие табличные пространства могут быть созданы за пределами каталога данных MySQL, способны к хранению многих таблиц и поддерживают таблицы всех форматов строк.

Таблицы добавлены к общему табличному пространству через CREATE TABLE tbl_name ... TABLESPACE [=] tablespace_name или ALTER TABLE tbl_name TABLESPACE [=] tablespace_name.

16.4.10. Табличное пространство отмены

Табличное пространство отмены состоит из одного или более файлов, содержащих журнал отмены. Табличное пространство отмены создается только когда журнал отмены отделен от системного табличного пространства, используя опции innodb_undo_tablespaces и innodb_undo_directory .

16.4.11. Временное табличное пространство

Временное табличное пространство это табличное пространство для несжатых временных таблиц и связанных объектов. Параметр конфигурации innodb_temp_data_file_path определяет относительный путь для временного файла с данными табличного пространства. Если innodb_temp_data_file_path не задан, в каталоге данных создается единственный авторасширяемый файл с данными в 12 МБ и именем ibtmp1. Временное табличное пространство обновлено при каждом старте сервера и получает динамически произведенный ID пространства, который помогает избежать конфликтов с существующими ID. Временное табличное пространство не может находиться на сыром устройстве. Сервер не стартует, если временное табличное пространство не может быть создано.

Временное табличное пространство удалено при нормальном завершении работы или прерванной инициализации. Временное табличное пространство не удалено, когда катастрофический отказ происходит. В этом случае администратор базы данных может удалить временное табличное пространство вручную или перезапустить сервер с той же самой конфигурацией, которая удаляет и обновляет временное табличное пространство.

16.4.11.1. Временные табличные журналы отмены InnoDB

Временные табличные журналы отмены используются для временных таблиц и связанных объектов. Этот тип журнала отмены не redo-журнал, поскольку временные таблицы не восстановлены во время восстановления катастрофического отказа и не требуют такого журнала. Временные табличные журналы отмены, однако, используются для отмены, в то время как сервер работает. Этот специальный тип журнала позволяет обойтись без redo-протоколов ввода/вывода для временных таблиц и связанных объектов. Временные табличные журналы отмены находятся во временном табличном пространстве. Значение по умолчанию: временный файл табличного пространства, ibtmp1, расположенный в каталоге данных по умолчанию и всегда обновляется при запуске сервера. Определяемое пользователем местоположение для временного файла табличного пространства может быть определено, устанавливая опцию конфигурации innodb_temp_data_file_path.

32 сегмента отмены отведены для временных табличных журналов отмены для транзакций, которые изменяют временные таблицы и связанные объекты, что означает, что максимальное количество сегментов отмены, доступных для изменяющих данные транзакций, которые производят отчеты отмены, 96. С 96 доступными сегментами отмены предел параллельных изменяющих данные транзакциях составляет 96K. Для получения дополнительной информации см. разделы 16.3 и 16.8.7.

16.4.12. Журнал redo

Журнал redo это основанная на диске структура данных, используемая во время восстановления катастрофического отказа, чтобы исправить данные, написанные неполными транзакциями. Во время нормального функционирования журнал кодирует просьбы изменить табличные данные, которые следуют из запросов SQL или вызовов низкого уровня API. Модификации, которые не закончили обновлять файлы с данными перед неожиданным завершением работы, переигрываются автоматически во время инициализации, прежде, чем соединения будут приняты. Для информации о роли журналов redo в восстановлении после катастрофического отказа см. раздел 16.17.1.

По умолчанию журнал физически представлен на диске как ряд файлов, названных ib_logfile0 и ib_logfile1. MySQL пишет файлы системного журнала круговым способом. Данные в журнале закодированы с точки зрения затронутых записей, эти данные все вместе упоминаются как redo. Проход данных через журнал представлен постоянно увеличивающимся значением LSN.

Для соответствующей информации см.:

16.4.12.1. Групповой Commit для сброса Redo-журнала

InnoDB, как ACID-совместимый механизм базы данных, сбрасывает redo-журнал транзакций прежде, чем это будет передано. InnoDB использует групповой commit, чтобы сгруппировать много таких запросов вместе. Из-за этого InnoDB делает одну запись в файл журнала, чтобы выполнить действие для многих транзакций, которые идут приблизительно в то же самое время, значительно улучшая пропускную способность.

Для получения дополнительной информации об исполнении COMMIT и других действий с транзакциями см. see раздел 9.5.2.

16.5. Блокировка InnoDB и операционная модель

Чтобы осуществить крупномасштабное или очень надежное приложение базы данных или настроить работу MySQL, важно понять блокировку и операционную модель InnoDB.

Этот раздел обсуждает несколько тем, связанных с блокировкой и операционной моделью, с которой Вы должны быть знакомы.

  • раздел 16.5.1 описывает типы блокировки, используемые InnoDB.

  • раздел 16.5.2 описывает операционные уровни изоляции и стратегии блокировки. Это также обсуждает использование autocommit, последовательные чтения без блокировки и блокирующие чтения.
  • раздел 16.5.3 обсуждает определенные типы блокировок InnoDB для различных запросов.
  • раздел 16.5.4 описывает как InnoDB применяет блокировку следующего ключа, чтобы избежать призрачных строк.
  • раздел 16.5.5 обеспечивает пример тупика, обсуждает обнаружение тупика и обеспечивает подсказки для уменьшения и обработки тупиков в InnoDB.

16.5.1. Блокировка InnoDB

Этот раздел описывает типы блокировки, используемые InnoDB.

Совместно использованные и исключительные блокировки

InnoDB реализует стандартные блокировки уровня строки, где есть два типа блокировок, совместно использованные (S) и исключительные (X).

Если транзакция T1 держит совместно используемую (S) блокировку на строке r, тогда запросы от некоторой отличной транзакции T2 для блокировки на строке r обработаны следующим образом:

  • Запрос T2 для S можно немедленно предоставить. В результате оба запроса T1 и T2 держат S на r.

  • Запрос T2 для X нельзя немедленно предоставить.

Если транзакция T1 держит исключительную (X) блокировку строки r, запрос от некоторой отличной транзакции T2 для блокировки любого типа на r не может быть немедленно предоставлен. Вместо этого транзакция T2 должна ждать, пока транзакция T1 выпустит блокировку на строке r.

Блокировки намерения

InnoDB допускает многократные блокировки степени детализации, которые разрешают сосуществование блокировок на уровне строки и соединяет все таблицы. Чтобы сделать блокировку на многих уровнях степени детализации дополнительные типы блокировок, названных блокировками намерения, используются. Блокировки намерения это блокировки на уровне таблицы в InnoDB, которые указывают, какого типа блокировки (совместно используемые или исключительные) транзакция потребует позже для строки в той таблице. Есть два типа блокировок намерения, используемых в InnoDB (предположим, что транзакция T требует блокировку обозначенного типа на таблице t):

Например, SELECT ... LOCK IN SHARE MODE поставит IS, а SELECT ... FOR UPDATE поставит IX.

Протокол блокировки намерения:

  • Прежде, чем транзакция может приобрести S на строку в таблице t, это должно сначала приобрести IS или более сильную блокировку на t.

  • Прежде, чем транзакция может приобрести X на строку, это должно сначала приобрести IX на t.

Эти правила могут быть удобно получены в итоге посредством следующей матрицы совместимости типа блокировки.

X IXS IS
XКонфликтуют КонфликтуютКонфликтуютКонфликтуют
IXКонфликтуютСовместимы КонфликтуютСовместимы
SКонфликтуютКонфликтуют СовместимыСовместимы
ISКонфликтуютСовместимы СовместимыСовместимы

Блокировку предоставляют транзакции требования, если это совместимо с существующими блокировками, но не предоставляют, если это находится в противоречии с существующими блокировками. Тогда транзакция ждет, пока противоречивая существующая блокировка не будет выпущена. Если запрос блокировки находится в противоречии с существующей блокировкой и не может быть предоставлен, потому что он вызвал бы тупик, происходит ошибка.

Таким образом, блокировки намерения не блокируют ничего кроме полных табличных запросов (например, LOCK TABLES ... WRITE). Основная цель IX и IS показать, что кто-то блокирует строку или собирается заблокировать строку в таблице.

Блокировка записей

Блокировка записей это блокировка на индексной записи. Например, SELECT c1 FOR UPDATE FROM t WHERE c1 = 10; препятствует тому, чтобы любая другая транзакция вставила, обновила или удалила строки, где значение t.c1 = 10.

Такие блокировки всегда блокируют индексные записи, даже если таблица определена без индекса. Для таких случаев InnoDB создает кластеризируемый скрытый индекс и использует его. См. раздел 16.8.8.

Блокировки промежутка

Блокировки промежутка это блокировка на промежутке между индексными записями или блокировка на промежутке перед первой или после последней индексной записью. Например, SELECT c1 FOR UPDATE FROM t WHERE c1 BETWEEN 10 and 20; препятствует тому, чтобы другие транзакции вставили значение 15 в столбец t.c1 независимо от того, было ли уже какое-либо такое значение в столбце, потому что промежутки между всеми существующими значениями в диапазоне заблокированы.

Промежуток может охватить одно значение, несколько значений или даже быть пустым.

Блокировки промежутка это часть компромисса между производительностью и параллелизмом и используются в некоторых операционных уровнях изоляции.

Блокировка промежутка не необходима для запросов, которые блокируют строки, используя уникальный индекс, чтобы искать уникальную строку. Это не включает случай, что условие поиска включает только некоторые столбцы уникального многостолбцового индекса, в этом случае блокировка промежутка действительно происходит. Например, если столбец id имеет уникальный индекс, следующий запрос использует только блокировку записи индекса для строки с id 100, и не имеет значения, вставляют ли другие сеансы строки в предыдущий промежуток:

SELECT * FROM child WHERE id = 100;

Если id не индексирован или имеет неуникальный индекс, запрос действительно блокирует предыдущий промежуток.

Также стоит отметить здесь, что противоречивые блокировки могут быть проведены на промежутке различными транзакциями. Например, транзакция A может держать совместно используемую блокировку промежутка (S-блокировка промежутка) на промежутке, в то время как транзакция B держит исключительную блокировку промежутка (X-блокировка промежутка) на том же самом промежутке. Причина, по которой позволены противоречивые блокировки промежутка, состоит в том, что если запись очищена из индекса, блокировки промежутка для записи, которые держат разные транзакции, должны быть слиты.

Блокировки промежутка в InnoDB только мешают другим транзакциям вставить в промежуток. Они не препятствуют тому, чтобы различные транзакции работали с ним как-то иначе. Таким образом, X-блокировка промежутка имеет тот же самый эффект как S-блокировка.

Блокировка промежутка может быть отключена явно. Это происходит, если Вы изменяете операционный уровень изоляции на READ COMMITTED. При этих обстоятельствах блокировка промежутка отключена для поисков и сканирований индексов и используется только для проверки ограничения внешнего ключа и дублирования ключей.

Есть также другие эффекты использования уровня изоляции READ COMMITTED. Блокировки записи для того, чтобы несоответствующие строки были выпущены после того, как MySQL оценил WHERE. Для UPDATE InnoDB делает такое чтение, что это возвращает последнюю переданную версию в MySQL так, чтобы MySQL мог определить, соответствует ли строка WHERE выражению в UPDATE.

Блокировки следующего ключа

Это комбинация блокировки записи на записи индекса и блокировки промежутка перед этой записью.

InnoDB выполняет блокировку на уровне строки таким способом, что когда это ищет или просматривает индекс таблицы, то устанавливает совместно использованные или исключительные блокировки на индексных записях. Таким образом, блокировки на уровне строки фактически блокировки индекса. Блокировка следующего ключа также затрагивает промежуток перед этой записью. Если у одного сеанса есть совместно используемая или исключительная блокировка на записи R в индексе, другой сеанс не может вставить новую индексную запись в промежутке сразу перед R в порядке индекса.

Предположите, что индекс содержит значения 10, 11, 13 и 20. Возможные блокировки для этого индекса покрывают следующие интервалы, где круглая скобка обозначает исключение конечной точки интервала, а квадратная скобка обозначает включение конечной точки:

(минус бесконечность, 10]
(10, 11]
(11, 13]
(13, 20]
(20, бесконечность)

Для последнего интервала это блокирует промежуток выше самого большого значения в индексе и виртуальную запись, имеющую значение выше, чем любое значение фактически в индексе. Такой записи на самом деле нет, таким образом, в действительности, это блокировка только промежутка после самого большого значения индекса.

По умолчанию InnoDB работает на уровне изоляции REPEATABLE READ . В этом случае InnoDB использует такую блокировку для поисков и индексных просмотров, что предотвращает появление призрачных строк (см. раздел 16.5.4).

Блокировки намерения вставки

Блокировки намерения вставки это тип блокировки промежутка, установленной операцией INSERT до вставки строки. Эта блокировка сигнализирует намерение вставить таким способом, что многие транзакции, вставляющие в то же самый промежуток, не должны ждать друг друга, если они не вставляют в ту же самую позицию в пределах промежутка. Предположите, что есть индексные записи со значениями 4 и 7. Отдельные транзакции, которые пытаются вставить значения 5 и 6, соответственно, каждая блокировка промежуток между 4 и 7 с блокировками намерения вставки до получения исключительной блокировки на вставленной строке, но не блокируют друг друга, потому что строки не находятся в противоречии.

Следующий пример демонстрирует транзакцию, берущую блокировку намерения вставки до получения исключительной блокировки на вставленной записи. Пример вовлекает двух клиентов A и B.

Клиент А составляет таблицу, содержащую две записи в индексе (90 и 102) и затем запускает транзакцию, которая помещает исключительную блокировку на записи индекса с ID больше 100. Исключительная блокировка включает блокировку промежутка перед записью 102:

mysql> CREATE TABLE child (id int(11) NOT NULL, PRIMARY KEY(id))
                 ENGINE=InnoDB;
mysql> INSERT INTO child (id) values (90),(102);
mysql> START TRANSACTION;
mysql> SELECT * FROM child WHERE id > 100 FOR UPDATE;
+-----+
| id  |
+-----+
| 102 |
+-----+

Клиент B начинает транзакцию, чтобы вставить отчет в промежуток. Транзакция берет блокировку намерения вставки, в то время как она ждет, чтобы получить исключительную блокировку.

mysql> START TRANSACTION;
mysql> INSERT INTO child (id) VALUES (101);

Чтобы рассмотреть данные о блокировке намерения вставки, выполните SHOW ENGINE INNODB STATUS. Данные, подобные следующим, появляются под заголовком TRANSACTIONS:

mysql> SHOW ENGINE INNODB STATUS\G
...
SHOW ENGINE INNODB STATUS
---TRANSACTION 8731, ACTIVE 7 sec inserting
mysql tables in use 1, locked 1
LOCK WAIT 2 lock struct(s), heap size 360, 1 row lock(s)
MySQL thread id 3, OS thread handle 0x7f996beac700, query id 30 localhost root update
INSERT INTO child (id) VALUES (101)
------- TRX HAS BEEN WAITING 7 SEC FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 31 page no 3 n bits 72 index `PRIMARY` of table `test`.`child`
trx id 8731 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
 0: len 4; hex 80000066; ascf;;
 1: len 6; hex 000000002215; asc " ;;
 2: len 7; hex 9000000172011c; asc r  ;;...

Блокировка AUTO-INC

Блокировка AUTO-INC это специальная блокировка на уровне таблицы, взятая транзакциями, вставляющими в таблицы со столбцами AUTO_INCREMENT. В самом простом случае, если одна транзакция вставляет значения в таблицу, любые другие транзакции должны ждать, чтобы сделать их собственные вставки в эту таблицу так, чтобы строки, вставленные первой транзакцией, получили последовательные значения первичного ключа.

Параметр конфигурации innodb_autoinc_lock_mode управляет алгоритмом, используемым для блокировки автоинкремента. Это позволяет Вам выбирать, как балансировать между предсказуемыми последовательностями значений автоинкремента и максимальным параллелизмом для операций вставки.

Подробности в разделе 16.8.5.

Блокировка предиката для пространственного индекса

InnoDB поддерживает индексацию столбцов с пространственными данными (см. раздел 12.5.3.5 ).

Чтобы обработать блокировку для вовлечения операций с индексами SPATIAL, блокировка следующего ключа не работает хорошо, чтобы поддержать уровни изоляции REPEATABLE READ или SERIALIZABLE. В многомерных данных нет никакого абсолютного понятия упорядочивания, таким образом, не ясно, что является следующим ключом.

Чтобы обеспечить поддержку уровней изоляции для таблиц с индексами SPATIAL, InnoDB применяет блокировки предиката. Индекс SPATIAL содержит минимальный ограничительный прямоугольник (MBR) значения, таким образом, InnoDB проводит в жизнь последовательное чтение на индексе, устанавливая предикат, на значении MBR, используемом для запроса. Другие транзакции не могут вставить или изменить строку, которая соответствовала бы условию запроса.

16.5.2. Транзакционная модель InnoDB

В транзакционной модели InnoDB цель состоит в том, чтобы объединить лучшие свойства мультиверсионной базы данных с традиционной двухфазовой блокировкой. InnoDB выполняет блокировку на уровне строки и выполняет запросы как последовательные чтения без блокировки по умолчанию в стиле Oracle. Информация о блокировке в InnoDB сохранена пространственно-эффективно так, чтобы эскалация блокировки не была необходима. Как правило, нескольким пользователям разрешают блокировать каждую строку таблицы InnoDB или любое случайное подмножество строк без истощения памяти InnoDB.

16.5.2.1. Операционные уровни изоляции

Операционная изоляция это одна из основ обработки базы данных. Изоляция это I в ACID, уровень изоляции это установка, которая точно настраивает баланс между работой и надежностью, последовательностью и воспроизводимостью результатов, когда многократные транзакции производят изменения и выполняют запросы в то же самое время.

InnoDB реализует все четыре операционных уровня изоляции, которые описаны стандартом SQL:1992: READ UNCOMMITTED , READ COMMITTED , REPEATABLE READ и SERIALIZABLE. По умолчанию используется REPEATABLE READ .

Пользователь может изменить уровень изоляции для единственного сеанса или для всех последующих соединений командой SET TRANSACTION. Чтобы установить уровень изоляции по умолчанию сервера для всех соединений, используйте параметр --transaction-isolation. Для получения дальнейшей информации об уровнях изоляции и устанавливающем уровень синтаксисе см. раздел 14.3.6.

InnoDB реализует каждый из операционных уровней изоляции, описанных здесь, используя различные стратегии блокировки. Вы можете провести в жизнь высокую степень последовательности с уровнем по умолчанию REPEATABLE READ , для операций на решающих данных, где совместимость с ACID принципиальна. Или Вы можете расслабить правила последовательности с READ COMMITTED или READ UNCOMMITTED в ситуациях, где точная последовательность и повторимые результаты менее важны, чем уменьшение количества издержек блокировки. SERIALIZABLE проводит в жизнь еще более строгие правила, чем REPEATABLE READ , и используется, главным образом, в специализированных ситуациях, таких как транзакции XA и для того, чтобы расследовать проблемы с параллелизмом и тупиками.

Следующий список описывает, как MySQL поддерживает различные операционные уровни. Список идет от обычно используемого уровня до наименее используемого.

  • REPEATABLE READ

    Это уровень изоляции значения по умолчанию для InnoDB. Для последовательных чтений есть важное отличие от READ COMMITTED: все последовательные чтения в пределах той же самой транзакции читают снимок, установленный первым чтением. Это соглашение означает это, если Вы выпускаете несколько простых (без блокировки) запросов SELECT в пределах той же самой транзакции, то эти SELECT последовательны также друг относительно друга. См. раздел 16.5.2.3.

    Чтобы заблокировать чтения (SELECT с FOR UPDATE или LOCK IN SHARE MODE), UPDATE и DELETE, блокировка зависит от того, использует ли запрос уникальный индекс с уникальным условием поиска или условием поиска типа диапазона. Если уникальный индекс с уникальным условием поиска, InnoDB блокирует только найденные индексные записи, но не промежуток перед этим. Для других условий поиска InnoDB блокирует индексный диапазон, используя блокировки промежутка или блокировки следующего ключа, чтобы заблокировать вставки другими сеансами в промежутки, покрытые диапазоном.

  • READ COMMITTED

    Несколько подобный Oracle уровень изоляции относительно последовательных чтений (без блокировки): каждое последовательное чтение, даже в пределах той же самой транзакции, устанавливает и читает свой собственный новый снимок. См. раздел 16.5.2.3.

    Для того, чтобы заблокировать чтения (SELECT с FOR UPDATE или LOCK IN SHARE MODE), UPDATE и DELETE, InnoDB блокирует только индексные записи, но не промежутки перед ними, и таким образом разрешает свободную вставку новых записей рядом с заблокированными.

    В MySQL 8.0 при использовании READ COMMITTED не применяется блокировка промежутка за исключением проверки ограничения внешнего ключа и дубликата ключа. Кроме того, блокировки записи используются для того, чтобы несоответствовующие строки были выпущены после того, как MySQL оценил WHERE.

    Если Вы используете READ COMMITTED, Вы должны использовать основанное на строке двоичное журналирование.

  • READ UNCOMMITTED

    Запросы SELECT выполнены способом без блокировки, но возможная более ранняя версия строки могла бы использоваться. Таким образом, используя этот уровень изоляции, такие чтения не последовательны. Это также называют грязным чтением. Иначе этот уровень изоляции работает как READ COMMITTED.

  • SERIALIZABLE

    Похоже на REPEATABLE READ, но InnoDB неявно конвертируется все простые SELECT в SELECT ... LOCK IN SHARE MODE, autocommit выключен. Если же autocommit включен, SELECT выполняется в собственной транзакции. Это только для чтения и может быть преобразовано в последовательную форму, если выполнено как последовательное чтение (без блокировки) и не должно заблокировать другие транзакции. Чтобы простой SELECT заблокировать, если другие транзакции изменили выбранные строки, отключите autocommit.

16.5.2.2. autocommit, Commit и Rollback

В InnoDB вся пользовательская деятельность происходит в транзакции. Если режим autocommit включен, каждый запрос SQL формирует единственную транзакцию самостоятельно. По умолчанию MySQL запускает сеанс для каждого нового соединения с включенным autocommit, таким образом, MySQL делает передачу после каждого запроса SQL, если запрос не возвращал ошибку. См. раздел 16.20.4.

Сеанс, который имеет включенную опцию autocommit, может выполнить транзакцию из многих запросов, запуская это с явной командой START TRANSACTION или BEGIN и завершая COMMIT или ROLLBACK. См. раздел 14.3.1.

Если autocommit выключен в пределах сеанса с помощью SET autocommit = 0, у сеанса всегда есть открытая транзакция. COMMIT или ROLLBACK заканчивает текущую транзакцию, и новая запускается.

Если сеанс, который имеет выключенный autocommit завершается, явно не передавая заключительную транзакцию, MySQL отменяет эту транзакцию до прежнего состояния.

Некоторые запросы неявно заканчивают транзакцию, как будто Вы сделали a COMMIT. См. раздел 14.3.3.

COMMIT означает, что изменения, сделанные в текущей транзакции, делаются постоянными и становятся видимыми другим сеансам. ROLLBACK отменяет все модификации, сделанные текущей транзакцией. COMMIT и ROLLBACK снимают все блокировки, которые были установлены во время текущей транзакции.

Группировка операций DML с транзакциями

По умолчанию соединение с сервером MySQL начинается с включенным режимом autocommit, который автоматически передает каждый запрос SQL, когда Вы выполняете это. Этот режим работы мог бы быть незнакомым, если у Вас есть опыт работы с другими системами базы данных, где общепринятой практикой является последовательность запросов DML и передача или отмена их все вместе.

Чтобы использовать транзакцию из многих запросов, выключите режим командой SET autocommit = 0 и заканчивайте каждую транзакцию командой COMMIT или ROLLBACK. Чтобы это сделать при включенном autocommit, начинайте каждую транзакцию с START TRANSACTION и заканчивайте COMMIT или ROLLBACK. Следующий пример показывает две транзакции. Первая передана, вторая отменена.

shell> mysql test
mysql> CREATE TABLE customer (a INT, b CHAR (20), INDEX (a));
Query OK, 0 rows affected (0.00 sec)
mysql> -- Do a transaction with autocommit turned on.
mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO customer VALUES (10, 'Heikki');
Query OK, 1 row affected (0.00 sec)
mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)
mysql> -- Do another transaction with autocommit turned off.
mysql> SET autocommit=0;
Query OK, 0 rows affected (0.00 sec)
mysql> INSERT INTO customer VALUES (15, 'John');
Query OK, 1 row affected (0.00 sec)
mysql> INSERT INTO customer VALUES (20, 'Paul');
Query OK, 1 row affected (0.00 sec)
mysql> DELETE FROM customer WHERE b = 'Heikki';
Query OK, 1 row affected (0.00 sec)
mysql> -- Now we undo those last 2 inserts and the delete.
mysql> ROLLBACK;
Query OK, 0 rows affected (0.00 sec)
mysql> SELECT * FROM customer;
+----+--------+
| a  | b      |
+----+--------+
| 10 | Heikki |
+----+--------+
1 row in set (0.00 sec)
mysql>
Транзакции на клиентских языках

В таких API, как PHP, Perl DBI, JDBC, ODBC или обычный интерфейс C Вы можете послать команду управления транзакцией серверу как строку точно так же, как любые другие запросы SQL, такие как SELECT или INSERT. Некоторые API также предлагает отдельные специальные функции или методы.

16.5.2.3. Последовательные чтения без блокировки

Последовательное чтение означает, что InnoDB использует мультиверсии, чтобы представить запросу снимок базы данных в момент времени. Запрос видит изменения, произведенные транзакциями, которые передали перед тем моментом времени, но никаких изменений, произведенных позже или нейтральными транзакциями. Исключение: запрос видит изменения, произведенные более ранними запросами в пределах той же самой транзакции. Это исключение вызывает следующую аномалию: если Вы обновляете некоторые строки в таблице, SELECT видит последнюю версию обновленных строк, но мог бы также видеть более старые версии любых строк. Если другие сеансы одновременно обновляют ту же самую таблицу, аномалия означает, что Вы могли бы видеть таблицу в статусе, который никогда не существовал в базе данных.

Если операционный уровень изоляции REPEATABLE READ (по умолчанию), все последовательные чтения в пределах той же самой транзакции читают снимок, установленный первым таким чтением в этой транзакции. Вы можете получить более новый снимок для своих запросов, передавая текущую транзакцию и выдавая новые запросы.

На уровне READ COMMITTED каждое последовательное чтение в пределах транзакции устанавливает и читает свой собственный новый снимок.

Последовательное чтение это режим по умолчанию, в котором InnoDB обрабатывает запросы SELECT на уровнях READ COMMITTED и REPEATABLE READ . Последовательное чтение не устанавливает блокировок на таблицы, к которым оно получает доступ, и поэтому другие сеансы свободны изменить те таблицы в то же самое время, когда последовательное чтение выполняется на таблице.

Предположите, что Вы работаете на уровне REPEATABLE READ . Когда Вы выпускаете последовательное чтение (то есть, одиночный SELECT), InnoDB дает Вашей транзакции точку времени, согласно которой Ваш запрос видит базу данных. Если другая транзакция удаляет строку и передает после того, как Ваша точка была назначена, Вы не видите строку как удаленную. Вставки и обновления обработаны так же.

Снимок базы данных относится к SELECT в пределах транзакции, не обязательно к запросам DML. Если Вы вставляете или изменяете некоторые строки и затем передаете транзакцию, запросы DELETE или UPDATE от другой параллельной транзакции REPEATABLE READ могут затронуть те переданные строки, даже при том, что сеанс не мог запросить их. Если транзакция действительно обновляет или удаляет строки, переданные иной транзакцией, те изменения действительно становятся видимыми к текущей транзакции. Например, Вы могли бы столкнуться с такой ситуацией:

SELECT COUNT(c1) FROM t1 WHERE c1 = 'xyz';
-- Returns 0: no rows match.
DELETE FROM t1 WHERE c1 = 'xyz';
-- Deletes several rows recently committed by other transaction.

SELECT COUNT(c2) FROM t1 WHERE c2 = 'abc';
-- Returns 0: no rows match.
UPDATE t1 SET c2 = 'cba' WHERE c2 = 'abc';
-- Affects 10 rows: another txn just committed 10 rows with 'abc' values.
SELECT COUNT(c2) FROM t1 WHERE c2 = 'cba';
-- Returns 10: this txn can now see the rows it just updated.

Вы можете обновить точку времени, передавая Вашу транзакцию и затем делая другой запрос SELECT или START TRANSACTION WITH CONSISTENT SNAPSHOT .

В следующем примере сеанс A видит строку, вставленную B, только когда B передал вставку, а A передал также, чтобы точка времени обновилась.

      Сеанс A            Сеанс B

 SET autocommit=0;  SET autocommit=0;
time
| SELECT * FROM t;
| empty set
|   INSERT INTO t VALUES (1, 2);
|
v SELECT * FROM t;
  empty set
COMMIT;

  SELECT * FROM t;
  empty set

  COMMIT;

  SELECT * FROM t;
  ---------------------
  | 1    | 2          |
  ---------------------

Если Вы хотите видеть свежее состояние базы данных, используйте любой уровень изоляции READ COMMITTED или блокировку чтения:

SELECT * FROM t LOCK IN SHARE MODE;

На уровне READ COMMITTED каждое последовательное чтение в пределах транзакции устанавливает и читает свой собственный новый снимок. С LOCK IN SHARE MODE блокировка чтения происходит вместо этого: SELECT блокирует до транзакции, содержащей самые новые концы строк (см. раздел 16.5.2.4).

Последовательное чтение не работает по определенным запросам DDL:

  • Последовательное чтение не работает через DROP TABLE, поскольку MySQL не может использовать таблицу, которая была удалена, а InnoDB разрушает эту таблицу.

  • Последовательное чтение не работает через ALTER TABLE, так как запрос делает временную копию оригинальной таблицы и удаляет оригинальную таблицу, когда временная копия создана. Когда Вы используете последовательное чтение в пределах транзакции, строки в новой таблице невидимы, потому что те строки не существовали, когда снимок транзакции был взят. В этом случае транзакция возвращает ошибку: ER_TABLE_DEF_CHANGED , Table definition has changed, please retry transaction.

Тип чтения изменяется для выбора в запросах INSERT INTO ... SELECT, UPDATE ... (SELECT) и CREATE TABLE ... SELECT, которые не определяют FOR UPDATE или LOCK IN SHARE MODE:

  • По умолчанию InnoDB использует более сильные блокировки и SELECT действует как READ COMMITTED, где каждое последовательное чтение, даже в пределах той же самой транзакции, устанавливает и читает свой собственный новый снимок.

  • Чтобы использовать последовательное чтение в таких случаях, установите уровень изоляции транзакции READ UNCOMMITTED, READ COMMITTED или REPEATABLE READ (то есть, что-либо кроме SERIALIZABLE). В этом случае никакие блокировки не установлены на строках, считанных из выбранной таблицы.

16.5.2.4. Блокировка чтений

Если Вы запрашиваете данные и затем вставляете или обновляете связанные данные в пределах той же самой транзакции, запрос SELECT не дает достаточную защиту. Другие транзакции могут обновить или удалить те же самые строки, которые Вы только что запросили. InnoDB понимает два типа блокировки чтений, которые предлагают дополнительную безопасность:

  • SELECT ... LOCK IN SHARE MODE задает совместно используемый режим блокировки на любые строки, которые считаны. Другие сеансы могут считать строки, но не могут изменить их, пока Ваша транзакция не передается. Если какая-либо из этих строк была изменена другой транзакцией, которая еще не передалась, Ваш запрос ждет ее завершения и затем использует последние значения.

  • Для индексных записей поиска SELECT ... FOR UPDATE блокирует строки и любые связанные записи в индексе, как будто была команда UPDATE для тех строк. Другие транзакции заблокированы на обновление тех строк из SELECT ... LOCK IN SHARE MODE или от чтения данных в определенных операционных уровнях изоляции. Последовательные чтения игнорируют любой набор блокировок на записях, которые существуют в представлении чтения. Старые версии записи не могут быть заблокированы: они восстановлены, применяя журнал отмены к копии записи в памяти.

Эти пункты прежде всего полезны, имея дело со структурированными деревом или структурированными данными графика в единственной таблице или в разделении на несколько таблиц. Вы пересекаете края или ответвления дерева от одного места до другого, резервируя право возвратиться и изменить любой из этих указателей.

Все блокировки, установленные LOCK IN SHARE MODE и FOR UPDATE выпущены, когда транзакция передана или отменена.

Блокировка строк для использования обновления SELECT FOR UPDATE применяется, когда autocommit отключен любым способом (START TRANSACTION или установкой autocommit в 0). Если autocommit включен, строки, соответствующие спецификации, не заблокированы.

Примеры использования

Предположите, что Вы хотите вставить новую строку в таблицу child и удостоверьтесь, что дочерняя строка имеет родительскую строку в таблице parent. Ваш код программы может гарантировать ссылочную целостность всюду по этой последовательности операций.

Во-первых, используйте последовательное чтение, чтобы запросить таблицу PARENT и проверьте, что родительская строка существует. Можете Вы безопасно вставлять дочернюю строку в таблицу CHILD? Нет, потому что некоторый другой сеанс мог удалить родительскую строку в момент между Вашими SELECT и INSERT.

Чтобы избежать этой потенциальной проблемы, используйте SELECT с LOCK IN SHARE MODE:

SELECT * FROM parent WHERE NAME = 'Jones' LOCK IN SHARE MODE;

После LOCK IN SHARE MODE запрос возвращает 'Jones', который Вы можете безопасно добавить в дочернюю запись в таблице CHILD и передать транзакцию. Любая транзакция, которая пытается приобрести исключительную блокировку в применимой строке в таблице PARENT ждет, пока Вы не закончите, то есть, пока данные во всех таблицах не находятся в последовательном статусе.

Для другого примера, рассмотрите область счетчика целого числа в таблице таблице CHILD_CODES, используемую, чтобы назначить уникальный идентификатор каждому дочернему элементу в таблице CHILD. Не используйте последовательное чтение или совместно используемое чтение, чтобы считать текущее значение счетчика, потому что два пользователя базы данных могли видеть то же самое значение счетчика, и происходит ошибка дублирования ключа, если две транзакции пытаются добавить строки с тем же самым идентификатором к CHILD.

Здесь LOCK IN SHARE MODE плохое решение, потому что, если два пользователя читают счетчик в то же самое время, по крайней мере один из них заканчивает в тупике, когда пытается обновить счетчик.

Чтобы осуществить чтение и постепенное увеличение счетчика, сначала выполните блокировку чтения счетчика через FOR UPDATE, а затем увеличьте счетчик. Например:

SELECT counter_field FROM child_codes FOR UPDATE;
UPDATE child_codes SET counter_field = counter_field + 1;

SELECT ... FOR UPDATE читает последние доступные данные, устанавливая исключительные блокировки на каждой строке, которую читает. Таким образом, это устанавливает те же самые блокировки, какие ищущий UPDATE установил бы на строках.

Предыдущее описание просто пример того, как работает SELECT ... FOR UPDATE. В MySQL определенная задача производства уникального идентификатора фактически может быть выполнена, используя только единственный доступ к таблице:

UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + 1);
SELECT LAST_INSERT_ID();

SELECT просто получает информацию об идентификаторе (определенном для текущего соединения). Это не получает доступ ни к какой таблице.

16.5.3. Установка блокировок различными запросами SQL в InnoDB

Блокировка чтения, UPDATE или DELETE вообще устанавливают блокировки записи на каждой записи индекса, которая просмотрена в обработке запроса SQL. Не имеет значения, есть ли условие WHERE в запросе, которое исключило бы строку. InnoDB не помнит точное выражение WHERE, а только знает, которые индексные диапазоны, были просмотрены. Блокировки обычно следующего ключа, которые также блокируют промежуток сразу перед записью. Однако, блокировка промежутка может быть отключена явно, что заставляет блокировку следующего ключа не использоваться. Подробности в разделе 16.5.1. Операционный уровень изоляции также может затронуть, какие блокировки установлены, см. раздел 14.3.6.

Если вторичный индекс используется в поиске, и блокировки индексной записи, которые будут установлены, исключительны, InnoDB также получает соответствующие записи кластеризируемого индекса и ставит на них блокировки.

Различия между совместно используемыми и исключительными блокировками описаны в разделе 16.5.1.

Если Вы не имеете индекса, подходящего для Вашего запроса, и MySQL должен просмотреть всю таблицу, чтобы обработать запрос, каждая строка таблицы становится заблокированной, что в свою очередь блокирует все вставки другими пользователями в таблицу. Важно создать хороший индекс так, чтобы Ваши запросы не просматривали слишком много строк.

Для SELECT ... FOR UPDATE или SELECT ... LOCK IN SHARE MODE блокировки приобретены для просмотренные строки и, как ожидают, будут выпущены для строк, которые не имеют право на включение в набор результатов (например, если они не соответствуют критериям, поданным в WHERE). Однако, в некоторых случаях, строки нельзя было бы немедленно разблокировать, потому что отношения между строкой результата и ее первоисточником потеряны во время выполнения запроса. Например, в UNION просмотренные (и заблокированные) строки могли бы быть вставлены во временную таблицу перед оценкой, имеют ли они право на набор результатов. При этом потеряны отношения строк во временной таблице к строкам в оригинальной таблице, и последние строки не разблокируют до конца выполнения запроса.

InnoDB устанавливает типы блокировок следующим образом.

  • SELECT ... FROM последовательное чтение, читая снимок базы данных и не устанавливая блокировок, если операционный уровень изоляции не установлен в SERIALIZABLE. Для уровня SERIALIZABLE поиск ставит совместно использованные блокировки следующего ключа на индексные записи.

  • SELECT ... FROM ... LOCK IN SHARE MODE ставит совместно использованные блокировки следующего ключа на все индексные записи, используемые поиском.
  • Для индексных записей поиска SELECT ... FROM ... FOR UPDATE блокирует другие сеансы от выполнения SELECT ... FROM ... LOCK IN SHARE MODE или чтения в определенных операционных уровнях изоляции. Последовательные чтения проигнорируют любой набор блокировок на записях, которые существуют в представлении чтения.
  • UPDATE ... WHERE ... ставит исключительную блокировку следующего ключа на каждой записи столкновения поиска.
  • Когда UPDATE меняет запись в кластеризируемом индексе, неявные блокировки взяты на затронутых записях вторичного индекса. UPDATE также ставит совместно использованные блокировки на затронутые записи вторичного индекса, когда выполняется проверка на дубликаты до вставки новых записей вторичного индекса и когда происходит собственно вставка новых записей вторичного индекса.
  • DELETE FROM ... WHERE ... ставит исключительную блокировку следующего ключа на каждую запись поиска.
  • INSERT ставит исключительную блокировку на вставленной строке. Эта блокировка на самом деле блокирует запись индекса, а не следующий ключ (то есть, нет никакой блокировки промежутка), и не препятствует тому, чтобы другие сеансы вставили в промежуток перед вставленной строкой.

    До вставки строки блокировка промежутка вызывает установку блокировки промежутка намерения вставки. Эта блокировка сигнализирует намерение вставить таким способом, что многократные транзакции, вставляющие в тот же самый промежуток, не должен ждать друг друга, если они не вставляют в той же самой позиции в пределах промежутка. Предположите, что есть индексные записи со значениями 4 и 7. Отдельные транзакции, которые пытаются вставить значения 5 и 6 блокируют промежуток между 4 и 7 с блокировками намерения вставки до получения исключительной блокировки на вставленной строке, но не заблокируют друг друга, потому что строки не находятся в противоречии.

    Если происходит ошибка дублирования ключа, совместно используемая блокировка на дубликате индексной записи установлена. Это использование совместно используемой блокировки может привести к тупику, когда есть многократные сеансы, пытающиеся вставить ту же самую строку, если у другого сеанса уже есть исключительная блокировка. Это может произойти, если другой сеанс удаляет строку. Предположите, что таблица InnoDB t1 имеет следующую структуру:

    CREATE TABLE t1 (i INT, PRIMARY KEY (i)) ENGINE = InnoDB;
    

    Теперь предположите, что три сеанса выполняют следующие операции в порядке:

    Сеанс 1:

    START TRANSACTION;
    INSERT INTO t1 VALUES(1);
    

    Сеанс 2:

    START TRANSACTION;
    INSERT INTO t1 VALUES(1);
    

    Сеанс 3:

    START TRANSACTION;
    INSERT INTO t1 VALUES(1);
    

    Сеанс 1:

    ROLLBACK;
    

    Сначала сеанс 1 приобретает исключительную блокировку на строку. Сеансы 2 и 3 получают ошибку дубликата ключа и они оба просят совместно используемую блокировку для строки. Когда сеанс 1 откатывается, он выпускает свою исключительную блокировку на строке, и запросы совместно используемой блокировки сеансами 2 и 3 удовлетворены. Вот здесь 2 и 3 в тупике: ни один не может приобрести исключительную блокировку на строке из-за совместно используемой блокировки, проводимой другим.

    Подобная ситуация происходит, если таблица уже содержит строку со значением ключа 1, и три сеанса выполняют следующие операции в порядке:

    Сеанс 1:

    START TRANSACTION;
    DELETE FROM t1 WHERE i = 1;
    

    Сеанс 2:

    START TRANSACTION;
    INSERT INTO t1 VALUES(1);
    

    Сеанс 3:

    START TRANSACTION;
    INSERT INTO t1 VALUES(1);
    

    Сеанс 1:

    COMMIT;
    

    Сеанс 1 приобретает исключительную блокировку на строке. Сеансы 2 и 3 получают ошибку дубликата ключа и оба требуют совместно используемую блокировку для строки. Когда сеанс 1 передает транзакцию, он выпускает свою исключительную блокировку на строке, и совместно используемые запросы блокировки 2 и 3 удволетворены. В итоге 2 и 3 в тупике: ни один не может приобрести исключительную блокировку на строку из-за совместно используемой блокировки, проводимой другим.

  • INSERT ... ON DUPLICATE KEY UPDATE отличается от простого INSERT использованием исключительной блокировки следующего ключа вместо совместно используемой блокировки на строке, которая будет обновлена, когда происходит ошибка дубликата ключа.
  • REPLACE сделан как INSERT, если нет никакого столкновения на уникальном ключе. Иначе исключительная блокировка следующего ключа помещена на строку, которая будет заменена.
  • INSERT INTO T SELECT ... FROM S WHERE ... ставит исключительную блокировку индексной записи (без блокировки промежутка) на каждой строке, вставленной в T. Если операционный уровень изоляции READ COMMITTED, InnoDB делает поиск на S как последовательное чтение (никакие блокировки не применяются). Иначе InnoDB ставит совместно используемую блокировку следующего ключа на строках из S. InnoDB должен установить блокировки в последнем случае: в восстановлении после резервного копирования каждый запрос SQL должен быть выполнен точно таким же образом, как это было сделано первоначально.

    CREATE TABLE ... SELECT ... выступает как SELECT с с совместно используемыми блокировками следующего ключа или как последовательное чтение при INSERT ... SELECT.

    Когда SELECT учавствует в REPLACE INTO t SELECT ... FROM s WHERE ... или UPDATE t ... WHERE col IN (SELECT ... FROM s ...), InnoDB ставит совместно используемую блокировку следующего ключа на строках из таблицы s.

  • Инициализируя ранее указанный столбец AUTO_INCREMENT в таблице, InnoDB ставит исключительную блокировку на конце индекса, связанного со столбцом AUTO_INCREMENT. При доступе к счетчику автоинкремента InnoDB использует режим блокировки AUTO-INC, где блокировка длится только до конца текущего запроса SQL, но не до конца всей транзакции. Другие сеансы не могут вставить в таблицу в то время, как проводится табличная блокировка AUTO-INC, см. раздел 16.5.2.

    InnoDB приносит значение ранее инициализированного столбца AUTO_INCREMENT, не устанавливая блокировок.

  • Если ограничение FOREIGN KEY определено на таблице, любые вставки, обновления или удаления, которые требуют, чтобы условие ограничения было проверено, ставят совместно используемую блокировку на уровне записи, которые проверяются на ограничение. InnoDB ставит эти блокировки в случае, где ограничение терпит неудачу.
  • LOCK TABLES ставит табличные блокировки, но это более высокий уровень MySQL, выше слоя InnoDB, который устанавливает эти блокировки. InnoDB знает о табличных блокировках, если innodb_table_locks = 1 (по умолчанию) и autocommit = 0 и уровень MySQL выше InnoDB знает о блокировках на уровне строки.

    Иначе автоматическое обнаружение тупика InnoDB не может обнаружить тупики, где такие табличные блокировки вовлечены. Кроме того, потому что в этом случае более высокий уровень MySQL не знает о блокировках на уровне строки, можно получить табличную блокировку на таблице, где у другого сеанса в настоящее время есть блокировки на уровне строки. Однако, это не подвергает опасности операционную целостность, как обсуждено в разделе 16.5.5.2. См. также раздел 16.8.7.

16.5.4. Строки-призраки

Так называемая призрачная проблема происходит в пределах транзакции, когда тот же самый запрос производит различные наборы строк в разное время. Например, если SELECT выполнен дважды, но возвращает строку во второй раз, которая не была возвращена в первый раз, строка призрачная.

Предположите, что есть индекс на столбце id таблицы child и что Вы хотите считать и заблокировать все строки из таблицы, имеющей значение идентификатора, больше 100, с намерением обновить некоторый столбец в выбранных строках позже:

SELECT * FROM child WHERE id > 100 FOR UPDATE;

Запрос просматривает индекс с первой записи, где id больше 100. Пусть в таблице строки с id 90 и 102. Если блокировки на записях индекса в просмотренном диапазоне не запрещают вставки в промежутки (в этом случае, промежуток между 90 и 102), другой сеанс может вставить новую строку в таблицу с id 101. Если Вы должны были выполнить тот же самый SELECT в пределах той же самой транзакции Вы видели бы новую строку с id 101 (призрак) в наборе результатов, возвращенном запросом. Если мы расцениваем ряд строк как элемент данных, новый призрачный дочерний элемент нарушил бы принцип изоляции транзакций, что транзакция должна быть в состоянии работать так, чтобы данные, которые она прочитала, не изменились во время транзакции.

Чтобы избегать таких ситуаций InnoDB использует алгоритм, названный блокировка следующего ключа, который комбинирует блокировку индекса строки с блокировкой промежутка. InnoDB выполняет блокировку на уровне строки таким способом, что когда это ищет или просматривает индекс таблицы, это устанавливает совместно использованные или исключительные блокировки на индексных записях, с которыми сталкивается. Таким образом, блокировки на уровне строки фактически блокировки индексных записей. Кроме того, блокировка следующего ключа на записи индекса также затрагивает промежуток перед этой записью. Таким образом, блокировка следующего ключа это блокировка индексной записи и промежутка, предшествующего ей. Если у одного сеанса есть совместно используемая или исключительная блокировка на записи R в индексе, другой сеанс не может вставить новую запись в промежутке немедленно перед R в порядке индекса.

Когда InnoDB просматривает индекс, это может также заблокировать промежуток после последней записи в индексе. Это происходит в предыдущем примере: чтобы предотвратить любую вставку в таблицу, где id больше 100, блокировки, установленные InnoDB, включают блокировку на промежутке после id 102.

Вы можете использовать блокировку следующего ключа, чтобы осуществить проверку уникальности в Вашем приложении: если Вы читаете свои данные в режиме совместного доступа и не видите дубликат строки, которую собираетесь вставить, то можете безопасно вставить свою строку и знать, что блокировка следующего ключа, установленная на преемнике Вашей строки во время чтения, предотвращает вставку дубликата для Вашей строки. Таким образом, блокировка следующего ключа позволяет Вам блокировать небытие чего-то в Вашей таблице.

Блокировка промежутка может быть отключена как обсуждено в разделе 16.5.1. Это может вызвать призрачные проблемы, потому что другие сеансы могут вставить новые строки в промежутки, когда блокировка промежутка отключена.

16.5.5. Тупики в InnoDB

Тупик это ситуация, где различные транзакции не способны продолжить работу потому, что каждый держит блокировку, нужную другой. Поскольку обе транзакции ждут ресурса, ни одна никогда не будет выпускать блокировки, которые держит.

Тупик может произойти, когда транзакции блокируют строки в многих таблицах (через такие запросы, как UPDATE или SELECT ... FOR UPDATE), но в противоположном порядке. Тупик может также произойти, когда такие запросы блокируют диапазоны, индексных записей и промежутки с каждой транзакцией, приобретающей некоторые блокировки, но не другие из-за проблемы синхронизацией. Для примера тупика см. раздел 16.5.5.1.

Чтобы уменьшить возможность тупиков, используйте транзакции, а не LOCK TABLES, сохраните транзакции, которые вставляют или обновляют данные, достаточно маленькими, чтобы они не оставались открытыми в течение долгих промежутков времени, когда различные транзакции обновляют многие таблицы или большие спектры строк, используйте тот же самый порядок операций (таких, как SELECT ... FOR UPDATE) в каждой транзакции, создайте индексы на столбцах, используемых в SELECT ... FOR UPDATE и UPDATE ... WHERE. Возможность тупиков не затронута уровнем изоляции, потому что уровень изоляции изменяет поведение операций чтения, в то время как тупики происходят из-за записи. Для получения дополнительной информации об уходе от условий тупика см. раздел 16.5.5.3 .

Когда обнаружение тупика включено (значение по умолчанию), и тупик действительно происходит, InnoDB обнаруживает условие и откатывает одну из транзакций до прежнего уровня. Если обнаружение тупика отключено, используя опцию innodb_deadlock_detect, InnoDB полагается на настройку innodb_lock_wait_timeout, чтобы откатить транзакции до прежнего уровня в случае тупика. Таким образом, даже если Ваша логика приложения правильна, Вы должны все еще обработать случай, где транзакция должна быть повторена. Чтобы увидеть последний тупик в пользовательской транзакции InnoDB, используйте SHOW ENGINE INNODB STATUS. Если частые тупики выделяют проблему с операционной структурой или обработкой ошибки приложения, работайте с опцией innodb_print_all_deadlocks, чтобы напечатать информацию обо всех тупиках в журнал ошибок mysqld . Для получения дополнительной информации о том, как тупики автоматически обнаружены и обработаны см. раздел 16.5.5.2.

16.5.5.1. Пример тупика в InnoDB

Следующий пример иллюстрирует, как ошибка может произойти, когда запрос блокировки вызвал бы тупик. Пример вовлекает двух клиентов A и B.

Клиент А составляет таблицу, содержащую одну строку, а затем начинает транзакцию. В пределах транзакции A получает блокировку S на строке, выбирая это в режиме общего доступа:

mysql> CREATE TABLE t (i INT) ENGINE = InnoDB;
Query OK, 0 rows affected (1.07 sec)

mysql> INSERT INTO t (i) VALUES(1);
Query OK, 1 row affected (0.09 sec)

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM t WHERE i = 1 LOCK IN SHARE MODE;
+---+
| i |
+---+
| 1 |
+---+

Затем клиент Б начинает транзакцию и пытается удалить строку из таблицы:

mysql> START TRANSACTION;
Query OK, 0 rows affected (0.00 sec)

mysql> DELETE FROM t WHERE i = 1;

Удаление требует блокировки X. Блокировку нельзя предоставить, потому что это является несовместимым с S, которую держит клиент А, таким образом, запрос идет в очередь запросов блокировки для строки, что блокирует клиента B.

Наконец, клиент также пытается удалить строку из таблицы:

mysql> DELETE FROM t WHERE i = 1;
ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction

Тупик происходит здесь потому, что клиент A требует блокировку X, чтобы удалить строку. Однако, тот запрос блокировки нельзя предоставить, потому что у клиента B уже есть запрос на X, и он ждет, пока клиент A выпустит блокировку S. Так они будут ждать друг друга вечно. В результате InnoDB производит ошибку для одного из клиентов и выпускает все его блокировки. Клиент возвращает эту ошибку:

ERROR 1213 (40001): Deadlock found when trying to get lock;
try restarting transaction

Здесь можно предоставить запрос блокировки для другого клиента, и это удаляет строку из таблицы.

16.5.5.2. Обнаружение тупика и отмена

Когда обнаружение тупика включено (по умолчанию), InnoDB автоматически обнаруживает транзакционные тупики и откатывает до прежнего уровня транзакцию или транзакции, чтобы найти выход из тупика. InnoDB старается выбрать маленькие транзакции, чтобы откатить, где размер транзакции определен числом затронутых ей строк.

InnoDB знает о табличных блокировках, если innodb_table_locks = 1 (по умолчанию) и autocommit = 0, и уровень MySQL выше этого знает о блокировках на уровне строки. Иначе InnoDB не может обнаружить тупики, где табличная блокировка, установленная MySQL LOCK TABLES или блокировка, установленная механизмом хранения кроме InnoDB, вовлечена. Решите эти ситуации, устанавливая значение innodb_lock_wait_timeout.

Когда InnoDB выполняет полную отмену транзакции, все блокировки, установленные транзакцией, выпущены. Однако, если только единственный запрос SQL откатывается до прежнего уровня в результате ошибки, некоторые из блокировок, установленных запросом, могут быть сохранены. Это происходит потому, что InnoDB хранит блокировки строк таким образом, что не может знать, какая блокировка была установлена которым запросом.

Если SELECT вызывает сохраненную функцию в транзакции, и запрос в пределах функции терпит неудачу, то запрос откатывается. Кроме того, если ROLLBACK выполнен после этого, откатывается вся транзакция.

Если раздел LATEST DETECTED DEADLOCK в InnoDB Monitor включает сообщение TOO DEEP OR LONG SEARCH IN THE LOCK TABLE WAITS-FOR GRAPH, WE WILL ROLL BACK FOLLOWING TRANSACTION, это указывает, что число транзакций в ожидании достигло предела 200. Это обработано как тупик и транзакция, пытающаяся встать в очередь откатывается до прежнего уровня. Та же самая ошибка может также произойти, если поток блокировки должен смотреть больше, чем на 1000000 блокировок, принадлежавших транзакциям в списке ожидания.

Для методов, чтобы организовать операции базы данных, чтобы избежать тупиков, см. раздел 16.5.5.

Отключение обнаружения тупика

На высоконагруженных системах обнаружение тупика может вызвать замедление, когда многочисленные потоки ждут той же самой блокировки. Время от времени может быть более эффективно отключить обнаружение тупика и положиться на опцию innodb_lock_wait_timeout для операционной отмены, когда тупик происходит. Обнаружение тупика может быть отключено, используя опцию innodb_deadlock_detect.

16.5.5.3. Как минимизировать и обработать тупики

Этот раздел основывается на концептуальной информации о тупиках в разделе 16.5.5.2. Это объясняет, как организовать операции базы данных, чтобы минимизировать тупики и последующую обработку ошибок, требуемую в приложениях.

Тупики это классическая проблема в транзакционных базах данных, но они не опасны, если не являются настолько частыми, что Вы не можете выполнить определенные транзакции вообще. Обычно Вы должны написать свои приложения так, чтобы они были всегда подготовлены перезапустить транзакцию, если она отменена из-за тупика.

InnoDB использует автоматическую блокировку на уровне строки. Вы можете получить тупики даже в случае транзакций, которые только вставляют или удаляют единственную строку. Это так, потому что эти операции не действительно атомарные, они автоматически устанавливают блокировки (возможно, несколько) индексных записей строки, вставленной или удаленной.

Вы можете справиться с тупиками и уменьшить вероятность их возникновения следующими методами:

  • В любое время скомандуйте SHOW ENGINE INNODB STATUS, чтобы определить причину нового тупика. Это может помочь Вам настроить свое приложение, чтобы избежать тупиков.

  • Если часты предупреждения о тупике, соберите более обширную информацию отладки, включая опцию innodb_print_all_deadlocks. Информация о каждом тупике, не только последнем, зарегистрирована в журнале ошибок MySQL. Отключите эту опцию, когда Вы закончите отладку.
  • Всегда готовьтесь перезапустить транзакцию, если это терпит неудачу. Тупики не опасны. Только попробуйте еще раз.
  • Сохраните транзакции маленькими и короткими по продолжительности, чтобы сделать их менее склонными к столкновению.
  • Передайте транзакции немедленно после создания ряда связанных изменений, чтобы сделать их менее склонными к столкновению. В частности не оставляйте интерактивную сессию mysql открытой в течение долгого времени с нейтральной транзакцией.
  • Если Вы используете блокировку чтения (SELECT ... FOR UPDATE или SELECT ... LOCK IN SHARE MODE), попытайтесь использовать более низкий уровень изоляции, такой как READ COMMITTED.
  • Когда изменение многих таблиц в пределах транзакции или различных наборов строк в той же самой таблице, делает те операции в последовательном порядке каждый раз, транзакции формируют четкие очереди и не заходят в тупик. Например, организуйте операции базы данных в функции в пределах Вашего приложения или вызывайте хранимые подпрограммы вместо того, чтобы кодировать многократные подобные последовательности INSERT, UPDATE и DELETE в различных местах.
  • Добавьте хорошо подобранный индекс к Вашим таблицам. Тогда Ваши запросы должны просмотреть меньше индексных записей и следовательно устанавливают меньше блокировок. Хорошо использовать EXPLAIN SELECT, чтобы определить, которые индекс сервер MySQL использует как самый подходящий для Ваших запросов.
  • Применяйте меньше блокировок. Если Вы можете позволить себе разрешить SELECT, чтобы возвратить данные из старого снимка, не добавляйте FOR UPDATE или LOCK IN SHARE MODE. Используя уровня изоляции READ COMMITTED хорошо здесь, потому что каждое последовательное чтение в пределах той же самой транзакции читает из ее собственного нового снимка.
  • Если ничто иное не помогает, преобразуйте в последовательную форму свои транзакции с блокировками на уровне таблицы. Правильный способ использовать LOCK TABLES с InnoDB: начать с SET autocommit = 0 (но не START TRANSACTION) сопровождаемый LOCK TABLES и не вызывать UNLOCK TABLES пока Вы не передаете транзакцию явно. Например, если Вы должны записать в таблицу t1 и читать из таблицы t2, Вы можете сделать это:
    SET autocommit=0;
    LOCK TABLES t1 WRITE, t2 READ, ...;
    ... do something with tables t1 and t2 here ...
    COMMIT;
    UNLOCK TABLES;
    

    Блокировки на уровне таблицы предотвращают параллельные обновления таблицы, избегая тупиков за счет менее быстрого отклика для занятой системы.

  • Другой способ преобразовать в последовательную форму транзакции состоит в том, чтобы создать вспомогательную таблицу, которая содержит только единственную строку. Каждое операция обновляет эту строку прежде, чем получить доступ к другим таблицам. Таким образом, все транзакции происходят последовательным способом. Отметьте, что мгновенный алгоритм обнаружения тупика InnoDB также работает в этом случае, потому что блокировка преобразования в последовательную форму это блокировка на уровне строки. С MySQL блокировки на уровне таблицы метод тайм-аута должен использоваться, чтобы решить тупики.

16.6. Конфигурация InnoDB

Этот раздел предоставляет информацию о конфигурации и процедуры для инициализации и запуска InnoDB, а также различные компоненты и особенности механизма хранения InnoDB. Для информации об оптимизации операций базы данных для таблиц InnoDB см. раздел 9.5 .

16.6.1. Конфигурация запуска InnoDB

Первые решения о настройке InnoDB вовлекают конфигурацию файлов с данными, файлов системного журнала, размера страницы и буферов памяти. Рекомендуется, чтобы Вы определили файл с данными, файл системного журнала и конфигурацию размера страницы прежде, чем создать экземпляр InnoDB. Изменение файла с данными или конфигурации файла системного журнала после запуска InnoDB может вовлечь нетривиальную процедуру, и размер страницы может быть определен только когда InnoDB начально инициализирован.

В дополнение к этим темам этот раздел предоставляет информацию об опциях в конфигурационном файле, рассматривая информацию об инициализации и важные соображения о хранении.

Определение опций в конфигурационном файле MySQL

Поскольку MySQL использует файл с данными, файл системного журнала и настройки конфигурации размера страницы, чтобы инициализировать InnoDB, рекомендуется, чтобы Вы определили эти настройки в конфигурационном файле, который MySQL читает при запуске, до инициализации InnoDB впервые. InnoDB инициализирован, когда сервер MySQL запущен, и первая инициализация InnoDB обычно происходит в первый раз, когда Вы запускаете сервер MySQL.

Вы можете поместить опции InnoDB в группу [mysqld] любого файла опции, который читает Ваш сервер, когда запускается. Местоположения файлов опции MySQL описаны в разделе 5.2.6.

Чтобы удостовериться, что mysqld читает опции только из определенного файла (и mysqld-auto.cnf), используйте --defaults-file как первую опцию в командной строке, запуская сервер:

mysqld --defaults-file=path_to_configuration_file

Просмотр информации об инициализации InnoDB

Чтобы видеть сведения об инициализации InnoDB во время запуска, запустите mysqld из командной строки. Когда mysqld запущен из командной строки, информация об инициализации выведена на консоль.

Например, в Windows, если mysqld расположен в C:\Program Files\MySQL\MySQL Server 8.0\bin, запустите MySQL так:

C:\> "C:\Program Files\MySQL\MySQL Server 8.0\bin\mysqld" --console

В Unix-системах mysqld расположен в подкаталоге bin установки MySQL:

sell> bin/mysqld --user=mysql &

Если Вы не посылаете вывод сервера на консоль, проверьте журнал ошибок после запуска, чтобы видеть информацию об инициализации InnoDB, напечатанную во время процесса запуска.

Для информации о запуске MySQL, используя другие методы, см. раздел 2.9.5.

Важные соображения о хранении

Рассмотрите следующие связанные с хранением соображения перед продолжением Вашей конфигурации.

  • В некоторых случаях работа базы данных улучшается, если все данные не помещены на тот же самый физический диск. Помещение файлов системного журнала на различном диске от данных очень часто выгодно для работы. Например, Вы можете поместить системные файлы с данными табличного пространства и файлы системного журнала на различных дисках. Вы можете также использовать сырые дисковые разделы (сырые устройства) для файлов с данными InnoDB, что может ускорить ввод/вывод. См. раздел 16.7.3.

  • В Linux желательно отключить кэширование записи .

    На дисководах ATA/SATA команда hdparm -W0 /dev/hda может работать, чтобы отключить кэширование записи. Остерегайтесь того, что некоторые диски или дисковые контроллеры могут быть неспособны отключить кэширование записи.

  • Относительно способностей восстановления InnoDB, которые защищают пользовательские данные, InnoDB использует метод потока файла, вовлекающий структуру, названную буфер doublewrite, который включен по умолчанию (innodb_doublewrite=ON ). Буфер doublewrite добавляет безопасность восстановления после катастрофического отказа и улучшает работу относительно большинства вариантов Unix, уменьшая потребность в fsync(). Рекомендуется держать опцию innodb_doublewrite включенной, если Вы обеспокоены целостностью данных или возможными отказами. Для дополнительной информации о буфере doublewrite см. раздел 16.11.1.
  • Если надежность критично важна для Ваших данных, не надо конфигурировать InnoDB использовать файлы с данными или файлы системного журнала на томах NFS. Потенциальные проблемы изменяются в зависимости от OS и версии NFS, и включают такие проблемы, как нехватка защиты от конфликтов записи и ограничения на максимальные размеры файла.

Системная конфигурация файла с данными табличного пространства

Системные файлы с данными табличного пространства сконфигурированы, используя опции innodb_data_file_path и innodb_data_home_dir .

innodb_data_file_path используется, чтобы сконфигурировать системные файлы с данными табличного пространства. Значение innodb_data_file_path должно быть списком из одной или более спецификаций файла с данными. Если Вы называете больше чем один файл с данными, отделяете их точкой с запятой (;):

innodb_data_file_path=datafile_spec1[;datafile_spec2]...

Например, следующая установка явно создает минимальное системное табличное пространство:

[mysqld]
innodb_data_file_path=ibdata1:12M:autoextend

Эта установка конфигурирует единственный файл с данными 12 МБ ibdata1. Никакое местоположение для файла не задано, так что по умолчанию, InnoDB создает это в каталоге данных MySQL.

Размеры определены, используя буквы суффикса K, M или G, чтобы указать на KB, MB или GB.

Табличное пространство, содержащее файл с данными 50 МБ фиксированного размера с именем ibdata1 и 50MB автомасштабируемый файл с именем ibdata2 в каталоге данных может быть сконфигурирован как это:

[mysqld]
innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend

Полный синтаксис для спецификации файла с данными включает имя файла, его размер и несколько дополнительных признаков:

file_name:file_size[:autoextend[:max:max_file_size]]

autoextend и max могут использоваться только для последнего файла с данными в строке innodb_data_file_path .

Если Вы определяете autoextend для последнего файла с данными, InnoDB расширяет файл с данными, если он исчерпывает свободное пространство в табличном пространстве. Инкремент составляет 64 МБ за один раз по умолчанию. Чтобы изменить инкремент, измените значение innodb_autoextend_increment.

Если диск становится полным, Вы могли бы добавить другой файл с данными на другом диске. Для инструкций реконфигурирования табличного пространства см. раздел 16.7.1.

InnoDB не знает о максимальном размере файла в файловой системе, так что следует быть осторожным на файловых системах, где максимальный размер файла маленькое значение, такое как 2GB. Чтобы определить максимальный размер для файла с данными, используйте параметр max после autoextend. Используйте max только в случаях, где ограничение дискового использования имеет жизненную важность, потому что превышение максимального размера вызывает фатальную ошибку, возможно, включая катастрофический отказ. Следующяя конфигурация позволяет ibdata1 расти до 500MB:

[mysqld]
innodb_data_file_path=ibdata1:12M:autoextend:max:500M

InnoDB создает файлы табличного пространства в каталоге данных MySQL по умолчанию (datadir ). Чтобы определить местоположение явно, используйте опцию innodb_data_home_dir . Например, чтобы создать два файла ibdata1 и ibdata2 в /myibdata:

[mysqld]
innodb_data_home_dir = /myibdata
innodb_data_file_path=ibdata1:50M;ibdata2:50M:autoextend

InnoDB не создает каталоги, так что удостоверьтесь, что каталог /myibdata существует прежде, чем Вы запустите сервер. Используйте Unix или DOS mkdir, чтобы создать любые необходимые каталоги.

Удостоверьтесь, что у сервера MySQL есть надлежащие права доступа, чтобы создать файлы в каталоге данных. Более широко, у сервера должны быть права доступа в любом каталоге, где это должно создать файлы с данными.

InnoDB формирует путь к каталогу для каждого файла с данными, дословно добавляя значение innodb_data_home_dir к имени файла с данными, добавляя разделитель пути (наклонная черта или наклонная черта влево) между значениями в случае необходимости. Если опция innodb_data_home_dir не определена в my.cnf вообще, значение по умолчанию ./, что означает каталог данных MySQL. Сервер MySQL изменяет свой текущий рабочий каталог на свой каталог данных, когда он начинает выполняться.

Если Вы определяете innodb_data_home_dir как пустую строку, Вы можете определить абсолютные пути для файлов с данными, перечисленных в innodb_data_file_path . Следующий пример эквивалентен предыдущему:

[mysqld]
innodb_data_home_dir =
innodb_data_file_path=/ibdata/ibdata1:50M;/ibdata/ibdata2:50M:autoextend

Конфигурация файла системного журнала InnoDB

По умолчанию InnoDB создает два файла системного журнала по 48 МБ в каталоге данных MySQL (datadir) с именами ib_logfile0 и ib_logfile1.

Следующие опции могут использоваться, чтобы изменить конфигурацию по умолчанию:

  • innodb_log_group_home_dir определяет путь к каталогу с файлами системного журнала (redo logs). Если эта опция не сконфигурирована, файлы создаются в каталоге данных MySQL (datadir).

    Вы могли бы использовать эту опцию, чтобы поместить файлы системного журнала в ином физическом местоположении хранения, чем файлы с данными, чтобы избежать потенциальных конфликтов ресурса ввода/вывода. Например:

    [mysqld]
    innodb_log_group_home_dir = /dr3/iblogs
    
  • innodb_log_files_in_group определяет число файлов системного журнала в группе журналов. Значение по умолчанию и рекомендуемое значение 2.

  • innodb_log_file_size определяет размер в байтах каждого файла системного журнала в группе журналлв. Объединенный размер файлов системного журнала ( innodb_log_file_size * innodb_log_files_in_group) не может превысить максимальное значение, которое является немного меньше чем 512GB. Пара файлов системного журнала по 255 GB, например, приближается к пределу, но не превышает его. Размер файла системного журнала по умолчанию составляет 48 МБ. Заметные значения колеблются от 4 МБ до 1/N размера буферного пула, где N число файлов системного журнала в группе. Чем больше значение, тем меньше деятельности потока контрольной точки необходимо в буферном пуле, сохраняя дисковый ввод/вывод. Для дополнительной информации см. раздел 9.5.4.

Конфигурация табличного пространства отмены InnoDB

По умолчанию журналы отмены это часть системного табличного пространства. Однако, Вы можете хотеть хранить их в одном или более отдельных табличных пространств отмены, как правило, на ином устройстве хранения данных.

Опция innodb_undo_directory определяет путь, где InnoDB создает отдельные табличные пространства для журналов отмены. Эта опция как правило используется в соединении с innodb_undo_logs и innodb_undo_tablespaces, которые определяют дисковое расположение журналов отмены вне системного табличного пространства.

Подробности в разделе 16.7.7 .

Конфигурация временного табличного пространства InnoDB

По умолчанию InnoDB создает единственный автомасштабируемый временный файл с данными табличного пространства ibtmp1 в каталоге данных MySQL (datadir ) это немного больше, чем 12 МБ. Конфигурация по умолчанию может быть изменена при запуске, используя innodb_temp_data_file_path.

innodb_temp_data_file_path определяет путь, имя файла и размер файла для временных файлов с данными табличного пространства. Полный путь к каталогу для файла сформирован, связывая innodb_data_home_dir с путем, определенным innodb_temp_data_file_path. Размер файла определен в KB, MB или GB (1024MB), добавляя K, M или G к значению размера. Сумма размеров файлов должна быть немного больше, чем 12 МБ.

Конфигурация размера страницы InnoDB

innodb_page_size определяет размер страницы для всех табличных пространств InnoDB. Это значение установлено, когда экземпляр создается и остается постоянным позже. Допустимые значения составляют 64k, 32k, 16k (по умолчанию), 8k и 4k. Альтернативно, Вы можете определить размер страницы в байтах (65536, 32768, 16384, 8192, 4096).

Размер страницы по умолчанию 16k является подходящим для широкого диапазона рабочих нагрузок, особенно для запросов, вовлекающих сканирование таблицы и операции DML, вовлекающие оптовые обновления. Меньшие размеры страницы могли бы быть более эффективными для рабочих нагрузок OLTP, вовлекающих, многие маленькие записи, где может быть проблемой, когда единственная страница содержит много строк. Меньшие страницы могли бы также быть эффективными с устройствами хранения данных SSD, которые, как правило, используют маленькие размеры блока. Задание размера страницы близким к размеру блока устройства хранения данных минимизирует количество неизменных данных, которые переписаны на диск.

Конфигурация памяти InnoDB

MySQL выделяет память различным кэшам и буферам, чтобы улучшить исполнение операций базы данных. Выделяя память для InnoDB, всегда считайте память требуемую операционной системой, память, выделенную другим приложениям, и память для других буферов MySQL и кэшей. Например, если Вы используете таблицы MyISAM, считайте объем памяти, выделенный для ключевого буфера (key_buffer_size ). Для краткого обзора буферов MySQL и кэшей см. раздел 9.12.3.1.

Буферы для InnoDB сконфигурированы, используя следующие параметры:

  • innodb_buffer_pool_size определяет размер буферного пула, который является областью памяти, которая содержит кэшируемые данные для таблиц InnoDB, индексов и других вспомогательных буферов. Размер буферного пула важен для системной работы, и рекомендуют выделить под innodb_buffer_pool_size от 50 до 75 процентов системной памяти. Буферный размер пула по умолчанию составляет 128MB. Подробности в разделе 9.12.3.1. Для информации о том, как сконфигурировать размер пула буферного см. раздел 16.6.3.2. Размер пула может быть сконфигурирован при запуске или динамически.

    На системах с большим объемом памяти Вы можете улучшить параллелизм, деля буферный пул на несколько экземпляров. Числом экземпляров пула управляет innodb_buffer_pool_instances. По умолчанию InnoDB создает один буферный экземпляр. Число экземпляров пула может быть сконфигурировано при запуске. Для получения дополнительной информации см. раздел 16.6.3.3.

  • innodb_log_buffer_size определяет размер в байтах буфера, который InnoDB применяет для записи файлов системного журнала на диск. Размер по умолчанию составляет 16 МБ. Большой буфер журнала позволяет большим транзакциям работать без потребности записать журнал на диск прежде, чем транзакции передадут. Если у Вас есть транзакции, которые обновляют, вставляют или удаляют много строк, Вы могли бы полагать, что увеличение размера буфера журнала уменьшит дисковый ввод/вывод. innodb_log_buffer_size может быть сконфигурирован при запуске. Для соответствующей информации см. раздел 9.5.4.

В 32-bit GNU/Linux x86 не стоит устанавливать использование памяти слишком большим. glibc может разрешить куче процесса расти по стекам потока, который разрушает Ваш сервер. Это рискованно, если память, выделенная процессу mysqld для глобальных и поточных буферов и кэшей, близка к или превышает 2GB.

Формула, подобная следующей, которая вычисляет глобальное и поточное распределение памяти для MySQL, может использоваться, чтобы оценить использование памяти MySQL. Вы, возможно, должны изменить формулу, чтобы составлять буферы и кэши в Вашей версии MySQL и конфигурации. Для краткого обзора буферов MySQL и кэшей см. раздел 9.12.3.1.

innodb_buffer_pool_size + key_buffer_size +
   max_connections*(sort_buffer_size+read_buffer_size+binlog_cache_size) +
   max_connections*2MB

Каждый поток использует стек (часто 2 МБ, но только 256 КБ в двоичных модулях MySQL от Oracle Corporation) и в худшем случае также использует еще sort_buffer_size + read_buffer_size памяти.

В Linux, если ядро настроено для поддержки большой страницы, InnoDB может использовать большие страницы, чтобы выделить память для буферного пула. См. раздел 9.12.3.2.

16.6.2. Конфигурирование InnoDB для работы только для чтения

Вы можете теперь запросить таблицы, где каталог данных MySQL находится на носителе только для чтения, включая опцию --innodb-read-only при запуске сервера.

Как это включить

Чтобы подготовить систему к работе только для чтения, удостоверьтесь, что вся необходимая информация сброшена в файлы с данными прежде, чем сохранить ее на носителе только для чтения. Выполните сервер с отключенной буферизацией изменения ( innodb_change_buffering=0) и сделайте медленную парковку.

Чтобы включить режим только для чтения для всего MySQL, определите следующие параметры конфигурации при запуске сервера:

  • --innodb-read-only=1

  • Если данные на носителе только для чтения, таком как DVD, или каталог /var недоступен на запись: --pid-file=path_on_writeable_media и --event-scheduler=disabled.

С MySQL 8.0 включение innodb_read_only блокирует табличные операции создания и удаления для всех механизмов хранения. Эти операции изменяют таблицы словаря данных в системной базе данных mysql, но те таблицы использует механизм хранения InnoDB и не может изменить, когда включена innodb_read_only . То же самое ограничение относится к любой работе, которая изменяет таблицы словаря данных, такой как ANALYZE TABLE и ALTER TABLE tbl_name ENGINE=engine_name .

Кроме того, другие таблицы в базе данных mysql используют механизм хранения InnoDB в MySQL 8.0. Например, CREATE USER, GRANT, REVOKE и INSTALL PLUGIN не работают в режиме только для чтения.

Сценарии использования

Этот режим работы является подходящим в таких ситуациях:

  • Распределение приложения MySQL или ряда данных MySQL на носителе данных только для чтения, таком как DVD или CD.

  • Многие экземпляры MySQL, запрашивающие тот же самый каталог данных одновременно, как правило в конфигурации складирования данных. Вы могли бы использовать этот метод, чтобы избежать бутылочного горлышка, которое может произойти с в большой степени загруженным сервером MySQL, или Вы могли бы использовать различные параметры конфигурации для различных случаев, чтобы настроить каждого для особых видов запросов.
  • Запросы данных, которые были помещены в статус только для чтения для безопасности или по причине целостности данных, таких как заархивированные резервные данные.

Эта особенность, главным образом, предназначена для гибкости в распределении и развертывании, а не сырой работе, основанной на аспекте только для чтения. См. раздел 9.5.3 для способов настроить исполнение запросов только для чтения, которые не требуют создания всего сервера только для чтения.

Как это работает

Когда сервер выполнен в режиме только для чтения через --innodb-read-only , многие особенности и компоненты InnoDB уменьшены или выключены полностью:

  • Буферизация изменений не сделана, в особенности никакие слияния от буфера изменения. Чтобы удостовериться, что буфер изменения пуст, когда Вы готовите систему к работе только для чтения, выключите его ( innodb_change_buffering=0) и сделайте медленную парковку.

  • Нет никакой фазы восстановления катастрофического отказа при запуске.
  • Поскольку redo log не используется в работе только для чтения, Вы можете установить innodb_log_file_size к самому маленькому возможному размеру (1 MB).
  • Все фоновые потоки кроме потоков чтения ввода/вывода выключены. Как следствие, случай только для чтения не может столкнуться ни с каким тупиком.
  • Информация о тупиках, вывод монитора и так далее не написана во временные файлы. Как следствие, SHOW ENGINE INNODB STATUS ничего не покажет.
  • Изменения настроек параметра конфигурации, которые обычно изменяли бы поведение операций записи, не имеют никакого эффекта, когда сервер находится в режиме только для чтения.
  • MVCC обрабатываемый, чтобы провести в жизнь уровни изоляции выключен. Все запросы читают последнюю версию записи, потому что обновление и удаление невозможны.
  • Журнал отмены не используется. Отключите любые настройки для опций innodb_undo_tablespaces и innodb_undo_directory.

16.6.3. Конфигурация буферного пула InnoDB

Этот раздел обеспечивает конфигурацию буферного пула InnoDB.

16.6.3.1. Буферный пул InnoDB

InnoDB поддерживает область хранения, названную буферным пулом для того, чтобы кэшировать данные и индексы в памяти. Знание, как буфер работает и использование в своих интересах его, чтобы сохранить данные, к которым часто получают доступ, в памяти, важный аспект настройки MySQL.

Вы можете сконфигурировать различные аспекты буферного пула InnoDB, чтобы улучшить работу.

  • Идеально Вы устанавливаете размер буферного пула к столь большому значению как возможно, оставляя достаточную память для других процессов на сервере, чтобы работать без чрезмерных проблем. Чем больше буферный пул, тем больше InnoDB работает как база данных в памяти, читая данные с диска однажды и затем получая доступ к данным в памяти во время последующих чтений. См. раздел 16.6.3.2 .

  • С 64-битовыми системами с большими размерами памяти Вы можете разделить буферный пул на многие части, чтобы минимизировать содержимое для структур памяти среди параллельных операций. Для деталей см. раздел 16.6.3.3.
  • Вы можете сохранить данные, к которым часто получают доступ, в памяти, несмотря на пики деятельности для операций, таких как резервные копии или сообщение. Для деталей см. раздел 16.6.3.4 .
  • Вы можете управлять когда и как InnoDB выполняет предвыборки и предварительно принести страницы в буферный пул асинхронно, в ожидании, что страницы скоро будут необходимы. Для деталей см. раздел 16.6.3.5.
  • Вы можете управлять, когда фоновый сброс грязных страниц происходит и действительно ли InnoDB динамически корректирует уровень сброса, исходя из рабочей нагрузки. Для деталей см. раздел 16.6.3.6 .
  • Вы можете точно настроить аспекты InnoDB, чтобы улучшить работу. Для деталей см. раздел 16.6.3.7.
  • Вы можете сконфигурировать как InnoDB сохраняет текущее состояние буферного пула, чтобы избежать длинного периода разминки после перезапуска сервера. Вы можете также сохранить текущее состояние пула, в то время как сервер работает. Для деталей см. раздел 16.6.3.8.

Алгоритм InnoDB LRU

InnoDB управляет буферным пулом как списком, используя вариант последнего использованного алгоритма (LRU). Когда нужно место, чтобы добавить новую страницу к пулу, InnoDB вычеркивает последнюю использованную страницу и добавляет новую страницу к середине списка. Эта вставка в середину обрабатывает список как два подсписка:

  • В начальном подсписке новые (или молодые) страницы, к которым недавно получили доступ.

  • В хвостовом подсписке старые, к которым получили доступ достаточно давно.

Этот алгоритм сохраняет страницы, которые в большой степени используются запросами в новом подсписке. Старый подсписок содержит менее используемые страницы, эти страницы кандидаты на вычеркивание.

Алгоритм LRU работает следующим образом по умолчанию:

  • 3/8 буферного пула посвящены старому подсписку.

  • Середина списка это граница, где хвост нового подсписка встречает голову старого.
  • Когда InnoDB читает страницу в буферный пул, это первоначально вставляет это в середину (голова старого подсписка). Страница может быть считана потому, что она требуется для определенной пользователем работы, такой как запрос SQL, или как часть работы предвыборки, выполненной автоматически InnoDB.
  • Доступ к странице в старом подсписке делает ее новой, перемещая ее к началу буферного пула (голова нового подсписка). Если страница была считана потому, что она требовалась, первый доступ происходит немедленно, и страница становится молодой сразу. Если страница была считана в порядке предвыборки, первый доступ немедленно не происходит (и мог бы не произойти вообще).
  • Поскольку база данных работает, страницы в буферном пуле, к которым не получают доступ устаревают, перемещаясь к хвосту списка. Страницы в новом и в старом подсписках могут быть сделаны новыми. Страницы в старом подсписке также стареют, как страницы, вставленные в середине. В конечном счете, страница, которая остается неиспользованной довольно долго, достигает хвоста старого подсписка и вычеркивается.

По умолчанию, страницы, считанные запросами немедленно, перемещаются в новый подсписок, означая, что они будут оставаться в буферном пуле в течение долгого времени. Сканирование таблицы (такое, как выполнено для mysqldump или SELECT без WHERE) может принести большой объем данных в буферный пул и выдавить эквивалентное количество более старых данных, даже если новые данные никогда не используются снова. Точно так же страницы, которые загружены фоновым потоком предвыборки, к которым затем получен доступ только однажды, перемещены в начало нового списка. Эти ситуации могут продвинуть часто используемые страницы к старому подсписку, где они становятся кандидатами на вычеркивание. Для информации об оптимизации этого поведения см. разделы 16.6.3.4 и 16.6.3.5.

InnoDB Standard Monitor выводит содержимое нескольких полей в разделе BUFFER POOL AND MEMORY, которые принадлежат работе алгоритма LRU буферного пула. Для деталей см. раздел 16.6.3.9.

Параметры конфигурации буферов InnoDB

Несколько параметров конфигурации затрагивают различные аспекты буферного пула InnoDB.

  • innodb_buffer_pool_size

    Определяет размер буферного пула. Если буферный пул является небольшим, и у Вас есть достаточная память, пул большего размера может улучшить работу, уменьшая количество дискового ввода/вывода, необходимого для доступа запросов к таблицам InnoDB. Опция innodb_buffer_pool_size является динамической, что позволяет Вам сконфигурировать размер, не перезапуская сервер. См. раздел 16.6.3.2.

  • innodb_buffer_pool_chunk_size

    Определяет размер куска для изменения размера пула. См. раздел 16.6.3.2.

  • innodb_buffer_pool_instances

    Делит буферный пул на пользовательское конкретное количество отдельных областей, каждая с его собственным списком LRU и связанными структурами данных, чтобы уменьшить издержки во время параллельного чтения памяти. Эта опция вступает в силу только, когда Вы устанавливаете innodb_buffer_pool_size к значению 1GB или больше. Полный размер, который Вы определяете, разделен среди всех буферных пулов. Для лучшей эффективности, определите комбинацию innodb_buffer_pool_instances и innodb_buffer_pool_size так, чтобы каждый экземпляр буферного пула составил по крайней мере 1 гигабайт. См. раздел 16.6.3.3.

  • innodb_old_blocks_pct

    Определяет приблизительный процент буферного пула, который InnoDB использует для старого подсписка блока. Диапазон значений от 5 до 95. Значение по умолчанию 37 (то есть, 3/8 пула). См. раздел 16.6.3.4 .

  • innodb_old_blocks_time

    Определяет, сколько времени в миллисекундах (ms) страница, вставленная в старый подсписок, должна остаться там после первого доступа к ней прежде, чем сможет быть перемещена в новый подсписок. Если значение 0, страница, вставленная в старый подсписок, немедленно перемещается в новый подсписок в первый раз, когда к ней получают доступ, независимо от того, как быстро после вставки доступ происходит. Если значение больше 0, страницы остаются в старом подсписке, пока доступ не происходит, по крайней мере, столько миллисекунд после первого доступа. Например, значение 1000 предписывает страницам остаться в старом подсписке в течение 1 секунды после первого доступа прежде, чем они смогут переместиться в новый подсписок.

    Установка innodb_old_blocks_time больше 0 препятствует тому, чтобы одноразовое сканирование таблицы затопило новый подсписок страницами, используемыми только для просмотра. К строкам страницы для просмотра получают доступ много раз в быстрой последовательности, но страница не использована после этого. Если innodb_old_blocks_time установлен в значение больше, чем время обработки страницы, эта страница остается в старом и сдвигается к хвосту списка, который будет выселен быстро. Этим путем страницы, используемые только для одноразового просмотра, не действуют в ущерб в большой степени используемым страницам в новом подсписке.

    innodb_old_blocks_time может быть установлен во время выполнения, таким образом, Вы можете изменить его временно, выполняя такие операции, как сканирование таблицы и дампы:

    SET GLOBAL innodb_old_blocks_time = 1000;
    ... perform queries that scan tables ...
    SET GLOBAL innodb_old_blocks_time = 0;
    

    Эта стратегия не применяется, если Ваше намерение нагреть буферный пул, заполняя его контентом таблицы. Например, оценочные испытания часто выполняют сканирование таблицу или индекса при запуске сервера, потому что те данные обычно были бы в буферном пуле после периода нормальной эксплуатации. В этом случае установите innodb_old_blocks_time в 0, по крайней мере пока идет фаза разминки.

    См. раздел 16.6.3.4.

  • innodb_read_ahead_threshold

    Управляет чувствительностью линейной предвыборки, чтобы предварительно принести страницы в буферный пул .

    См. раздел 16.6.3.5 .

  • innodb_random_read_ahead

    Включает случайный метод предвыборки страниц в буферный пул. Случайное чтение это метод, который предсказывает, какие страницы могли бы скоро быть необходимы, основываясь на страницах, которые уже в буферном пуле, независимо от порядка, в котором были считаны те страницы. innodb_random_read_ahead отключен по умолчанию. См. раздел 16.6.3.5.

  • innodb_adaptive_flushing

    Определяет, скорректировать ли динамически уровень сброса flushing грязных страниц в буферном пуле, основываясь на рабочей нагрузке. Корректировка уровня потока динамически предназначена, чтобы избежать взрывов деятельности ввода/вывода. Эта установка включена по умолчанию. См. раздел 16.6.3.6 .

  • innodb_adaptive_flushing_lwm

    Нижний процент redo log, при котором адаптивный сброс включен. См. раздел 16.6.3.7.

  • innodb_flush_neighbors

    Определяет, сбрасывают ли страницы из буферного пула другие грязные страницы в том же самом экстенте. См. раздел 16.6.3.7.

  • innodb_flushing_avg_loops

    Число итераций, для которых InnoDB сохраняет ранее сделанный снимок состояния сброса, управляя, как быстро адаптивный сброс отвечает на изменяющиеся рабочие нагрузки. См. раздел 16.6.3.7.

  • innodb_lru_scan_depth

    Параметр, который влияет на алгоритмы и эвристику для работы сброса для буферного пула. Прежде всего интересен для исполнительных экспертов, настраивающих рабочие нагрузки I/O. Это определяет как далеко вниз поток page_cleaner сканирует буферный пул LRU в поисках грязных страниц для сброса. См. раздел 16.6.3.7.

  • innodb_max_dirty_pages_pct

    InnoDB старается сбросить данные из буферного пула так, чтобы процент грязных страниц не превысил это значение. Определите целое число в диапазоне от 0 до 99. Значение по умолчанию 75. См. раздел 16.6.3.6 .

  • innodb_max_dirty_pages_pct_lwm

    Нижний уровень (в процентах) грязных страниц, где предварительному сбросу позволяют управлять отношением грязных страниц. Значение по умолчанию 0 отключает предварительно это поведение полностью.

    См. раздел 16.6.3.7 .

  • innodb_buffer_pool_filename

    Определяет название файла, который хранит список ID табличного пространства и страницы, произведенный innodb_buffer_pool_dump_at_shutdown или innodb_buffer_pool_dump_now. См. раздел 16.6.3.8.

  • innodb_buffer_pool_dump_at_shutdown

    Определяет, сделать ли запись страниц, кэшируемых в буферном пуле, когда сервер MySQL закрыт, чтобы сократить процесс следующего перезапуска. См. раздел 16.6.3.8.

  • innodb_buffer_pool_load_at_startup

    Определяет, что на запуске сервера MySQL буферный пул автоматически подогревается, загружая те же самые страницы, которые это содержало в более раннее время. Как правило, используется в комбинации с innodb_buffer_pool_dump_at_shutdown. См. раздел 16.6.3.8.

  • innodb_buffer_pool_dump_now

    Немедленно делает запись страниц, кэшируемых в буферном пуле. См. раздел 16.6.3.8.

  • innodb_buffer_pool_load_now

    Немедленно нагревает буферный пул, загружая ряд страниц данных, не ожидая перезапуска сервера. Может быть полезно, чтобы возвратить кэш-память к известному статусу во время сопоставительного анализа или к готовому серверу MySQL, чтобы возобновить его нормальную рабочую нагрузку после выполнения запросов для отчетов или обслуживания. Как правило используется с innodb_buffer_pool_dump_now. См. раздел 16.6.3.8.

  • innodb_buffer_pool_dump_pct

    Определяет процент последний раз используемых страниц для каждого буферного пула для сброса. Диапазон от 1 до 100. См. раздел 16.6.3.8.

  • innodb_buffer_pool_load_abort

    Прерывает процесс восстановления буферного содержимого, вызванный innodb_buffer_pool_load_at_startup или innodb_buffer_pool_load_now. См. раздел 16.6.3.8.

16.6.3.2. Конфигурирование размера буферного пула InnoDB

Вы можете сконфигурировать размер буферного пула офлайн (при запуске) или онлайн в то время, как сервер работает. Поведение, описанное в этом разделе, относится к обоим методам.

Увеличивая или уменьшая innodb_buffer_pool_size работа выполняется кусками. Размер куска определен параметром конфигурации innodb_buffer_pool_chunk_size, у которого есть значение по умолчанию 128M.

Размер пула должен всегда быть равным или кратным числу innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances. Если Вы конфигурируете innodb_buffer_pool_size к значению, которое не равно или кратно числу innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances, размер пула автоматически скорректирован к значению, которое равно или кратно этому числу, но не меньше чем указанный буферный размер пула.

В следующем примере innodb_buffer_pool_size установлен в 8G, и innodb_buffer_pool_instances установлен в 16. innodb_buffer_pool_chunk_size 128M, что является значением по умолчанию.

8G допустимое значение innodb_buffer_pool_size, потому что 8G кратно innodb_buffer_pool_instances=16 * innodb_buffer_pool_chunk_size=128M, которое 2G.

shell> mysqld --innodb_buffer_pool_size=8G
                 --innodb_buffer_pool_instances=16
mysql> SELECT @@innodb_buffer_pool_size/1024/1024/1024;
+------------------------------------------+
| @@innodb_buffer_pool_size/1024/1024/1024 |
+------------------------------------------+
|   8.000000000000                         |
+------------------------------------------+

В этом примере innodb_buffer_pool_size установлен в 9G и innodb_buffer_pool_instances установлен в 16. innodb_buffer_pool_chunk_size 128M, что является значением по умолчанию. В этом случае 9G не кратно innodb_buffer_pool_instances=16 * innodb_buffer_pool_chunk_size=128M, так что innodb_buffer_pool_size скорректирован к 10G, что является следующим числом, кратным innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances, но не меньше чем указанный размер пула.

shell> mysqld --innodb_buffer_pool_size=9G
                 --innodb_buffer_pool_instances=16
mysql> SELECT @@innodb_buffer_pool_size/1024/1024/1024;
+------------------------------------------+
| @@innodb_buffer_pool_size/1024/1024/1024 |
+------------------------------------------+
|  10.000000000000                         |
+------------------------------------------+
Конфигурирование размера куска буфера InnoDB

innodb_buffer_pool_chunk_size может быть увеличен или уменьшен с шагом в 1MB (1048576 байт), но может быть изменен только при запуске в командной строки или в конфигурационном файле MySQL.

Командная строка:

shell> mysqld --innodb_buffer_pool_chunk_size=134217728

Конфигурационный файл:

[mysqld]
innodb_buffer_pool_chunk_size=134217728

Следующие условия применяются, изменяя innodb_buffer_pool_chunk_size:

  • Если новое значение If the new innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances больше, чем текущий буферный размер пула, когда буферный пул инициализирован, innodb_buffer_pool_chunk_size является усеченным к innodb_buffer_pool_size / innodb_buffer_pool_instances.

    Например, если буферный пул инициализирован с размером 2GB (2147483648 байт), 4 экземплярами пула и размером куска 1GB (1073741824 байт), размер куска является усеченным к значению, равному innodb_buffer_pool_size / innodb_buffer_pool_instances, как показано ниже:

    shell> mysqld --innodb_buffer_pool_size=2147483648
                     --innodb_buffer_pool_instances=4
                     --innodb_buffer_pool_chunk_size=1073741824;
    
    mysql> SELECT @@innodb_buffer_pool_size;
    +---------------------------+
    | @@innodb_buffer_pool_size |
    +---------------------------+
    |  2147483648               |
    +---------------------------+
    
    mysql> SELECT @@innodb_buffer_pool_instances;
    +--------------------------------+
    | @@innodb_buffer_pool_instances |
    +--------------------------------+
    | 4                              |
    +--------------------------------+
    
    # Chunk size was set to 1GB (1073741824 bytes) on startup but was
    # truncated to innodb_buffer_pool_size / innodb_buffer_pool_instances
    
    mysql> SELECT @@innodb_buffer_pool_chunk_size;
    +---------------------------------+
    | @@innodb_buffer_pool_chunk_size |
    +---------------------------------+
    |   536870912                     |
    +---------------------------------+
    
  • Буферный размер пула должен всегда быть равным или кратным innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances. Если Вы изменяете innodb_buffer_pool_chunk_size, innodb_buffer_pool_size автоматически скорректирован к значению, которое равно или кратно innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances не меньше, чем текущий буферный размер пула. Корректировка происходит, когда буферный пул инициализирован. Это поведение продемонстрировано в следующем примере:
    # The buffer pool has a default size of 128MB (134217728 bytes)
    
    mysql> SELECT @@innodb_buffer_pool_size;
    +---------------------------+
    | @@innodb_buffer_pool_size |
    +---------------------------+
    |   134217728               |
    +---------------------------+
    
    # The chunk size is also 128MB (134217728 bytes)
    
    mysql> SELECT @@innodb_buffer_pool_chunk_size;
    +---------------------------------+
    | @@innodb_buffer_pool_chunk_size |
    +---------------------------------+
    |   134217728                     |
    +---------------------------------+
    
    # There is a single buffer pool instance
    
    mysql> SELECT @@innodb_buffer_pool_instances;
    +--------------------------------+
    | @@innodb_buffer_pool_instances |
    +--------------------------------+
    | 1                              |
    +--------------------------------+
    
    # Chunk size is decreased by 1MB (1048576 bytes) at startup
    # (134217728 - 1048576 = 133169152):
    
    shell> mysqld --innodb_buffer_pool_chunk_size=133169152
    mysql> SELECT @@innodb_buffer_pool_chunk_size;
    +---------------------------------+
    | @@innodb_buffer_pool_chunk_size |
    +---------------------------------+
    |   133169152                     |
    +---------------------------------+
    
    # Buffer pool size increases from 134217728 to 266338304
    # Buffer pool size is automatically adjusted to a value that is equal to
    # or a multiple of innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances
    # that is not less than current buffer pool size
    
    mysql> SELECT @@innodb_buffer_pool_size;
    +---------------------------+
    | @@innodb_buffer_pool_size |
    +---------------------------+
    |   266338304               |
    +---------------------------+
    

    Этот пример демонстрирует то же самое поведение, но с несколькими экземплярами буферного пула:

    # The buffer pool has a default size of 2GB (2147483648 bytes)
    
    mysql> SELECT @@innodb_buffer_pool_size;
    +---------------------------+
    | @@innodb_buffer_pool_size |
    +---------------------------+
    |  2147483648               |
    +---------------------------+
    
    # The chunk size is .5 GB (536870912 bytes)
    
    mysql> SELECT @@innodb_buffer_pool_chunk_size;
    +---------------------------------+
    | @@innodb_buffer_pool_chunk_size |
    +---------------------------------+
    |   536870912                     |
    +---------------------------------+
    
    # There are 4 buffer pool instances
    
    mysql> SELECT @@innodb_buffer_pool_instances;
    +--------------------------------+
    | @@innodb_buffer_pool_instances |
    +--------------------------------+
    | 4                              |
    +--------------------------------+
    
    # Chunk size is decreased by 1MB (1048576 bytes) at startup
    # (536870912 - 1048576 = 535822336):
    
    shell> mysqld --innodb_buffer_pool_chunk_size=535822336
    mysql> SELECT @@innodb_buffer_pool_chunk_size;
    +---------------------------------+
    | @@innodb_buffer_pool_chunk_size |
    +---------------------------------+
    |   535822336                     |
    +---------------------------------+
    
    # Buffer pool size increases from 2147483648 to 4286578688
    # Buffer pool size is automatically adjusted to a value that is equal to
    # or a multiple of innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances
    # that is not less than current buffer pool size of 2147483648
    
    mysql> SELECT @@innodb_buffer_pool_size;
    +---------------------------+
    | @@innodb_buffer_pool_size |
    +---------------------------+
    |  4286578688               |
    +---------------------------+
    

    Забота должна быть проявлена, изменяя innodb_buffer_pool_chunk_size, поскольку это значение может увеличить размер буферного пула, как показано в примерах выше. Прежде чем Вы измените innodb_buffer_pool_chunk_size, вычислите эффект, который это будет иметь на innodb_buffer_pool_size, чтобы гарантировать, что получающийся размер пула является приемлемым.

Чтобы избежать потенциальных исполнительных проблем, число кусков ( innodb_buffer_pool_size / innodb_buffer_pool_chunk_size) не должно превышать 1000.

Конфигурирование буфера InnoDB Online

Опция innodb_buffer_pool_size может быть установлена динамически, используя командой SET, разрешая Вам изменить размеры буферного пула, не перезапуская сервер. Например:

mysql> SET GLOBAL innodb_buffer_pool_size=402653184;

Активные транзакции и операции через InnoDB API должны быть завершены прежде, чем изменить размеры буферного пула. Начиная изменение размера, работа не запускается, пока все активные транзакции не завершены. Как только работа по изменению размеров началась, новые транзакции и операции, которые требуют доступа к буферному пулу, ждут, пока работа не закончится. Исключение: параллельный доступ к буферному пулу разрешен в то время, когда буферный пул дефрагментируется. Недостаток разрешения параллельного доступа состоит в том, что это может привести к временной нехватке доступных страниц, в то время как страницы удаляются.

Вложенные транзакции могут отвалиться, если начаты после того, как началась работа по изменению размера буфера.

Контроль изменения размера пула

Innodb_buffer_pool_resize_status сообщает о ходе изменения размеров буферного пула:

mysql> SHOW STATUS WHERE Variable_name='InnoDB_buffer_pool_resize_status';
+----------------------------------+----------------------------------+
| Variable_name                    | Value                            |
+----------------------------------+----------------------------------+
| Innodb_buffer_pool_resize_status | Resizing also other hash tables. |
+----------------------------------+----------------------------------+

Это также зарегистрировано в файле журнала ошибок сервера. Этот пример показывает записи, которые зарегистрированы, увеличивая размер буферного пула:

[Note] InnoDB: Resizing buffer pool from 134217728 to 4294967296. (unit=134217728)
[Note] InnoDB: disabled adaptive hash index.
[Note] InnoDB: buffer pool 0 : 31 chunks (253952 blocks) was added.
[Note] InnoDB: buffer pool 0 : hash tables were resized.
[Note] InnoDB: Resized hash tables at lock_sys, dictionary.
[Note] InnoDB: completed to resize buffer pool from 134217728 to 4294967296.
[Note] InnoDB: re-enabled adaptive hash index.

Этот пример показывает записи, которые зарегистрированы, уменьшая размер буферного пула:

[Note] InnoDB: Resizing buffer pool from 4294967296 to 134217728. (unit=134217728)
[Note] InnoDB: disabled adaptive hash index.
[Note] InnoDB: buffer pool 0 : start to withdraw the last 253952 blocks.
[Note] InnoDB: buffer pool 0 : withdrew 253952 blocks from free list. tried to relocate 0 pages.
(253952/253952)
[Note] InnoDB: buffer pool 0 : withdrawn target 253952 blocks.
[Note] InnoDB: buffer pool 0 : 31 chunks (253952 blocks) was freed.
[Note] InnoDB: buffer pool 0 : hash tables were resized.
[Note] InnoDB: Resized hash tables at lock_sys, dictionary.
[Note] InnoDB: completed to resize buffer pool from 4294967296 to 134217728.
[Note] InnoDB: re-enabled adaptive hash index.
Как происходит изменение

Работа изменения размеров выполнена фоновым потоком. Увеличивая размер буферного пула:

  • Добавляются страницы в кусок (размер куска определен innodb_buffer_pool_chunk_size).

  • Хэш-таблицы, списки и указатели преобразованы, чтобы использовать новые адреса в памяти.
  • Добавляются новые страницы к свободному списку.

В то время как эти операции происходят, другие потоки заблокированы на доступ к буферному пулу.

Уменьшение размера буферного пула:

  • Дефрагментация пула и освобождение страниц.

  • Удаление страниц в куске (размер куска определен innodb_buffer_pool_chunk_size).
  • Хэш-таблицы, списки и указатели преобразованы, чтобы использовать новые адреса в памяти.

Из этих операций только дефрагментация и удаление страниц позволяют другим потокам доступ к буферному пулу одновременно.

16.6.3.3. Конфигурирование многих буферных экземпляров

Для систем с буферными пулами в диапазоне нескольких гигабайт деление буферного пула на отдельные экземпляры может улучшить параллелизм, уменьшая столкновения потоков при доступе к кэшируемым страницам. Эта особенность как правило предназначается для систем с многогигабайтным буфером. Многократные буферные экземпляры сконфигурированы, используя опцию innodb_buffer_pool_instances, и Вы могли бы также корректировать innodb_buffer_pool_size.

Когда буферный пул является большим, много запросов данных могут быть удовлетворены, получая из памяти. Вы могли бы столкнуться с узкими местами от многократных потоков, пытающихся получить доступ к буферному пулу сразу. Вы можете позволить многим буферным пулам минимизировать это. Каждая страница, которая сохранена в (или считана из) буферного пула, назначена на один из буферных пулов беспорядочно, используя хеширующую функцию. Каждый буферный пул управляет своими собственными свободными списками, списками потока, LRU и всеми другими структурами данных, соединенными с буферным пулом. До MySQL 8.0 каждый буферный пул был защищен его собственным mutex. В MySQL 8.0 и позже mutex был заменен несколькими списками и хешем, чтобы уменьшить накладные расходы.

Чтобы включить многократные буферы, установите опцию innodb_buffer_pool_instances к значению больше 1 (значение по умолчанию), но до 64 (максимум). Эта опция вступает в силу только, когда Вы устанавливаете innodb_buffer_pool_size к размеру 1GB или больше. Полный размер, который Вы определяете, разделен среди всех буферных пулов. Для лучшей эффективности, определите комбинацию innodb_buffer_pool_instances и innodb_buffer_pool_size так, чтобы каждый экземпляр буфера был по крайней мере в 1GB.

Для информации об изменении размера буфера InnoDB см. раздел 16.6.3.2.

16.6.3.4. Создание стойкого к сканированию буферного пула

Вместо того, чтобы использовать строгий алгоритм LRU InnoDB использует метод, чтобы минимизировать объем данных, который принесен в буферный пул, но не используется никогда больше. Цель состоит в том, чтобы удостовериться, что часто используемые (горячие) страницы остаются в буферном пуле, как раз когда предвыборка и полное сканирование таблицы вводят новые блоки, которые не факт, что будут использованы позже.

Недавно считанные блоки вставлены в середину списка LRU. Все недавно прочитанные страницы вставлены в место, которое по умолчанию занимает место в 3/8 от хвоста списка LRU. Страницы перемещены в начало списка, когда к ним получают доступ в буферном пуле впервые. Таким образом, страницы, к которым никогда не получают доступ, никогда не добираются до передней части списка LRU и вычеркиваются скорее, чем со строгим подходом LRU. Это расположение делит список LRU на два сегмента, где страницы сдвигаются вниз от точки вставки.

Для объяснения внутренних работ буферного пула InnoDB и специфических особенностей алгоритма LRU см. раздел 16.6.3.1.

Вы можете управлять точкой вставки в списке LRU и выбрать применяет ли InnoDB ту же самую оптимизацию к блокам, принесенным в буферный пул просмотром таблицы или индекса. Параметр конфигурации innodb_old_blocks_pct управляет процентом старых блоков в списке LRU. Значение по умолчанию innodb_old_blocks_pct 37 соответствует оригинальному отношению 3/8. Диапазон значения от 5 (новые страницы в буфере стареют очень быстро) до 95 (только 5% буферного пула сохранены для горячих страниц, делая алгоритм близким к знакомой стратегии LRU).

Оптимизация, которая препятствует буферному пулу взбалтываться предвыборкой, может избежать подобных проблем из-за просмотров таблицы или индекса. В этих просмотрах к странице данных как правило получают доступ несколько раз в быстрой последовательности и никогда не затрагивают ее снова. Параметр конфигурации innodb_old_blocks_time определяет окно времени (в миллисекундах) после первого доступа к странице, во время которого к ней можно получить доступ, не перемещая ее в начало списка LRU. Значение по умолчанию innodb_old_blocks_time 1000. Увеличение этого значения делает все больше блоков стареющими быстро.

innodb_old_blocks_pct и innodb_old_blocks_time являются динамическими, глобальными и может быть определены в файле опции MySQL (my.cnf или my.ini) или изменены во время выполнения через SET GLOBAL. Изменение настроек требует привилегии SUPER.

Помочь Вам измерить эффект этих параметров может отчет команды SHOW ENGINE INNODB STATUS о буферной статистике пула. Для деталей см. раздел 16.6.3.9.

Поскольку эффекты этих параметров могут значительно различаться в зависимости от Вашей конфигурации аппаратных средств, Ваших данных и деталей Вашей рабочей нагрузки, всегда определяйте эффективность, чтобы проверить что получилось прежде, чем изменить эти настройки в любой критической по отношению к работе или производственной среде.

В смешанных рабочих нагрузках, где большая часть деятельности OLTP с с периодическими запросами сообщения пакета, которые приводят к большим просмотрам, установка значения innodb_old_blocks_time во время пакетных выполнений может помочь сохранить рабочий набор нормальной рабочей нагрузки в буферном пуле.

Просматривая большие таблицы, которые не могут поместиться полностью в буферном пуле, установите innodb_old_blocks_pct к маленькому значению, чтобы не дать данным, которые только считаны однажды, заполнить весь буфер. Например, установка innodb_old_blocks_pct=5 ограничивает эти данные 5% размера буферного пула.

Когда просматриваете маленькие таблицы, которые действительно вписываются в память, уменьшите накладные расходы на перемещение страниц в буфере, установив innodb_old_blocks_pct в его значение по умолчанию или еще выше, например, innodb_old_blocks_pct=50.

Эффект изменения innodb_old_blocks_time предсказать трудней, чем innodb_old_blocks_pct, так как он изменяется больше с рабочей нагрузкой. Чтобы достигнуть оптимального значения, проведите свои собственные точки отсчета, если изменение производительности от корректировки innodb_old_blocks_pct недостаточно.

16.6.3.5. Конфигурирование предвыборки InnoDB

Предвыборка это запрос ввода/вывода предварительно принести страницы в буферный пул асинхронно, в ожидании, что эти страницы скоро будут необходимы. Запросы получают все страницы в одном экстенте . InnoDB использует два алгоритма предвыборки, чтобы улучшить работу ввода/вывода:

Линейная предвыборка метод, который предсказывает, какие страницы могли бы скоро быть необходимы, основываясь на страницах в буферном пуле. Вы управляете, когда InnoDB выполняет работу предвыборки, корректируя число последовательных доступов к странице, требуемых, чтобы вызвать асинхронный запрос чтения, используя параметр конфигурации innodb_read_ahead_threshold.

Параметр конфигурации innodb_read_ahead_threshold контролирует, насколько чувствителен InnoDB в обнаружении образцов последовательного доступа страницы. Если число чтения страниц последовательно из экстента больше чем или равно innodb_read_ahead_threshold, InnoDB начинает асинхронную работу чтения следующего экстента целиком. innodb_read_ahead_threshold может быть установлен в любое значение от 0 до 64. По умолчанию 56. Чем выше значение, тем более строгая проверка образца доступа. Например, если Вы устанавливаете значение в 48, InnoDB вызывает линейный запрос предвыборки только когда к 48 страницам в текущем экстенте получили доступ последовательно. Если значение 8, InnoDB вызывает линейный запрос предвыборки даже если только к 8 страницам в экстенте получают доступ последовательно. Вы можете установить значение этого параметра в файле конфигурации MySQL или изменить это динамически с помощью SET GLOBAL, но для этого надо иметь привилегиюSUPER.

Случайная это метод, который предсказывает, когда страницы могли бы скоро быть необходимы, основываясь на страницах, которые уже в буферном пуле, независимо от порядка, в котором были считаны те страницы. Если 13 последовательных страниц из того же самого экстента найдены в буферном пуле, InnoDB делает запрос предварительно загрузить остающиеся страницы экстента. Чтобы активировать эту опцию, установите переменную конфигурации innodb_random_read_ahead в ON.

Команда SHOW ENGINE INNODB STATUS показывает статистику, чтобы помочь Вам оценить эффективность алгоритма чтения. Статистические данные включают счетчики для следующих глобальных переменных состояния:

Эта информация может быть полезной, точно настраивая innodb_random_read_ahead.

Для получения дополнительной информации о работе ввода/вывода см. разделы 9.5.8 и 9.12.1.

16.6.3.6. Конфигурирование сброса буфера InnoDB

InnoDB выполняет определенные задачи в фоне, включая сброс of грязных страниц (те страницы, которые были изменены, но еще не записаны в файлы базы данных) из буферного пула.

InnoDB начинает сбрасывать страницы пула, когда процент грязных страниц в буферном пуле достигает нижнего предела, определенного innodb_max_dirty_pages_pct_lwm. Эта опция предназначена, чтобы управлять отношением грязных страниц в буферном пуле и идеально препятствовать тому, чтобы процент грязных страниц достиг innodb_max_dirty_pages_pct. Если процент грязных страниц в буферном пуле превышает innodb_max_dirty_pages_pct, InnoDB начинает сброс буферных страниц немедленно.

InnoDB использует алгоритм, чтобы оценить необходимый уровень сброса, основанный на скорости генерации журнала redo и действующего коэффициента сброса. Намерение состоит в том, чтобы пригладить эффективность работы, гарантируя, что буферная деятельность потока не отстает от потребности сохранить буферный пул чистым. Автоматическая корректировка уровня сброса может помочь избежать внезапных падений пропускной способности, когда сброс буферного пула начинает мешать обычному вводу-выводу.

InnoDB использует файлы системного журнала круговым способом. Прежде, чем снова использовать часть файла системного журнала, InnoDB сбрасывает на диск все грязные буферные страницы, чьи записи содержатся в этой части файла системного журнала, это процесс острой контрольной точки. Если рабочая нагрузка записи интенсивная, она производит много информации в журнале redo. Если все свободное место в файлах системного журнала израсходовано, острая контрольная точка происходит, вызывая временное сокращение пропускной способности. Эта ситуация может произойти, даже если innodb_max_dirty_pages_pct не достигнут.

InnoDB использует эвристический алгоритм, чтобы избежать такого сценария, измеряя число грязных страниц в буферном пуле и уровень прироста журнала redo. Основываясь на этих числах, InnoDB решает, сколько грязных страниц сбросить из буферного пула каждую секунду. Этот адаптивный алгоритм в состоянии иметь дело с внезапными изменениями в рабочей нагрузке.

Внутренний сопоставительный анализ показал, что этот алгоритм не только поддерживает пропускную способность в течение долгого времени, но и может также значительно улучшить полную пропускную способность.

Поскольку адаптивный сброс может значительно затронуть образец ввода/вывода рабочей нагрузки, параметр innodb_adaptive_flushing позволяет Вам выключать эту особенность. Значение по умолчанию для innodb_adaptive_flushing TRUE, адаптивный алгоритм включен. Вы можете установить значение этого параметра в файле опции MySQL (my.cnf или my.ini) или изменить это динамически с помощью SET GLOBAL, имея привилегию SUPER.

Для информации о точной настройке сброса пула в InnoDB см. раздел 16.6.3.7. Для получения дополнительной информации о работе ввода/вывода InnoDB см. раздел 9.5.8.

16.6.3.7. Точная настройка сброса буферного пула InnoDB

Опции innodb_flush_neighbors и innodb_lru_scan_depth позволяют Вам точно настраивать определенные аспекты процесса сброса для буферного пула InnoDB. Эти опции прежде всего помогают рабочим нагрузкам с интенсивной записью. С большой активностью DML сброс может отстать, если это недостаточно агрессивно, приводя к чрезмерному использованию памяти в буферном пуле. С другой стороны сброс может перегрузить Вашу систему ввода/вывода, если этот механизм слишком агрессивен. Идеальные настройки зависят от Вашей рабочей нагрузки, образцов доступа к данным и конфигурации хранения (например, хранятся ли данные на HDD или SSD).

Для систем с постоянными тяжелыми рабочими нагрузками или рабочими нагрузками, которые широко колеблются, несколько параметров конфигурации позволяют Вам точно настраивать поведение сброса для таблиц:

Эти опции подпитывают формулу, используемую параметром innodb_adaptive_flushing.

Опции innodb_adaptive_flushing, innodb_io_capacity и innodb_max_dirty_pages_pct ограничены или расширены следующими опциями:

Механизм адаптивного сброса InnoDB не является подходящим во всех случаях. Это приносит большинство пользы, когда журнал redo рискует заполниться. Опция innodb_adaptive_flushing_lwm определяет процент нижнего предела заполнения журнала redo, когда этот порог пересечен, InnoDB включает адаптивный сброс даже если не определена опция innodb_adaptive_flushing.

Если активность сброса слишком мала, InnoDB может сбрасывать более настойчиво, чем указано в innodb_io_capacity . innodb_io_capacity_max представляет верхний предел нагрузки ввода/вывода, используемой в таких чрезвычайных ситуациях, чтобы пик ввода/вывода не потреблял всю пропускную способность сервера.

InnoDB старается сбросить данные из буферного пула так, чтобы процент грязных страниц не превысил значение innodb_max_dirty_pages_pct. Значение по умолчанию для innodb_max_dirty_pages_pct 75.

innodb_max_dirty_pages_pct устанавливает цель для активности сброса. Это не затрагивает уровень сброса. Для информации об управлении уровнем сброса см. раздел 16.6.3.6.

Опция innodb_max_dirty_pages_pct_lwm определяет значение, которое представляет процент грязных страниц, при котором предварительному сбросу позволяют управлять отношением грязных страниц и идеально препятствовать тому, чтобы процент грязных страниц достиг innodb_max_dirty_pages_pct. Значение innodb_max_dirty_pages_pct_lwm=0 отключает предсброс.

Большинство опций, на которые ссылаются выше, наиболее применимы к серверам, которые работают с большими рабочими нагрузками по записи в течение долгих промежутков времени.

innodb_flushing_avg_loops определяет число итераций для которого InnoDB сохраняет ранее расчитанный снимок состояния сброса, который управляет, как быстро адаптивный сброс отвечает на изменения загрузки. Указание большого значения для innodb_flushing_avg_loops предписывает хранить расчитанный снимок дольше, таким образом, адаптивный сброс отвечает более медленно. Высокое значение также уменьшает позитивные отклики между передним планом и фоновой работой, но задание большого значения очень важно, чтобы гарантировать, что использование InnoDB журнала redo не достигает 75% (предел, при котором запускается сброс), и что innodb_max_dirty_pages_pct сохраняет число грязных страниц на уровне, который является подходящим для рабочей нагрузки.

Системы с последовательными рабочими нагрузками, большим innodb_log_file_size и маленькими пиками, которые не достигают 75% использования места в журнале redo, должны использовать верхний уровень innodb_flushing_avg_loops, чтобы продолжить сбрасывать столь гладко, насколько возможно. Для систем с экстремальными пиками загрузки или файлами системного журнала, которые не обеспечивают много пространства, должны использовать меньшее значение innodb_flushing_avg_loops. Меньшее значение позволяет сбрасывать так, чтобы точно отследить загрузку и помогает избежать использования 75% пространства журнала redo.

16.6.3.8. Сохранение и восстановление состоояния буферного пула

Чтобы уменьшить период загрузки после перезапуска сервера, InnoDB сохраняет процент последний раз используемых страниц для каждого буферного пула при завершении работы сервера и восстанавливает эти страницы при запуске сервера. Процент недавно используемых страниц, который сохранен, определен параметром innodb_buffer_pool_dump_at_shutdown.

После перезапуска занятого сервера как правило есть период разминки с устойчиво увеличивающейся пропускной способностью, поскольку дисковые страницы, которые были в буферном пуле, возвращены в память (поскольку те же самые данные запрошены, обновлены и так далее). Способность восстановить буферный пул при запуске сокращает период разминки, перезагружая дисковые страницы, которые были в буферном пуле перед перезапуском вместо того, чтобы ждать операций DML, чтобы получить доступ к соответствующим строкам. Кроме того, запросы ввода/вывода могут быть выполнены в больших пакетах, делая полный ввод/вывод быстрее. Загрузка страниц происходит в фоне и не задерживает запуск базы данных.

В дополнение к сохранению состояния буферного пула при завершении работы и восстановлении его при запуске, Вы можете сохранить и восстановить состояние буферного пула в любое время, в то время как сервер работает. Например, Вы можете сохранить состояние после достижения устойчивой пропускной способности при устойчивой рабочей нагрузке. Вы можете также восстановить предыдущее состояние буферного пула после выполнения отчетов или заданий обслуживания, которые приносят страницы данных в буферный пул, которые нужны только для тех операций, или после выполнения некоторой другой нетипичной рабочей нагрузки.

Даже при том, что буферный пул может быть много гигабайт в размере, данные пула, которые InnoDB сохраняет на диск являются крошечными. Только ID табличного пространства и ID страницы, необходимые, чтобы определить местонахождение соответствующих страниц, сохранены на диск. Эта информация получена из таблицы INNODB_BUFFER_PAGE_LRU INFORMATION_SCHEMA. По умолчанию ID табличного пространства и страницы сохранены в файле ib_buffer_pool, в кталоге данных InnoDB. Имя файла и местоположение могут быть изменены, используя параметр innodb_buffer_pool_filename.

Поскольку данные кэшируются и устаревают в пуле, нет никакой проблемы, если дисковые страницы были недавно обновлены, или если работа DML вовлекает данные, которые еще не были загружены. Механизм загрузки пропускает требуемые страницы, которые больше не существуют.

Основной механизм вовлекает фоновый поток, чтобы выполнить операции загрузки и дамп.

Дисковые страницы от сжатых таблиц загружены в буферный пул в их сжатой форме. Страницы разсжаты, когда к содержанию страницы получают доступ во время операций DML. Поскольку разсжатие страниц является процессом, серьезно нагружающим центральный процессор, более эффективно для параллелизма выполнить работу в потоке соединения, а не в единственном потоке, который выполняет работу восстановления пула.

Конфигурирование процента дампа для страниц буферного пула

Прежде, чем вывести страницы из буферного пула, Вы можете сконфигурировать процент используемых буферных страниц, которые Вы хотите вывести, устанавливая опцию innodb_buffer_pool_dump_pct. Если Вы планируете вывести буферные страницы в то время, как сервер работает, Вы можете сконфигурировать опцию динамически:

SET GLOBAL innodb_buffer_pool_dump_pct=40;

Если Вы планируете вывести буферные страницы при завершении работы сервера, надо установить innodb_buffer_pool_dump_pct в Вашем конфигурационном файле.

[mysqld]
innodb_buffer_pool_dump_pct=40

Значение innodb_buffer_pool_dump_pct по умолчанию 25 (дамп 25% используемых последний раз страниц).

Сохранение статуса буферного пула при завершении работы и восстановление при запуске

Чтобы сохранить статус буферного пула при завершении работы сервера, сделайте следующее запрос до закрытия сервера:

SET GLOBAL innodb_buffer_pool_dump_at_shutdown=ON;

innodb_buffer_pool_dump_at_shutdown включена по умолчанию.

Чтобы восстановить статус пула при запуске сервера, определите опцию --innodb_buffer_pool_load_at_startup, запуская сервер:

mysqld --innodb_buffer_pool_load_at_startup=ON;

innodb_buffer_pool_load_at_startup включен по умолчанию.

Сохранение и восстановление статуса буферного пула онлайн

Чтобы сохранить состояние буферного пула в то время, как сервер MySQL работает, сделайте следующее:

SET GLOBAL innodb_buffer_pool_dump_now=ON;

Чтобы восстановить состояние буферного пула в то время, как сервер MySQL работает, сделайте следующее:

SET GLOBAL innodb_buffer_pool_load_now=ON;
Отображение процесса дампа буферного пула

Чтобы вывести на экран процесс сохранения пула на диск, сделайте следующее:

SHOW STATUS LIKE 'Innodb_buffer_pool_dump_status';

Если работа еще не запустилась, вернется not started . Если работа завершена, время завершения напечатано (например, Finished at 110505 12:18:02). Если работа происходит, информация о статусе обеспечена (например, Dumping buffer pool 5/7, page 237/2873).

Отображение процесса загрузки буферного пула

Чтобы вывести на экран процесс загрузки пула, сделайте следующее:

SHOW STATUS LIKE 'Innodb_buffer_pool_load_status';

Если работа еще не запустилась, вернется not started . Если работа завершена, время завершения напечатано (например, Finished at 110505 12:18:02). Если работа происходит, информация о статусе обеспечена (например, Loaded 123/22300 pages).

Прерывание загрузки пула

Чтобы прервать работу загрузки пула, сделайте следующее:

SET GLOBAL innodb_buffer_pool_load_abort=ON;
Контроль загрузки пула, используя Performance Schema

Вы можете контролировать ход загрузки пула, используя Performance Schema.

Следующий пример демонстрирует, как включить инструмент этапа событий stage/innodb/buffer pool load и связанные потребительские таблицы, чтобы контролировать продвижение загрузки.

Для информации о дампе пула и процедурах загрузки, используемых в этом примере, см. раздел 16.6.3.8 . Для информации об инструментах этапа Performance Schema и связанных потребителях, см. раздел 23.9.5.

  1. Включите инструмент stage/innodb/buffer pool load :

    mysql> UPDATE performance_schema.setup_instruments SET ENABLED = 'YES'
                     WHERE NAME LIKE 'stage/innodb/buffer%';
    
  2. Включите потребительские таблицы этапа событий, которые включают events_stages_current , events_stages_history и events_stages_history_long.
    mysql> UPDATE performance_schema.setup_consumers SET ENABLED = 'YES'
                     WHERE NAME LIKE '%stages%';
    
  3. Выведите текущее буферное состояние с помощью innodb_buffer_pool_dump_now.
    mysql> SET GLOBAL innodb_buffer_pool_dump_now=ON;
    
  4. Проверьте состояние дампа пула, чтобы гарантировать, что работа завершилась.
    mysql> SHOW STATUS LIKE 'Innodb_buffer_pool_dump_status'\G
    *************************** 1. row ***************************
    Variable_name: Innodb_buffer_pool_dump_status
    Value: Buffer pool(s) dump completed at 150202 16:38:58
    
  5. Загрузите буферный пул с помощью innodb_buffer_pool_load_now:
    mysql> SET GLOBAL innodb_buffer_pool_load_now=ON;
    
  6. Проверьте текущий статус загрузки пула, запрашивая таблицу Performance Schema events_stages_current. Столбец WORK_COMPLETED показывает число загруженных страниц пула. WORK_ESTIMATED обеспечивает оценку остающейся работы в страницах.
    mysql> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED
                     FROM performance_schema.events_stages_current;
    +-------------------------------+----------------+----------------+
    | EVENT_NAME                    | WORK_COMPLETED | WORK_ESTIMATED |
    +-------------------------------+----------------+----------------+
    | stage/innodb/buffer pool load | 5353           | 7167           |
    +-------------------------------+----------------+----------------+
    

    Таблица events_stages_current возвращает пустой набор, если работа загрузки пула завершилась. В этом случае Вы можете проверить таблицу events_stages_history , чтобы рассмотреть данные для завершенного случая. Например:

    mysql> SELECT EVENT_NAME, WORK_COMPLETED, WORK_ESTIMATED
                     FROM performance_schema.events_stages_history;
    +-------------------------------+----------------+----------------+
    | EVENT_NAME                    | WORK_COMPLETED | WORK_ESTIMATED |
    +-------------------------------+----------------+----------------+
    | stage/innodb/buffer pool load | 7167           | 7167           |
    +-------------------------------+----------------+----------------+
    

Вы можете также контролировать ход загрузки пула, используя Performance Schema, загружая буферный пул при запуске с использованием innodb_buffer_pool_load_at_startup. В этом случае инструмент stage/innodb/buffer pool load и связанные потребители должны быть включены при запуске. Для получения дополнительной информации см. раздел 23.2.2 .

16.6.3.9. Контроль буферного пула, используя стандартный монитор InnoDB

Вывод InnoDB Standard Monitor, к которому можно получить доступ, используя SHOW ENGINE INNODB STATUS , обеспечивает метрики, которые принадлежат работе с пулом InnoDB. Буферные метрики пула расположены в разделе BUFFER POOL AND MEMORY вывода InnoDB Standard Monitor и подобны следующему:

----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 2198863872
Dictionary memory allocated 776332
Buffer pool size   131072
Free buffers   124908
Database pages 5720
Old database pages 2071
Modified db pages  910
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 4, not young 0
0.10 youngs/s, 0.00 non-youngs/s
Pages read 197, created 5523, written 5060
0.00 reads/s, 190.89 creates/s, 244.94 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not
0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read
ahead 0.00/s
LRU len: 5720, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]

Следующая таблица описывает метрики пула, о которых сообщает InnoDB Standard Monitor.

Средние числа в секунду в выводе InnoDB Standard Monitor основаны на прошедшем времени с последнего вывода InnoDB Standard Monitor.

Таблица 16.2. Метрики пула

ИмяОписание
Total memory allocatedПолная память, которая выделена для буферного пула в байтах.
Dictionary memory allocatedПолная память, выделенная для словаря данных InnoDB в байтах.
Buffer pool sizeПолный размер в страницах буферного пула.
Free buffersПолный размер в страницах свободного списка.
Database pagesПолный размер в страницах списка LRU.
Old database pagesПолный размер в страницах старого подсписка LRU.
Modified db pagesТекущее число страниц, измененных в буферном пуле.
Pending readsЧисло страниц, ждущих считывания в пул.
Pending writes LRUЧисло старых грязных страниц в буферном пуле, которые будут записаны от конца списка LRU.
Pending writes flush listЧисло страниц пула, которые будут сброшены во время установки контрольных точек.
Pending writes single pageЧисло независимых страниц в ожидании записи в буферном пуле.
Pages made youngОбщее количество молодых страниц в списке LRU (перемещенных к началу подсписка новых страниц).
Pages made not youngОбщее количество страниц, не сделанных молодыми в списке LRU (страницы, которые остались в подсписке старых, не будучи сделанным молодыми).
youngs/sСреднее число доступов в секунду к старым страницам в списке LRU, которые привели к созданию молодых страниц. См. примечания, которые следуют за этой таблицей для получения дополнительной информации.
non-youngs/sСреднее число доступов в секунду к старым страницам в списке LRU, которые не привели к созданию молодых страниц.
Pages readОбщее количество страниц, прочитанных из буферного пула.
Pages createdОбщее количество страниц, созданных в буферном пуле.
Pages writtenОбщее количество страниц, записанных из буферного пула.
reads/sСреднее число в секунду прочитанных страниц.
creates/sСреднее число в секунду создаваемых буферных страниц.
writes/sСреднее число записываемых буферных страниц в секунду.
Buffer pool hit rateЧастота успешных обращений к странице для страниц из буферной памяти, а не с диска.
young-making rateСредняя частота успешных обращений, в которых доступ к странице привел к созданию молодых страниц.
not (young-making rate)Средняя частота успешных обращений, в которых доступ к странице не привел к созданию молодых страниц.
Pages read ahead Среднее число операций предвыборки в секунду.
Pages evicted without accessСреднее число вычеркнутых страниц в секунду, к которым не получен доступ из буферного пула.
Random read aheadСреднее число операций случайного чтения в секунду.
LRU lenПолный размер в страницах списка LRU.
unzip_LRU lenПолный размер в страницах списка unzip_LRU.
I/O sumОбщее количество страниц списка LRU, к которым был доступ в течение прошлых 50 секунд.
I/O curОбщее количество страниц списка LRU, к которым получают доступ сейчас.
I/O unzip sumОбщее количество страниц списка unzip_LRU, к которым получали доступ.
I/O unzip curОбщее количество страниц списка unzip_LRU, к которым получают доступ сейчас.

Примечания:

  • Метрика youngs/s касается только старых страниц. Это основано на числе доступов к страницам, а не числе страниц. Могут быть многократные доступы к данной странице, которые все посчитаны. Если Вы видите очень низкое значение youngs/s, когда нет никакого большого появления просмотров, Вы, возможно, должны были бы уменьшить время задержки или увеличить процент буферного пула, используемого для старого подсписка. Увеличение процента делает старый подсписок больше, таким образом, у страниц в этом подсписке уходит больше времени, чтобы переместиться в хвост и быть вычеркнутыми. Это увеличивает вероятность, что к страницам получат доступ снова и сделают их молодыми.

  • Метрика non-youngs/s касается только старых страниц. Это основано на числе доступов к страницам, а не числе страниц. Могут быть многократные доступы к данной странице, которые все посчитаны. Если Вы не видите много non-youngs/s, когда Вы делаете большое сканирование таблицы (и много youngs/s), увеличьте значение задержки.
  • Коэффициент young-making учитывает доступы ко всем страницам пула, не только доступы к страницам в старом подсписке. Коэффициенты young-making и not обычно не составляют в сумме полную частоту успешных обращений к пулу.
  • not (young-making rate) средняя частота успешных обращений, в которой доступы к страницам не привели к созданию молодых страниц из-за задержки, определенной innodb_old_blocks_time, или из-за попаданий на страницы в новом подсписке, которые не приводили к страницам, перемещаемым к началу. Этот уровень составляет доступы ко всем страницам пула, не только доступы к страницам в старом подсписке.

Переменные статуса сервера пула InnoDB и таблица INNODB_BUFFER_POOL_STATS обеспечивает многие из тех же самых метрик пула, найденных в таблице INNODB_BUFFER_POOL_STATS, см. пример 16.19.

16.6.4. Конфигурирование изменения буферизации InnoDB

Когда INSERT, UPDATE и DELETE выполнены на таблице, значения индексированных столбцов (особенно значения вторичных ключей) часто находятся в несортированном порядке, требуя существенного ввода/вывода, чтобы принести вторичный индекс. InnoDB имеет буфер изменений, который кэширует изменения вторичного индекса, когда соответствующая страница не находится в буферном пуле, таким образом избегая дорогих операций ввода/вывода, не читая немедленно страницу с диска. Буферизованные изменения слиты, когда страница загружена в буферный пул, и обновленная страница позже сбрасывается на диск. Основной поток InnoDB объединяет изменения, когда сервер почти неактивен, и во время медленной парковки.

Поскольку это может привести к меньшему количеству обращений к диску, эта особенность является самой ценной для рабочих нагрузок, которые имеют большой ввод-вывод, например приложения с большим объемом операций DML, таких как большой объем вставок.

Однако, буфер изменения занимает часть буферного пула, уменьшая память, доступную страницам данных о кэше. Если рабочий набор данных почти помещается в буферный пул, или если Ваши таблицы имеют, относительно немногие вторичные индексы, может быть полезно отключить буферизацию изменения. Если работа помещается в буфере полностью, буферизация изменения не налагает дополнительных издержек, потому что это только относится к страницам, которые не находятся в буферном пуле.

Вы можете управлять степенью, в которой InnoDB выполняет буферизацию изменения, используя параметр innodb_change_buffering. Вы можете включить или отключить буферизацию для вставок и удалений (когда индексные записи первоначально отмечены для удаления) и операций чистки (когда индексные записи физически удалены). Обновления это комбинация вставки и удаления. Значение по умолчанию для innodb_change_buffering all.

Разрешенные значения innodb_change_buffering:

  • all

    Значение по умолчанию: вставки в буфер, операции удаления и чистки.

  • none

    Не буферизировать ничего.

  • inserts

    Буферизировать только вставки.

  • deletes

    Буферизировать только удаления.

  • changes

    Буферизировать только удаления и вставки.

  • purges

    Буферизировать физические операции удаления, которые происходят в фоне.

Вы можете установить innodb_change_buffering в файле опций MySQL (my.cnf или my.ini) или измените это динамически с помощью SET GLOBAL (нужна привилегия SUPER). Изменение установки затрагивает буферизацию новых операций, слияние существующих буферизованных записей не затронуто.

Подробности в разделе 16.4.2 . Для информации о конфигурировании размера буфера изменения см. раздел 16.6.4.1.

16.6.4.1. Конфигурирование максимального размера буфера изменений

Опция innodb_change_buffer_max_size позволяет Вам конфигурировать максимальный размер буфера изменения как процент полного размера буферного пула. По умолчанию innodb_change_buffer_max_size установлена в 25. Максимум 50.

Вы могли бы рассмотреть увеличение innodb_change_buffer_max_size на сервере MySQL с тяжелой вставкой, обновлением и удалением, где буферное слияние изменения не идет в ногу с новыми буферными записями изменения, заставляя буфер изменения достичь его максимального предела размера.

Вы могли бы рассмотреть уменьшение innodb_change_buffer_max_size на сервере MySQL со статическими данными, используемыми для отчетов, или если буфер изменения потребляет слишком много места в памяти, которое совместно использовано с буферным пулом, заставляя страницы стареть скорее, чем надо.

Проверьте различные настройки с представительной рабочей нагрузкой, чтобы определить оптимальную конфигурацию. Настройка innodb_change_buffer_max_size является динамической, что позволяет Вам изменять ее, не перезапуская сервер.

16.6.5. Конфигурирование параллелизма потока для InnoDB

InnoDB использует потоки операционной системы, чтобы обработать запросы от пользовательских транзакций. Транзакции могут выпустить много запросов к InnoDB перед завершением. На современных операционных системах и серверах с мультиядерными процессорами, где переключение контекста эффективно, большинство рабочих нагрузок, выполнены хорошо без особого предела на число параллельных потоков.

В ситуациях, где полезно минимизировать контекст, переключающийся между потоками, InnoDB может использовать много методов, чтобы ограничить число параллельного выполнения потоков операционной системы (и таким образом число запросов, которые обработаны в любой момент). Когда InnoDB получает новый запрос от пользовательского сеанса, если число одновременно выполняющихся потоков дошло до предопределенного предела, запрос спит в течение короткого времени прежде, чем попробует еще раз. Запрос, который не может быть запланирован после сна, помещен в очередь first-in/first-out и в конечном счете обработан. Потоки, ждущие блокировок, не посчитаны в числе параллельного выполнения потоков.

Вы можете ограничить число параллельных потоков, устанавливая параметры конфигурации innodb_thread_concurrency. Как только число выполняемых потоков достигает этого предела, дополнительные потоки спят в течение числа микросекунд, установленного параметром конфигурации innodb_thread_sleep_delay, прежде, чем быть помещенными в очередь.

Вы можете установить параметр конфигурации innodb_adaptive_max_sleep_delay к самому высокому значению, которое Вы разрешаете для innodb_thread_sleep_delay, и InnoDB автоматически корректирует innodb_thread_sleep_delay в зависимости от текущей и планируемой активности потоков. Эта динамическая корректировка помогает механизму планирования потока работать гладко в течение времен, когда система слегка загружена и когда она занята максимально.

Значение по умолчанию для innodb_thread_concurrency и подразумеваемый предел значения по умолчанию числа параллельных потоков был изменен в различных выпусках MySQL и InnoDB. Значение по умолчанию для innodb_thread_concurrency 0, чтобы по умолчанию не было никакого предела числа параллельного выполнения потоков.

InnoDB отправляет потоки в спячку только, когда число параллельных потоков ограничено. Когда нет никакого предела числа потоков, все работают одинаково. Таким образом, если innodb_thread_concurrency 0, значение innodb_thread_sleep_delay проигнорировано.

Когда есть предел числа потоков (когда innodb_thread_concurrency > 0), InnoDB уменьшает издержки переключения контекста, разрешая многократные запросы во время выполнения одного запроса SQL, не проверяя предела, установленного innodb_thread_concurrency. Так как запрос SQL может включить многострочные операции в пределах InnoDB, InnoDB назначает конкретное количество тикетов, которые позволяют потоку неоднократно планироваться с минимальными издержками.

Когда новый запрос SQL запускается, у потока нет никаких тикетов, и это должно работать согласно innodb_thread_concurrency. Как только поток входит в InnoDB, этому назначают много тикетов, которые это может использовать для того, чтобы впоследствии выполнить операции со строками. Если тикеты заканчиваются, поток вычеркивается, и innodb_thread_concurrency снова отслеживается, чтобы поместить поток назад в очередь first-in/first-out потоков ожидания. Когда поток еще раз попадает туда, тикеты назначены снова. Число назначенных тикетов определено глобальной опцией innodb_concurrency_tickets, 5000 по умолчанию. Потоку, который ждет блокировки, дают один тикет, как только блокировка становится доступной.

Правильные значения этих переменных зависят от Вашей среды и рабочей нагрузки. Попробуйте диапазон различных значений, чтобы определить, какое значение работает на Ваших приложениях. Прежде, чем ограничить число параллельного выполнения потоков, рассмотрите параметры конфигурации, которые могут улучшить исполнение InnoDB, например, innodb_adaptive_hash_index.

Для общей информации об обработке потока MySQL см. раздел 9.12.4.1.

16.6.6. Конфигурирование числа фоновых потоков ввода/вывода InnoDB

InnoDB применяет фоновые потоки , чтобы обслужить различные типы запросов ввода/вывода. Вы можете сконфигурировать число фоновых потоков, используя параметры конфигурации innodb_read_io_threads и innodb_write_io_threads. Эти параметры показывают число фоновых потоков, используемых для чтения и записи, соответственно. Они эффективны на всех поддержанных платформах. Вы можете установить значение этих параметров в файле опции MySQL (my.cnf или my.ini), Вы не можете изменить их динамически. Значение по умолчанию для этих параметров 4 допустимые значения 1-64.

Цель этого изменения состоит в том, чтобы сделать InnoDB более масштабируемым на системах высокого класса. Каждый фоновый поток может обработать до 256 запросов ввода/вывода. Основной источник фонового ввода/вывода это запросы предвыборки. InnoDB пытается сбалансировать загрузку входящих запросов таким способом, которым большая часть фоновой доли потоков работает одинаково. InnoDB также пытается выделить запросы чтения от того же самого экстента к тому же самому потоку, чтобы увеличить возможности соединения запросов вместе. Если у Вас есть подсистема ввода/вывода высокого класса, и Вы видите больше, чем 64 ждущих чтения запросов в SHOW ENGINE INNODB STATUS, Вы могли бы извлечь пользу, увеличивая значение innodb_read_io_threads.

Для получения дополнительной информации о работе ввода/вывода InnoDB см. раздел 9.5.8.

16.6.7. Конфигурирование ведущего уровня ввода/вывода потока InnoDB

Мастер-поток в InnoDB это поток, который выполняет различные задачи в фоне. Большинство этих задач связаны с вводом/выводом, такие, как сброс грязных страниц из буферного пула или запись изменений из буфера вставки в соответствующий вторичный индекс. Основной поток пытается выполнить эти задачи способом, который не оказывает негативное влияние на нормальную работу сервера. Это пытается оценить свободную доступную пропускную способность ввода/вывода и настроить свои действия, чтобы использовать в своих интересах эту свободную способность. Исторически InnoDB использовал твердое кодированное значение 100 IOPs (операций ввода/вывода в секунду) как полная способность ввода/вывода сервера.

Параметр innodb_io_capacity указывает на полную способность ввода/вывода, доступную InnoDB. Эти параметры должны быть установлены к приблизительному числу операций ввода/вывода, которые система может выполнить в секунду. Значение зависит от Вашей системной конфигурации. Когда innodb_io_capacity задано, основной поток оценивает пропускную способность ввода/вывода, доступную для фоновых задач, исходя из этого значения. Установка значения в 100 возвращает к старому поведению.

Вы можете установить значение innodb_io_capacity к числу 100 или больше. Значение по умолчанию 200, отражает, что производительность типичных современных устройств ввода/вывода выше, чем в первые годы MySQL. Как правило, значения около предыдущего значения по умолчанию 100 являются подходящими для устройств хранения данных потребительского уровня, таких как жесткие диски до 7200 RPM. Более быстрые жесткие диски, конфигурации RAID и SSD извлекают выгоду из более высоких значений.

innodb_io_capacity задает полный предел для всех экземпляров буферного пула. Когда грязные страницы сбрасываются, предел innodb_io_capacity разделен одинаково среди экземпляров буферного пула. Для получения дополнительной информации см. описание переменной innodb_io_capacity .

Вы можете установить значение этого параметра в файле опций MySQL или изменить динамически с помощью SET GLOBAL, при наличии привилегии SUPER.

Опция innodb_flush_sync предписывает игнорировать innodb_io_capacity во время взрывов деятельности ввода/вывода, которые происходят в контрольных точках. innodb_flush_sync включена по умолчанию.

В более ранних выпусках MySQL основной поток InnoDB также выполнял любые необходимые операции чистки . Те операции ввода/вывода теперь выполнены другими фоновыми потоками, числом которых управляет опция innodb_purge_threads .

Для получения дополнительной информации о работе ввода/вывода InnoDB см. раздел 9.5.8.

16.6.8. Конфигурирование опроса спин-блокировки

Много InnoDB mutex и rw-блокировок сохранены в течение короткого времени. На мультиядерной системе может быть более эффективно для потока непрерывно проверять, может ли это приобрести mutex или rw-блокировку некоторое время перед сном. Если mutex или rw-блокировка становятся доступными во время этого периода, поток может немедленно продолжиться в том же самом интервале времени. Однако, также частый опрос многократными потоками совместно используемого объекта может вызвать перегрузку кэша. InnoDB минимизирует эту проблему при ожидании случайное время между последующими опросами. Задержка осуществлена как цикл.

Вы можете управлять максимальной задержкой между тестированием mutex или rw-блокировки, используя параметр innodb_spin_wait_delay. Продолжительность цикла задержки зависит от компилятора C и целевого процессора. В эру Pentium на 100 МГц задержка была одной микросекундой. На системе, где все ядра процессора совместно используют быструю кэш-память, Вы могли бы уменьшить максимальную задержку или отключить цикл, устанавливая innodb_spin_wait_delay=0. На многопроцессорной системе эффект аннулирования кэша может быть более существенным, и Вы могли бы увеличить максимальную задержку.

Значение по умолчанию innodb_spin_wait_delay 6. Задержка это динамический глобальный параметр, который Вы можете определить в файле опции MySQL или командой SET GLOBAL innodb_spin_wait_delay=delay, где delay желаемая максимальная задержка. Изменение настроек требует привилегии SUPER.

Для исполнительных соображений операций блокировки в InnoDB см. раздел 9.11.

16.6.9. Конфигурирование планирования чистки InnoDB

Чистка (тип сбора мусора), которую InnoDB выполняет автоматически, теперь сделана в одном или более отдельных потоках, а не как часть мастер-потока. Это изменение улучшает масштабируемость, потому что основные операции базы данных работают независимо от работы обслуживания, происходящей в фоне.

Чтобы управлять этой особенностью, увеличьте значение параметра конфигурации innodb_purge_threads. Если действие DML сконцентрировано на единственной таблице или нескольких таблицах, сохраните установку низкой так, чтобы потоки не боролись друг с другом за доступ к занятым таблицам. Если операции DML распространены на многие таблицы, увеличивайте установку. Ее максимум 32.

Есть другой связанный параметр конфигурации innodb_purge_batch_size со значением по умолчанию 300 и максимальным значением 5000. Эта опция, главным образом, предназначена для экспериментирования и настройки операций чистки и не должна быть интересной типичным пользователям.

Для получения дополнительной информации о работе ввода/вывода InnoDB см. раздел 9.5.8.

16.6.10. Настройка оптимизатора статистики для InnoDB

Этот раздел описывает, как сконфигурировать постоянную статистику для таблиц InnoDB.

Статистические данные сохранены через перезапуски сервера, учитывая большую стабильность плана и и более последовательную работу запроса. Постоянные статистические данные также обеспечивают управление и гибкость с этими дополнительными выгодами:

  • Вы можете использовать параметр конфигурации innodb_stats_auto_recalc, чтобы управлять, обновлены ли статистические данные автоматически после существенных изменений в таблице.

  • Вы можете использовать параметры STATS_PERSISTENT, STATS_AUTO_RECALC и STATS_SAMPLE_PAGES в CREATE TABLE и ALTER TABLE, чтобы сконфигурировать статистику для отдельных таблиц.
  • Вы можете запросить данные о статистике в таблицах mysql.innodb_table_stats и mysql.innodb_index_stats.
  • Вы можете рассмотреть столбец last_update таблиц mysql.innodb_table_stats и mysql.innodb_index_stats, чтобы видеть, когда статистические данные обновлялись.
  • Вы можете вручную изменить таблицы mysql.innodb_table_stats и mysql.innodb_index_stats, чтобы вызвать определенный план оптимизации запроса или проверить альтернативные планы, не изменяя базу данных.

Постоянная опция статистики активирована по умолчанию ( innodb_stats_persistent=ON).

Нестойкие статистические данные очищены на каждом перезапуске сервера и после некоторых других операций, и повторно вычислены при следующем доступе к таблице. В результате различные оценки могли быть произведены при перевычислении статистики, приводя к различному выбору в планах выполнения и изменениям в работе запроса.

Этот раздел также предоставляет информацию об оценке сложности ANALYZE TABLE, которая может быть полезной, пытаясь достигнуть баланса между точной статистикой и временем выполнения ANALYZE TABLE .

16.6.10.1. Конфигурирование постоянных параметров статистики

Постоянная статистика улучшает стабильность плана, храня статистику на диске и делая ее постоянной через перезапуски сервера так, чтобы оптимизатор, более вероятно, сделал последовательный выбор каждый раз для данного запроса.

Статистические данные сохранены на диск, когда innodb_stats_persistent=ON или когда отдельные таблицы составлены или изменены с STATS_PERSISTENT=1 . innodb_stats_persistent включен по умолчанию.

Прежде статистика была очищена при каждом перезапуске сервера и после некоторых других операций и повторно вычислена при следующем доступе к таблице. Следовательно, различные оценки могли быть произведены, повторно вычисляя статистику, приводя к различному выбору в планах выполнения запроса и таким образом изменениям в работе запроса.

Постоянные статистические данные сохранены в таблицах mysql.innodb_table_stats и mysql.innodb_index_stats, как описано в разделе 16.6.10.1.5.

Чтобы вернуться к использованию нестойкой статистики, Вы можете изменить таблицы, используя ALTER TABLE tbl_name STATS_PERSISTENT=0. Для соответствующей информации см. раздел 16.6.10.2.

16.6.10.1.1. Конфигурирование автоматического вычисления для постоянной статистики

Опция innodb_stats_auto_recalc, которая включена по умолчанию, определяет, вычислены ли статистические данные автоматически всякий раз, когда таблица подвергается существенным изменениям (больше, чем 10% строк). Вы можете также сконфигурировать автоматический перерасчет статистики для отдельных таблиц, используя параметр STATS_AUTO_RECALC в CREATE TABLE или ALTER TABLE. innodb_stats_auto_recalc включен по умолчанию.

Из-за асинхронной природы автоматического перерасчета статистики (который происходит в фоне), статистика не может быть повторно вычислена немедленно после выполнения работы DML, которая затрагивает больше, чем 10% таблицы, даже когда включен innodb_stats_auto_recalc. В некоторых случаях перерасчет статистики может быть отсрочен на несколько секунд. Если современные статистические данные требуются немедленно после изменения существенных частей таблицы, выполните ANALYZE TABLE, чтобы начать синхронный перерасчет статистики.

Если innodb_stats_auto_recalc отключен, гарантируйте точность статистики через ANALYZE TABLE для каждой применимой таблицы после существенных изменений индексированных столбцов. Вы могли бы выполнить этот запрос в своих скриптах после того, как представительные данные были загружены в таблицу, и периодически после того, как операции DML значительно изменяют содержание индексированных столбцов, или по графику во время низкой активности. Когда новый индекс добавлен к существующей таблице, статистика вычисленыа и добавлена к таблице innodb_index_stats независимо от значения innodb_stats_auto_recalc.

Чтобы гарантировать сбор статистики, когда новый индекс создается, включите innodb_stats_auto_recalc или выполните ANALYZE TABLE после создания каждого нового индекса, когда постоянный режим статистики включен.

16.6.10.1.2. Параметры статистики для отдельных таблиц

innodb_stats_persistent, innodb_stats_auto_recalc и innodb_stats_persistent_sample_pages глобальные параметры конфигурации. Чтобы переопределить эти настройки в масштабе всей системы и сконфигурировать параметры статистики для отдельных таблиц, Вы можете определить параметры STATS_PERSISTENT, STATS_AUTO_RECALC и STATS_SAMPLE_PAGES в CREATE TABLE или ALTER TABLE.

  • STATS_PERSISTENT определяет, включить ли постоянную статистику для таблицы InnoDB. Значение DEFAULT заставляет постоянную установку статистики для таблицы быть определенной опцией innodb_stats_persistent. Значение 1 включает постоянную статистику для таблицы, в то время как значение 0 выключает эту особенность. После включения постоянной статистики через CREATE TABLE или ALTER TABLE скомандуйте ANALYZE TABLE, чтобы вычислить статистику, после загрузки представительных данных в таблицу.

  • STATS_AUTO_RECALC определяет, вычислить ли повторно автоматически постоянную статистику для таблицы InnoDB. Значение DEFAULT предписывает взять значение опции innodb_stats_auto_recalc. Значение 1 указывает, что статистика будет повторно вычислена, когда 10% данных в таблице изменились. Значение 0 предотвращает автоматический пересчет для этой таблицы, с этой установкой скомандуйте ANALYZE TABLE, чтобы повторно вычислить статистику после существенных изменений в таблице.
  • STATS_SAMPLE_PAGES определяет число индексных страниц в образце, оценивая количество элементов и другую статистику для индексированного столбца, таких как вычисленные ANALYZE TABLE.

Все три пункта определены в следующем примере CREATE TABLE:

CREATE TABLE `t1` (`id` int(8) NOT NULL auto_increment,
                   `data` varchar(255), `date` datetime, PRIMARY KEY (`id`),
                   INDEX `DATE_IX` (`date`)) ENGINE=InnoDB,
                   STATS_PERSISTENT=1, STATS_AUTO_RECALC=1,
                   STATS_SAMPLE_PAGES=25;
16.6.10.1.3. Конфигурирование числа выбранных страниц для статистики InnoDB

MySQL запрашивают оцененную статистику использования ключевых распределений, чтобы выбрать индексирование для плана выполнения, основанное на относительной селективности индексирования. Такие операции, как ANALYZE TABLE просят InnoDB пробовать случайные страницы каждого индекса таблицы, чтобы оценить количество элементов индексирования. Этот метод известен как случайные погружения.

Чтобы дать Вам контроль над качеством оценки статистики (и таким образом лучшую информацию для запроса), Вы можете изменить число выбранных страниц, используя параметр innodb_stats_persistent_sample_pages, который может быть установлен во время выполнения.

innodb_stats_persistent_sample_pages имеет значение по умолчанию 20. Как общее руководство, рассмотрите изменение этого параметра, сталкиваясь со следующими проблемами:

  1. Statistics are not accurate enough and the optimizer chooses suboptimal plans в выводе EXPLAIN. Точность статистики может быть проверена, сравнивая фактическое количество элементов индексирования (как возвращено SELECT DISTINCT на столбцах индекса с оценками, обеспеченными таблице mysql.innodb_index_stats.

    Если решено, что статистические данные недостаточно точны, значение innodb_stats_persistent_sample_pages должно быть увеличено, пока оценки статистики не станут достаточно точными. Увеличение innodb_stats_persistent_sample_pages, однако, может вызвать замедление ANALYZE TABLE.

  2. ANALYZE TABLE работает медленно. В этом случае innodb_stats_persistent_sample_pages надо уменьшить до приемлемой скорости ANALYZE TABLE. Уменьшение значения, однако, могло привести к первой проблеме неточной статистики и подоптимальных планов выполнения запроса.

    Если баланс не может быть достигнут между точной статистикой и скоростью statistics and ANALYZE TABLE помните, что сокращение числа индексированных столбцов в таблице или ограничение числа разделов уменьшает сложность ANALYZE TABLE. Число столбцов в первичном ключе таблицы также важно, поскольку столбцы первичного ключа добавлены к каждому групповому индексу.

    Для соответствующей информации см. раздел 16.6.10.3.

16.6.10.1.4. Включение помеченных для удаления записей в вычисления статистики

По умолчанию InnoDB читает нейтральные данные, вычисляя статистику. В случае нейтральной транзакции, которая удаляет строки из таблицы, InnoDB исключает записи, которые отмечены как удаленные, вычисляя оценки строки и индексную статистику, которая может привести к неоптимальным планам выполнения относительно других транзакций, которые воздействуют на таблицу, одновременно используя операционный уровень изоляции, кроме READ UNCOMMITTED. Чтобы обойти эту ситуацию, опция innodb_stats_include_delete_marked может быть включена, чтобы гарантировать, что InnoDB добавляет записи, которые отмечены как удаленные, вычисляя постоянную статистику.

При включении innodb_stats_include_delete_marked ANALYZE TABLE рассматривает помеченные как удаленные записи, повторно вычисляя статистику.

innodb_stats_include_delete_marked глобальная установка, которая затрагивает все таблицы. Это применимо только к постоянной статистике. innodb_stats_include_delete_marked была введена в MySQL 8.0.1.

16.6.10.1.5. Постоянные таблицы статистики InnoDB

Постоянная статистика полагается на таблицы innodb_table_stats и innodb_index_stats в базе данных mysql. Эти таблицы настроены автоматически в ходе установки и обновления.

Таблица 16.3. Столбцы innodb_table_stats

Имя столбцаОписание
database_nameИмя базы данных
table_nameИмя таблицы, имя раздела или подраздела
last_updatetimestamp, указывающий последнее время обновления этой строки
n_rowsЧисло строк в таблице
clustered_index_size Размер первичного индекса в страницах
sum_of_other_index_sizes Полный размер других (не первичных) индексов в страницах

Таблица 16.4. Столбцы innodb_index_stats

СтолбецОписание
database_nameИмя базы данных
table_nameИмя таблицы, имя раздела или подраздела
index_nameИмя индекса
last_updatetimestamp, указывающий последнее время обновления этой строки
stat_nameНазвание статистической величины, о значении которой сообщают в столбце stat_value
stat_valueЗначение статистической величины, которая названа в столбце stat_name
sample_sizeЧисло страниц, выбранных для оценки величины в столбце stat_value
stat_description Описание статистической величины, которую называют в столбце stat_name

Таблицы innodb_table_stats и innodb_index_stats включают столбец last_update, показывающий, когда InnoDB в последний раз обновлени индексную статистику, как показано в следующем примере:

mysql> select * from innodb_table_stats \G
*************************** 1. row ***************************
 database_name: sakila
table_name: actor
   last_update: 2014-05-28 16:16:44
n_rows: 200
clustered_index_size: 1
sum_of_other_index_sizes: 1
...

mysql> select * from innodb_index_stats \G
*************************** 1. row ***************************
   database_name: sakila
  table_name: actor
  index_name: PRIMARY
 last_update: 2014-05-28 16:16:44
   stat_name: n_diff_pfx01
  stat_value: 200
 sample_size: 1
 ...

Таблицы innodb_table_stats и innodb_index_stats это обычные таблицы и могут быть обновлены вручную. Способность обновить статистику вручную позволяет вызвать определенный план оптимизации запроса или проверить альтернативные планы, не изменяя базу данных. Если Вы вручную обновляете статистику, скомандуйте FLUSH TABLE tbl_name, чтобы заставить MySQL перезагрузить обновленную статистику.

16.6.10.1.6. Пример постоянной табличной статистики InnoDB

Таблица innodb_table_stats содержит одну строку на таблицу. Собранные данные продемонстрированы в следующем примере.

Таблица t1 содержит первичный индекс (столбцы a, b), вторичный индекс (столбцы c, d) и уникальный индекс (столбцы e, f):

CREATE TABLE t1 (a INT, b INT, c INT, d INT, e INT, f INT,
       PRIMARY KEY (a, b), KEY i1 (c, d),
       UNIQUE KEY i2uniq (e, f)) ENGINE=INNODB;

После вставки пяти строк типовых данных таблица выглядит так:

mysql> SELECT * FROM t1;
+---+---+----+----+-----+-----+
| a | b | c  | d  | e   | f   |
+---+---+----+----+-----+-----+
| 1 | 1 | 10 | 11 | 100 | 101 |
| 1 | 2 | 10 | 11 | 200 | 102 |
| 1 | 3 | 10 | 11 | 100 | 103 |
| 1 | 4 | 10 | 12 | 200 | 104 |
| 1 | 5 | 10 | 12 | 100 | 105 |
+---+---+----+----+-----+-----+

Чтобы немедленно обновить статистику, скомандуйте ANALYZE TABLE (если включена innodb_stats_auto_recalc, статистические данные обновлены автоматически в течение нескольких секунд, предполагая, что порог 10% для измененных строк таблицы достигнут):

mysql> ANALYZE TABLE t1;
+---------+---------+----------+----------+
| Table   | Op      | Msg_type | Msg_text |
+---------+---------+----------+----------+
| test.t1 | analyze | status   | OK       |
+---------+---------+----------+----------+

Табличная статистика для таблицы показывает: обновлена в последний раз 2014-03-14 14:36:34, число строк в таблице (5), размер кластеризируемого индекса (1 страница) и объединенный размер других индексов (2 страницы).

mysql> SELECT * FROM mysql.innodb_table_stats WHERE table_name like 't1'\G
*************************** 1. row ***************************
 database_name: test
table_name: t1
   last_update: 2014-03-14 14:36:34
n_rows: 5
clustered_index_size: 1
sum_of_other_index_sizes: 2

Таблица innodb_index_stats содержит многократные строки для каждого индекса. Каждая строка в таблице innodb_index_stats обеспечивает, данные, связанные с индексируемой статистической величиной, которую называют в столбце stat_name и описывают в stat_description, например:

mysql> SELECT index_name, stat_name, stat_value, stat_description
    ->        FROM mysql.innodb_index_stats WHERE table_name like 't1';
+------------+--------------+------------+-----------------------------------+
| index_name | stat_name    | stat_value | stat_description                  |
+------------+--------------+------------+-----------------------------------+
| PRIMARY    | n_diff_pfx01 | 1          | a                                 |
| PRIMARY    | n_diff_pfx02 | 5          | a,b                               |
| PRIMARY    | n_leaf_pages | 1          | Number of leaf pages in the index |
| PRIMARY    | size         | 1          | Number of pages in the index      |
| i1         | n_diff_pfx01 | 1          | c                                 |
| i1         | n_diff_pfx02 | 2          | c,d                               |
| i1         | n_diff_pfx03 | 2          | c,d,a                             |
| i1         | n_diff_pfx04 | 5          | c,d,a,b                           |
| i1         | n_leaf_pages | 1          | Number of leaf pages in the index |
| i1         | size         | 1          | Number of pages in the index      |
| i2uniq     | n_diff_pfx01 | 2          | e                                 |
| i2uniq     | n_diff_pfx02 | 5          | e,f                               |
| i2uniq     | n_leaf_pages | 1          | Number of leaf pages in the index |
| i2uniq     | size         | 1          | Number of pages in the index      |
+------------+--------------+------------+-----------------------------------+

Столбец stat_name показывает следующие типы статистики:

  • size: Где stat_name=size, столбец stat_value выводит на экран общее количество страниц в индексе.

  • n_leaf_pages: Где stat_name=n_leaf_pages , столбец stat_value выводит на экран число страниц в индексе.
  • n_diff_pfxNN: Где stat_name=n_diff_pfx01, столбец stat_value выводит на экран число отличных значений в первом столбце индексирования. Где stat_name=n_diff_pfx02, столбец stat_value столбец выводит на экран число отличных значений в первых двух столбцах индексирования и так далее. Дополнительно где stat_name=n_diff_pfxNN, столбец stat_description показывает список разделенных запятой значений индексированных столбцов, которые посчитаны.

Далее n_diff_pfxNN это статистическая величина, которая обеспечивает данные о количестве элементов, рассматриваемых в примере таблицы t1. Как показано ниже, таблица t1 составлена с первичным индексом (столбцы a, b), вторичным индексом (столбцы c, d) и уникальным индексом (столбцы e, f):

CREATE TABLE t1 (a INT, b INT, c INT, d INT, e INT, f INT,
       PRIMARY KEY (a, b), KEY i1 (c, d),
       UNIQUE KEY i2uniq (e, f)) ENGINE=INNODB;

После вставки пяти строк типовых данных таблица выглядит так:

mysql> SELECT * FROM t1;
+---+---+----+----+-----+-----+
| a | b | c  | d  | e   | f   |
+---+---+----+----+-----+-----+
| 1 | 1 | 10 | 11 | 100 | 101 |
| 1 | 2 | 10 | 11 | 200 | 102 |
| 1 | 3 | 10 | 11 | 100 | 103 |
| 1 | 4 | 10 | 12 | 200 | 104 |
| 1 | 5 | 10 | 12 | 100 | 105 |
+---+---+----+----+-----+-----+

Когда Вы запрашиваете index_name, stat_name, stat_value и stat_description, где stat_name LIKE 'n_diff%', следующий набор результатов возвращен:

mysql> SELECT index_name, stat_name, stat_value, stat_description
    ->        FROM mysql.innodb_index_stats
    ->        WHERE table_name like 't1' AND stat_name LIKE 'n_diff%';
+------------+--------------+------------+------------------+
| index_name | stat_name    | stat_value | stat_description |
+------------+--------------+------------+------------------+
| PRIMARY    | n_diff_pfx01 | 1          | a                |
| PRIMARY    | n_diff_pfx02 | 5          | a,b              |
| i1         | n_diff_pfx01 | 1          | c                |
| i1         | n_diff_pfx02 | 2          | c,d              |
| i1         | n_diff_pfx03 | 2          | c,d,a            |
| i1         | n_diff_pfx04 | 5          | c,d,a,b          |
| i2uniq     | n_diff_pfx01 | 2          | e                |
| i2uniq     | n_diff_pfx02 | 5          | e,f              |
+------------+--------------+------------+------------------+

Для индекса PRIMARY есть две строки n_diff%. Число строк равно числу столбцов в индексировании.

Для группового индекса InnoDB добавляет столбцы первичного ключа.

  • Где index_name=PRIMARY и stat_name=n_diff_pfx01, stat_value 1, который указывает, что есть единственное отличное значение в первом столбце индексирования (столбец a). Число отличных значений в столбце a подтверждено, рассматривая данные в столбце a таблицы t1, в котором есть единственное отличное значение (1). Посчитанный столбец (a) показан в столбце stat_description набора результатов.

  • Где index_name=PRIMARY и stat_name=n_diff_pfx02, stat_value 5, который указывает, что есть пять отличных значений в двух столбцах индексирования (a,b). Число отличных значений в столбцах a и b подтверждено, рассматривая данные в столбцах a и b таблицы t1, в которых есть пять отличных значений: (1,1), (1,2), (1,3), (1,4) и (1,5). Посчитанные столбцы (a,b) показаны в столбце stat_description набора результатов.

Для вторичного индекса (i1) есть четыре строки n_diff%. Только два столбца определены для вторичного индекса (c,d), но есть четыре строки n_diff% для него, потому что InnoDB соединяет все групповые индексы с первичным ключом. В результате есть четыре строки n_diff% вместо двух, чтобы сосчитать оба столбца вторичного индекса (c,d) и столбцы первичного ключа (a,b).

  • Где index_name=i1 и stat_name=n_diff_pfx01, stat_value 1, который указывает, что есть единственное отличное значение в первом столбце индексирования (столбец c). Число отличных значений в столбце c подтверждено, рассматривая данные в столбце c в таблице t1, в котором есть единственное отличное значение: (10). Посчитанный столбец (c) показан в столбце stat_description набора результатов.

  • Где index_name=i1 и stat_name=n_diff_pfx02, stat_value 2, который указывает, что есть два отличных значения в первых двух столбцах индексирования (c,d). Число отличных значений в столбцах c и d подтверждено, рассматривая данные в столбцах c и d в таблице t1, в которых есть два отличных значения: (10,11) и (10,12). Посчитанные столбцы (c,d) показаны в столбце stat_description набора результатов.
  • Где index_name=i1 и stat_name=n_diff_pfx03, stat_value 2, который указывает, что есть два отличных значения в первых трех столбцах индексирования (c,d,a). Число отличных значений в столбцах c, d и a подтверждено, рассматривая данные в столбцах c, d и a таблицы t1, в которых есть два отличных значения: (10,11,1) и (10,12,1). Посчитанные столбцы (c,d,a) показаны в столбце stat_description набора результатов.
  • Где index_name=i1 и stat_name=n_diff_pfx04, stat_value 5, который указывает, что есть пять отличных значений в четырех столбцах индексирования (c,d,a,b). Число отличных значений в столбцах c, d, a и b подтверждено, рассматривая данные в столбцах c, d, a и b в таблице t1, в которых есть пять отличных значений: (10,11,1,1), (10,11,1,2), (10,11,1,3), (10,12,1,4) и (10,12,1,5). Посчитанные столбцы (c,d,a,b) показаны в столбце stat_description набора результатов.

Для уникального индекса (i2uniq) есть две строки n_diff%.

  • Где index_name=i2uniq и stat_name=n_diff_pfx01, stat_value 2, который указывает, что есть два отличных значения в первом столбце индекса (столбец e). Число отличных значений в столбце e подтверждено, рассматривая данные в столбце e в таблице t1, в котором есть два отличных значения: (100) и (200). Посчитанный столбец (e) показан в столбце stat_description набора результатов.

  • Где index_name=i2uniq и stat_name=n_diff_pfx02, stat_value is 5, который указывает, что есть пять отличных значений в двух столбцах индекса (e,f). Число отличных значений в столбцах e и f подтверждено, рассматривая данные в столбцах e и f в таблице t1, в котором есть пять отличных значений: (100,101), (200,102), (100,103), (200,104) и (100,105). Посчитанные столбцы (e,f) показаны в столбце stat_description набора результатов.

16.6.10.1.7. Получение размера индекса, используя таблицу innodb_index_stats

Размер индекса для таблицы, раздела или подраздела может быть получен, используя таблицу innodb_index_stats. В следующем примере размеры индексов получены для таблицы t1. Для определения таблицы t1 и соответствующей статистики см. раздел 16.6.10.1.6.

mysql> SELECT SUM(stat_value) pages, index_name,
    ->        SUM(stat_value)*@@innodb_page_size size
    ->        FROM mysql.innodb_index_stats WHERE table_name='t1' AND
    ->        stat_name = 'size' GROUP BY index_name;
+-------+------------+-------+
| pages | index_name | size  |
+-------+------------+-------+
| 1     | PRIMARY    | 16384 |
| 1     | i1         | 16384 |
| 1     | i2uniq     | 16384 |
+-------+------------+-------+

Для раздела или подраздела подойдет тот же запрос, но с измененным WHERE. Например, следующий запрос получает размеры индексов для раздела таблицы t1:

mysql> SELECT SUM(stat_value) pages, index_name,
    ->        SUM(stat_value)*@@innodb_page_size size
    ->        FROM mysql.innodb_index_stats
                 WHERE table_name like 't1#P%' AND
    ->        stat_name = 'size' GROUP BY index_name;

16.6.10.2. Конфигурирование нестойких параметров статистики

Этот раздел описывает, как сконфигурировать нестойкую статистику. Статистические данные не сохранены на диске, когда innodb_stats_persistent=OFF или когда отдельные таблицы составлены или изменены с STATS_PERSISTENT=0 . Вместо этого статистические данные сохранены в памяти и потеряны, когда сервер закрыт. Статистические данные также периодически обновляются определенными операциями и при определенных условиях.

Статистические данные сохранены на диск по умолчанию при включении опции innodb_stats_persistent. Для информации о постоянной статистике см. раздел 16.6.10.1 .

Обновления статистики

Статистические данные обновлены когда:

  • Выполнена ANALYZE TABLE .

  • Выполнена SHOW TABLE STATUS , SHOW INDEX или запросы к таблице INFORMATION_SCHEMA.TABLES или INFORMATION_SCHEMA.STATISTICS с включенной опцией innodb_stats_on_metadata.

    Настройка по умолчанию для innodb_stats_on_metadata OFF. Включение innodb_stats_on_metadata может уменьшить скорость доступа для схем, у которых есть большое количество таблиц или индексов, и уменьшить стабильность планов выполнения относительно запросов, которые вовлекают таблицы InnoDB. innodb_stats_on_metadata сконфигурирована глобально, используя SET.

    SET GLOBAL innodb_stats_on_metadata=ON
    
  • Запуск mysql с опцией --auto-rehash, что является значением по умолчанию. Опция auto-rehash предписывает повторно вычислить статистику.

    Чтобы улучшить время запуска mysql и обновления статистики, Вы можете выключить auto-rehash, используя опцию --disable-auto-rehash. auto-rehash позволяет автоматическое завершение имени базы данных, таблицы и столбцов для интерактивных пользователей.

  • Таблица открыта первой.
  • InnoDB обнаруживает, что 1/16 таблицы была изменены с прошлого обновления статистических данных.

Конфигурирование числа выбранных страниц

Оптимизатор MySQL запрашивают оцененную статистику о ключевых распределениях, чтобы выбрать индексирование для плана выполнения, основанного на относительной селективности индекса. Когда InnoDB обновляет статистику, это пробует случайные страницы от каждого индекса в таблицы, чтобы оценить количество элементов индекса. Этот метод известен как случайные погружения.

Чтобы дать Вам контроль над качеством оценки статистики (и таким образом лучшую информацию для запроса), Вы можете изменить число выбранных страниц, используя параметр innodb_stats_transient_sample_pages. Число значения по умолчанию выбранных страниц 8 может быть недостаточным, чтобы произвести точную оценку. Этот метод особенно важен для больших таблиц и таблиц, используемых в joins. Ненужное полное сканирование таблицы для таких таблиц может быть существенной исполнительной проблемой. См. раздел 9.2.1.21 для подсказок относительно настройки таких запросов. innodb_stats_transient_sample_pages глобальный параметр, который может быть установлен во время выполнения.

Значение innodb_stats_transient_sample_pages влияет на осуществление выборки для всех таблиц и нидексов InnoDB, когда innodb_stats_persistent=0. Знайте о следующем потенциально существенном влиянии, когда Вы изменяете объем выборки:

  • Маленькие значения как 1 или 2 могут привести к неточным оценкам количества элементов.

  • Увеличение innodb_stats_transient_sample_pages могло бы потребовать большего количества дисковых чтений. Значения, намного больше 8 (например, 100), могут вызвать существенное замедление во время открытия таблицы или выполнения SHOW TABLE STATUS.
  • Оптимизатор мог бы выбрать совсем другие планы запроса, основанные на различных оценках селективности индекса.

Выберите значение, которое приводит к разумно точным оценкам для всех таблиц в Вашей базе данных, не требуя чрезмерного ввода/вывода. Поскольку статистические данные автоматически повторно вычислены неоднократно кроме выполнения ANALYZE TABLE, не имеет смысла увеличивать объем выборки, запуская ANALYZE TABLE, уменьшите объем выборки.

Меньшие таблицы вообще требуют меньшие образцы индекса, чем большие таблицы. Если у Вашей базы данных есть много больших таблиц, рассмотрите использование более высокого значения для innodb_stats_transient_sample_pages, чем если бы у Вас есть главным образом маленькие таблицы.

16.6.10.3. Оценка сложности ANALYZE TABLE для таблиц InnoDB

Сложность ANALYZE TABLE для таблицы InnoDB зависит от:

  • Числа выбранных страниц, как определено innodb_stats_persistent_sample_pages.

  • Числа индексированных столбцов в таблице.
  • Числа разделов. Если у таблицы нет никакого разделения, число разделов 1.

Используя эти параметры, приблизительная формула для того, чтобы оценить сложность ANALYZE TABLE:

Значение innodb_stats_persistent_sample_pages * число индексированных столбцов в таблице * число разделов.

Как правило, чем больше получающееся значение, тем больше время выполнения для ANALYZE TABLE.

innodb_stats_persistent_sample_pages определяет число страниц, выбранных на глобальном уровне. Чтобы определить число страниц, выбранных для отдельной таблицы, используйте опцию STATS_SAMPLE_PAGES в CREATE TABLE или ALTER TABLE. Подробности в разделе 16.6.10.1.

Если innodb_stats_persistent=OFF, число выбранных страниц определено innodb_stats_transient_sample_pages. См. раздел 16.6.10.2.

Для более всестороннего подхода к оценке сложности ANALYZE TABLE рассмотрите следующий пример.

В записи Big O сложность ANALYZE TABLE описана как:

O(n_sample * (n_cols_in_uniq_i + n_cols_in_non_uniq_i + n_cols_in_pk *
 (1 + n_non_uniq_i)) * n_part)

Здесь:

  • n_sample число выбранных страниц (определено innodb_stats_persistent_sample_pages).

  • n_cols_in_uniq_i общее количество всех столбцов всех уникальных индексов (не считая столбцы первичного ключа).
  • n_cols_in_non_uniq_i общее количество всех столбцов всех неуникальных индексов.
  • n_cols_in_pk число столбцов в первичном ключе (если первичный ключ не определен, InnoDB создает единственный первичный ключ столбца внутренне).
  • n_non_uniq_i число групповых индексов в таблице.
  • n_part число разделов. Если никакое разделение не определено, таблица является единственным разделом.

Теперь, рассмотрите следующую таблицу (таблица t), у которой есть первичный ключ (2 столбца), уникальный индекс (2 столбца) и два групповых индекса (по два столбца каждый):

CREATE TABLE t (a INT, b INT, c INT, d INT, e INT, f INT, g INT, h INT,
                PRIMARY KEY (a, b), UNIQUE KEY i1uniq (c, d),
                KEY i2nonuniq (e, f), KEY i3nonuniq (g, h));

Для данных столбца и индекса, требуемых алгоритмом, описанным выше, запрашивают постоянный индекс статистики из mysql.innodb_index_stats для таблицы t. Статистические данные n_diff_pfx% показывают столбцы, которые посчитаны для каждого индекса. Например, столбцы a и b посчитаны для индекса первичного ключа. Для неуникальных индексов столбцы первичного ключа (a,b) посчитаны в дополнение к определяемым пользователем столбцам.

Для дополнительной информации о постоянных таблицах статистики InnoDB см. раздел 16.6.10.1.

SELECT index_name, stat_name, stat_description FROM mysql.innodb_index_stats
       WHERE database_name='test' AND table_name='t' AND
       stat_name like 'n_diff_pfx%';
+------------+--------------+------------------+
| index_name | stat_name    | stat_description |
+------------+--------------+------------------+
| PRIMARY    | n_diff_pfx01 | a                |
| PRIMARY    | n_diff_pfx02 | a,b              |
| i1uniq     | n_diff_pfx01 | c                |
| i1uniq     | n_diff_pfx02 | c,d              |
| i2nonuniq  | n_diff_pfx01 | e                |
| i2nonuniq  | n_diff_pfx02 | e,f              |
| i2nonuniq  | n_diff_pfx03 | e,f,a            |
| i2nonuniq  | n_diff_pfx04 | e,f,a,b          |
| i3nonuniq  | n_diff_pfx01 | g                |
| i3nonuniq  | n_diff_pfx02 | g,h              |
| i3nonuniq  | n_diff_pfx03 | g,h,a            |
| i3nonuniq  | n_diff_pfx04 | g,h,a,b          |
+------------+--------------+------------------+

Основываясь на индексных данных о статистике, показанных выше, и табличном определении, следующие значения могут быть определены:

  • n_cols_in_uniq_i, общее количество всех столбцов во всех уникальных индексах, не считая столбцов первичного ключа, 2 (c и d).

  • n_cols_in_non_uniq_i, общее количество всех столбцов во всех неуникальных индексах 4 (e, f, g и h).
  • n_cols_in_pk, число столбцов в первичном ключе 2 (a и b).
  • n_non_uniq_i, число групповых индексов в таблице 2 (i2nonuniq и i3nonuniq)).
  • n_part, число разделов 1.

Вы можете теперь вычислить innodb_stats_persistent_sample_pages * (2 + 4 + 2 * (1 + 2)) * 1, чтобы определить число страниц, которые отсканированы. С установкой innodb_stats_persistent_sample_pages в значение по умолчанию 20 и с размером страницы по умолчанию 16 KiB ( innodb_page_size=16384) Вы можете тогда оценить, что 20 * 12 * 16384 байт считаны из таблицы t или приблизительно 4 MiB.

Все 4 MiB возможно, не будут считаны с диска, поскольку некоторые страницы могут уже кэшироваться в буферном пуле.

16.6.11. Конфигурирование порога слияния для индексных страниц

Вы можете сконфигурировать значение MERGE_THRESHOLD для индексных страниц. Если процент полных страниц для индексной страницы падает ниже MERGE_THRESHOLD, когда строка удалена или сокращена через UPDATE, InnoDB пробует слить индексную страницу с соседней индексной страницей. Значение по умолчанию MERGE_THRESHOLD 50, что является ранее неизменным значением. Минимум MERGE_THRESHOLD 1 и максимальное значение 50.

Когда процент полных страниц для индексной страницы падает ниже 50%, что является значением по умолчанию для MERGE_THRESHOLD, InnoDB пробует слить индексную страницу с соседней страницей. Если обе страницы близки к полным 50%, разделение страницы может произойти вскоре после того, как страницы слиты. Если это происходит часто, у него может быть неблагоприятное влияние на производительность. Чтобы избежать частых разделений слияния, Вы можете понизить MERGE_THRESHOLD так, чтобы InnoDB сливал страницы при более низком проценте полных страниц. Слияние страниц в более низком проценте полной страницы освобождает больше места в индексных страницах и помогает уменьшить разделение после слияния.

MERGE_THRESHOLD для индексных страниц может быть определен для таблицы или индекса. MERGE_THRESHOLD для отдельного индекса берет приоритет над MERGE_THRESHOLD для таблицы. Если не определен, значение MERGE_THRESHOLD по умолчанию 50.

Установка MERGE_THRESHOLD для таблицы

Вы можете установить значение MERGE_THRESHOLD для таблицы, используя предложение параметр COMMENT в CREATE TABLE:

CREATE TABLE t1 (id INT, KEY id_index (id)) COMMENT='MERGE_THRESHOLD=45';

Вы можете также установить значение MERGE_THRESHOLD для существующей таблицы, используя параметр COMMENT в ALTER TABLE:

CREATE TABLE t1 (id INT, KEY id_index (id));
ALTER TABLE t1 COMMENT='MERGE_THRESHOLD=40';

Задание MERGE_THRESHOLD для индекса

Установить значение MERGE_THRESHOLD для индекса можно через параметр COMMENT в запросах CREATE TABLE, ALTER TABLE или CREATE INDEX:

CREATE TABLE t1 (id INT, KEY id_index (id) COMMENT 'MERGE_THRESHOLD=40');

Или:

CREATE TABLE t1 (id INT, KEY id_index (id));
ALTER TABLE t1 DROP KEY id_index;
ALTER TABLE t1 ADD KEY id_index (id) COMMENT 'MERGE_THRESHOLD=40';

Или:

CREATE TABLE t1 (id INT);
CREATE INDEX id_index ON t1 (id) COMMENT 'MERGE_THRESHOLD=40';

Вы не можете изменить MERGE_THRESHOLD на уровне индекса для GEN_CLUST_INDEX, который является кластеризируемым индексом, создаваемым InnoDB, когда таблица составлена без первичного ключа или индекса уникального ключа. Вы можете только изменить MERGE_THRESHOLD для GEN_CLUST_INDEX установкой MERGE_THRESHOLD для таблицы.

Запрос значения MERGE_THRESHOLD для индекса

Текущее значение MERGE_THRESHOLD для индекса может быть получено, запрашивая таблицу INNODB_SYS_INDEXES:

mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_INDEXES
                   WHERE NAME='id_index' \G
*************************** 1. row ***************************
   INDEX_ID: 91
 NAME: id_index
   TABLE_ID: 68
 TYPE: 0
   N_FIELDS: 1
PAGE_NO: 4
SPACE: 57
MERGE_THRESHOLD: 40

Вы можете использовать SHOW CREATE TABLE, чтобы посмотреть значение MERGE_THRESHOLD для таблицы, если явно определено, используя предложение table_option COMMENT:

mysql> SHOW CREATE TABLE t2 \G
*************************** 1. row ***************************
   Table: t2
Create Table: CREATE TABLE `t2` (
  `id` int(11) DEFAULT NULL,
  KEY `id_index` (`id`) COMMENT 'MERGE_THRESHOLD=40'
) ENGINE=InnoDB DEFAULT CHARSET=latin1

MERGE_THRESHOLD для индексного уровня берет приоритет над MERGE_THRESHOLD уровня таблицы. Если не определено, то 50% (MERGE_THRESHOLD=50).

Аналогично, Вы можете использовать SHOW INDEX для просмотра MERGE_THRESHOLD для индексирования, если явно определено, используя COMMENT:

mysql> SHOW INDEX FROM t2 \G
*************************** 1. row ***************************
Table: t2
   Non_unique: 1
 Key_name: id_index
 Seq_in_index: 1
  Column_name: id
Collation: A
  Cardinality: 0
 Sub_part: NULL
   Packed: NULL
 Null: YES
   Index_type: BTREE
  Comment:
Index_comment: MERGE_THRESHOLD=40

Измерение эффекта MERGE_THRESHOLD

Таблица INNODB_METRICS обеспечивает два счетчика, которые могут использоваться, чтобы измерить эффект MERGE_THRESHOLD на слияниях индексной страницы.

mysql> SELECT NAME, COMMENT FROM INFORMATION_SCHEMA.INNODB_METRICS
                 WHERE NAME like '%index_page_merge%';
+-----------------------------+----------------------------------------+
| NAME                        | COMMENT                                |
+-----------------------------+----------------------------------------+
| index_page_merge_attempts   | Number of index page merge attempts    |
| index_page_merge_successful | Number of successful index page merges |
+-----------------------------+----------------------------------------+

Понижение значения MERGE_THRESHOLD дает:

  • Меньшее число попыток и успешные слияния страниц.

  • Подобное число попыток и успешных слияний страниц.

Установка MERGE_THRESHOLD, которая является слишком маленькой, могла привести к большим файлам с данными из-за чрезмерного количества пустого пространства страницы.

Для информации об использовании счетчиков INNODB_METRICS см. раздел 16.14.6 .

16.7. Табличные пространства InnoDB

16.7.1. Изменение размеров системного табличного пространства InnoDB

Этот раздел описывает, как увеличить или уменьшить системное табличное пространство InnoDB.

Увеличение размера системного табличного пространства InnoDB

Самый легкий способ увеличить размер системного табличного пространства это сконфигурировать его сначала на авторасширение. Определите атрибут autoextend для последнего файла с данными в определении табличного пространства. Тогда InnoDB увеличивает размер этого файла автоматически порциями по 64MB, когда это исчерпывает пространство. Размер порции может быть изменен, устанавливая значение innodb_autoextend_increment, которая измерена в мегабайтах.

Вы можете расширить системное табличное пространство определенным количеством, добавляя другой файл с данными:

  1. Закройте сервер MySQL.

  2. Если предыдущий последний файл с данными определен с ключевым словом autoextend, измените его определение, чтобы использовать фиксированный размер, основанный на том, как это фактически выросло. Проверьте размер файла с данными, округлите это в меньшую сторону к самому близкому числу, кратному 1024*1024 байт (=1MB), и определите этот округленный размер явно в innodb_data_file_path .
  3. Добавьте новый файл с данными в конец innodb_data_file_path, произвольно делая автомасштабирование файла. Только последний файл с данными в innodb_data_file_path может быть определен как автомасштабируемый.
  4. Запустите сервер MySQL снова.

Например, у этого табличного пространства есть только один автомасштабируемый файл с данными ibdata1:

innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:10M:autoextend

Предположите, что этот файл с данными в течение долгого времени вырос до 988MB. Вот строка конфигурации после изменения оригинального файла с данными, чтобы использовать фиксированный размер и добавления нового файла:

innodb_data_home_dir =
innodb_data_file_path = /ibdata/ibdata1:988M;/disk2/ibdata2:50M:autoextend

Когда Вы добавляете новый файл с данными к системной конфигурации табличного пространства, удостоверьтесь, что имя файла не обращается к существующему файлу. InnoDB создает и инициализирует файл, когда Вы перезапускаете сервер.

Уменьшение размера системного табличного пространства InnoDB

Вы не можете удалить файл с данными из системного табличного пространства. Чтобы уменьшить размер табличного пространства, используйте эту процедуру:

  1. Используйте mysqldump, чтобы вывести в дамп все Ваши таблицы InnoDB, включая таблицы InnoDB, расположенные в базе данных MySQL.

    mysql> select table_name from information_schema.tables
                     where table_schema='mysql' and engine='InnoDB';
    +---------------------------+
    | table_name                |
    +---------------------------+
    | columns_priv              |
    | db                        |
    | engine_cost               |
    | gtid_executed             |
    | help_category             |
    | help_keyword              |
    | help_relation             |
    | help_topic                |
    | innodb_index_stats        |
    | innodb_table_stats        |
    | plugin                    |
    | procs_priv                |
    | proxies_priv              |
    | server_cost               |
    | servers                   |
    | slave_master_info         |
    | slave_relay_log_info      |
    | slave_worker_info         |
    | tables_priv               |
    | time_zone                 |
    | time_zone_leap_second     |
    | time_zone_name            |
    | time_zone_transition      |
    | time_zone_transition_type |
    | user                      |
    +---------------------------+
    
  2. Остановите сервер.
  3. Удалите все существующие файлы табличного пространства (*.ibd), включая ibdata и ib_log. Не забывайте удалять *.ibd для таблиц, расположенных в базе данных MySQL.
  4. Сконфигурируйте новое табличное пространство.
  5. Перезапустите сервер.
  6. Импортируйте файлы дампа.

Если Ваши базы данных используют только механизм InnoDB, может быть более просто вывести в дамп все базы данных, остановить сервер, удалить все базы данных и файлы системного журнала InnoDB, перезапустить сервер и импортировать файлы дампа.

16.7.2. Изменение числа или размера файлов системного журнала Redo

Изменить число или размер файлов журнала redo можно так:

  1. Остановите сервер MySQL и удостоверьтесь, что он закрывается без ошибок.

  2. Отредактируйте my.cnf, чтобы изменить конфигурацию файла системного журнала. Чтобы изменить размер файла системного журнала, надо сконфигурировать innodb_log_file_size. Чтобы увеличить число файлов системного журнала, надо сконфигурировать innodb_log_files_in_group.
  3. Запустите сервер MySQL снова.

Если InnoDB обнаруживает, что innodb_log_file_size отличается от размера файла системного журнала, это напишет контрольную точку журнала, закроет и удалит старые файлы, создаст новые файлы в требуемом размере и откроет их.

16.7.3. Использование сырого дискового раздела для системного табличного пространства

Вы можете использовать сырой раздел в качестве файлов с данными в системном табличном пространстве InnoDB. Этот метод включает небуферизованный вводу/выводу в Windows и некоторых системах Linux и Unix без издержек файловой системы. Выполните тесты с и без сырого разделения, чтобы проверить, улучшает ли это изменение фактически работу относительно Вашей системы.

Когда Вы используете сырой дисковый раздел, гарантируете, что пользовательский ID, который выполняет сервер MySQL, имеет привилегии чтения и записи для того раздела. Например, если Вы выполняете сервер как mysql, раздел должен быть читаем и записываем для mysql. Если Вы выполняете сервер с опцией --memlock, сервер должен быть выполнен как root, таким образом, раздел должен быть доступен для root.

Процедуры, описанные ниже, вовлекают модификацию файла опции. Для дополнительной информации см. раздел 5.2.6.

Выделение сырого дискового раздела на системах Linux и Unix

  1. Когда Вы создаете новый файл с данными, определите ключевое слово newraw сразу после размера файла с данными для опции innodb_data_file_path. Раздел должен быть, по крайней мере, столь же большим как размер, который Вы определяете.

    [mysqld]
    innodb_data_home_dir=
    innodb_data_file_path=/dev/hdd1:3Gnewraw;/dev/hdd2:2Gnewraw
    
  2. Перезапустите сервер. InnoDB найдет ключевое слово newraw и инициализирует новый раздел. Однако, не создавайте или изменяйте таблицы. Иначе, когда Вы затем перезапускаете сервер, InnoDB повторно инициализирует раздел, и Ваши изменения потеряны. Как мера по безопасности InnoDB препятствует тому, чтобы пользователи изменили данные, когда любой раздел определен с newraw.
  3. После того, как InnoDB инициализировал новый раздел, остановите сервер и измените newraw на raw:
    [mysqld]
    innodb_data_home_dir=
    innodb_data_file_path=/dev/hdd1:3Graw;/dev/hdd2:2Graw
    
  4. Перезапустите сервер. InnoDB теперь разрешает вносить любые изменения.

Выделение сырого дискового раздела в Windows

В Windows те же самые шаги , описанные для систем Linux и Unix, применяются за исключением того, что innodb_data_file_path расходится немного в Windows.

  1. Когда Вы создаете новый файл с данными, определите ключевое слово newraw сразу после размера файла с данными для опции innodb_data_file_path:

    [mysqld]
    innodb_data_home_dir=
    innodb_data_file_path=//./D::10Gnewraw
    

    //./ соответствует синтаксису Windows \\.\ для того, чтобы получить доступ к физическим дискам. В примере выше D: имя диска раздела.

  2. Перезапустите сервер. InnoDB найдет ключевое слово newraw и инициализирует новый раздел.
  3. После этого остановите сервер и измените newraw на raw:
    [mysqld]
    innodb_data_home_dir=
    innodb_data_file_path=//./D::10Graw
    
  4. Перезапустите сервер. InnoDB теперь может работать.

16.7.4. Табличные пространства InnoDB File-Per-Table

Исторически все таблицы и индексы InnoDB были сохранены в системном табличном пространстве. Этот монолитный подход был хорош в машинах, посвященных полностью обработке базы данных, с тщательно запланированным ростом данных, где любое дисковое хранение, выделенное MySQL, никогда не будет необходимо в других целях. Табличное пространство InnoDB's file-per-table обеспечивает более гибкую альтернативу, где каждая таблица и индекс InnoDB сохранены в отдельном файле .ibd. Каждый такой файл .ibd представляет отдельное табличное пространство. Этой особенностью управляет опция innodb_file_per_table, которая включена по умолчанию.

Преимущества табличных пространств File-Per-Table

  • Вы можете исправить дисковое пространство, усекая или удаляя таблицу, сохраненную в файле. Усечение или удаление таблиц, сохраненных в совместно используемом системном табличном пространстве создает свободное пространство внутренне в системных файлах с данными табличного пространства (файлах ibdata), которое может использоваться только для новых данных InnoDB.

    Точно так же копирование таблицы ALTER TABLE на таблице, которая находится в совместно используемом табличном пространстве, может увеличить количество места, использованного табличным пространством. Такие операции могут потребовать такого большого количества дополнительного места, как данные в таблице плюс индекс.

  • TRUNCATE TABLE быстрее, когда выполнено на таблицах, сохраненных в файле.
  • Вы можете сохранить определенные таблицы на отдельных устройствах хранения данных, для оптимизации ввода/вывода, управления пространством или сделать копию, определяя местоположение каждой таблицы, используя синтаксис CREATE TABLE ... DATA DIRECTORY = absolute_path_to_directory, как описано в разделе 16.7.5.
  • Вы можете выполнить OPTIMIZE TABLE , чтобы уплотнить или обновить табличное пространство file-per-table. Когда Вы выполняете OPTIMIZE TABLE, InnoDB создает новый файл .ibd с временным именем, используя только место, требуемое, чтобы сохранить фактические данные. Когда оптимизация завершена, InnoDB удаляет старый файл .ibd и заменяет его новым. Если предыдущий файл .ibd вырос значительно, но фактические данные составляли только часть его размера, OPTIMIZE TABLE может восстановить неиспользуемое место.
  • Вы можете переместить таблицы, а не всю базу данных.
  • Вы можете скопировать таблицы между серверами MySQL.
  • Таблицы, составленные в табличных пространствах file-per-table, поддерживают функции, связанные с форматами строки compressed и dynamic.
  • Вы можете включить более эффективное хранение для таблиц с большими столбцами BLOB или TEXT, используя динамический формат строки .
  • Табличные пространства File-per-table могут улучшить возможности для успешного восстановления и сэкономить время, когда повреждение происходит, когда сервер не может быть перезапущен, или резервные и двоичные журналы недоступны.
  • Табличные пространства File-per-table удобны для создания отчетов о состоянии таблиц, копируя или поддерживая таблицы.
  • Вы можете контролировать табличный размер на уровне файловой системы, не получая доступ к MySQL.
  • Общие файловые системы Linux не разрешают параллельную запись в единственный файл, когда innodb_flush_method установлено O_DIRECT. В результате есть возможные исполнительные усовершенствования, используя табличные пространства file-per-table в соединении с innodb_flush_method .
  • Системное табличное пространство хранит словарь данных и журналы отмены, и имеет 64TB предел размера. В сравнении, каждое табличное пространство file-per-table имеет 64TB предел размера, который предоставляет Вам место для роста. См. раздел C.10.3.

Потенциальные недостатки табличных пространств File-Per-Table

  • С табличными пространствами file-per-table у каждой таблицы может быть неиспользуемое место, которое может быть использовано только строками той же самой таблицы. Это могло привести к потраченному впустую пространству если не должным образом управляется.

  • fsync должен работать на каждой открытой таблице, а не на единственном файле. Поскольку есть отдельный fsync для каждого файла, операции записи на многих таблицах не могут быть объединены в единственную работу ввода/вывода. Это может потребовать выполнить более высокое общее количество fsync.
  • mysqld должен сохранить один открытый дескриптор на таблицу, что может воздействовать на работу, если у Вас есть многочисленные таблицы в табличных пространствах file-per-table.
  • Используется больше описателей файла.
  • innodb_file_per_table включен по умолчанию. Вы можете рассмотреть отключение этого параметра, если обратная совместимость с MySQL 5.5 или ранее является важной. Отключение innodb_file_per_table не даст ALTER TABLE переместить таблицы InnoDB из системного табличного пространства в отдельные файлы .ibd в случаях, где ALTER TABLE обновляет таблицу (ALGORITHM=COPY).

    Например, когда идет реструктурирование кластеризируемого индека для InnoDB, таблица обновлена, используя текущую установку для innodb_file_per_table . Это поведение не применяется, добавляя или удаляя вторичные индексы. Когда вторичный индекс создается, не восстанавливая таблицу, индексирование сохранено в том же самом файле, где табличные данные, независимо от текущего значения innodb_file_per_table . Это поведение также не относится к таблицам, добавленным к системному табличному пространству через CREATE TABLE ... TABLESPACE или ALTER TABLE ... TABLESPACE . Эти таблицы не затронуты настройкой innodb_file_per_table.

  • Если много таблиц растут, есть потенциал для большего количества фрагментации, которая может препятствовать DROP TABLE и замедлить сканирование таблицы. Однако, когда фрагментацией управляют, файлы в их собственном табличном пространстве могут улучшить работу.
  • Буферный пул просмотрен при удалении табличного пространства file-per-table, что может занять несколько секунд для буферных пулов, которые имеют десятки гигабайтов в размере. Просмотр выполнен с широкой внутренней блокировкой, которая может задержать другие операции. Таблицы в системном табличном пространстве не затронуты.
  • innodb_autoextend_increment, которая определяет размер инкремента (в MB) для автомасштабирования совместно используемого файла табличного пространства, когда это становится полным, не относится к файлам табличного пространства file-per-table, которые масштабируются независимо от innodb_autoextend_increment. Начальные расширения небольшие, после них расширения происходят в инкрементах 4 МБ.

16.7.4.1. Включение и отключение табличных пространств File-Per-Table

Опция innodb_file_per_table включена по умолчанию.

Установить innodb_file_per_table можно как параметр командной строки --innodb_file_per_table или добавив строку в раздел [mysqld] файла my.cnf:

[mysqld]
innodb_file_per_table=1

Вы можете также установить innodb_file_per_table динамически, в то время как сервер работает:

SET GLOBAL innodb_file_per_table=1;

При включении innodb_file_per_table Вы можете сохранить таблицы InnoDB в файл tbl_name.ibd. В отличие от механизма хранения MyISAM с его отдельными файлами tbl_name.MYD и tbl_name.MYI, InnoDB хранит данные и индексы вместе в файле .ibd.

При выключении innodb_file_per_table в Ваших опциях запуска и перезапуске сервера или отключении этого через SET GLOBAL, InnoDB составляет новые таблицы в системном табличном пространстве, если Вы явно не поместили таблицу в табличное пространство file-per-table или общее табличное пространство, используя опцию CREATE TABLE ... TABLESPACE.

Вы можете всегда читать и писать любую таблицу InnoDB, независимо от установки file-per-table.

Чтобы переместить таблицу из системного табличного пространства в свое, измените innodb_file_per_table и пересоздайте таблицу:

SET GLOBAL innodb_file_per_table=1;
ALTER TABLE table_name ENGINE=InnoDB;

Таблицы, добавленные к системному табличному пространству через CREATE TABLE ... TABLESPACE или ALTER TABLE ... TABLESPACE не затронуты innodb_file_per_table. Чтобы переместить эти таблицы из системного табличного пространства в свое табличное пространство, они должны быть перемещены явно, используя ALTER TABLE ... TABLESPACE.

InnoDB всегда нуждается в системном табличном пространстве, потому что помещает свой внутренний словарь данных и журналы отмены там. Файлы .ibd недостаточны для работы InnoDB.

Когда таблица перемещена из системного табличного пространства в свое, файлы с данными, которые составляют системное табличное пространство, остаются того же самого размера. Место, прежде занятое таблицей, может быть снова использовано для новых данных, но не для использования операционной системой. Перемещая большие таблицы из системного табличного пространства, где дисковое пространство ограничено, Вы можете предпочесть включить innodb_file_per_table и обновите весь экземпляр, применяя mysqldump. Как упомянуто выше, таблицы, добавленные к системному табличному пространству через CREATE TABLE ... TABLESPACE или ALTER TABLE ... TABLESPACE не затронуты настройкой innodb_file_per_table . Эти таблицы должны быть перемещены индивидуально.

16.7.5. Создание табличного пространства File-Per-Table вне каталога данных

Чтобы создать новое табличное пространство file-per-table в определенном местоположении вне каталога данных MySQL, используйте параметр DATA DIRECTORY = absolute_path_to_directory в CREATE TABLE.

Запланируйте местоположение заранее, потому что Вы не можете использовать DATA DIRECTORY с ALTER TABLE . Каталог, который Вы определяете, мог быть на другом устройстве хранения данных с особыми характеристиками, таком как быстрый SSD или особо большой HDD.

В пределах целевого каталога MySQL создает подкаталог, соответствующий имени базы данных, и в его пределах файл .ibd для новой таблицы.

Следующий пример демонстрирует создание табличного пространства file-per-table вне каталога данных MySQL. Это показывает .ibd, создаваемый в указанном каталоге.

mysql> USE test;
Database changed

mysql> SHOW VARIABLES LIKE 'innodb_file_per_table';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| innodb_file_per_table | ON    |
+-----------------------+-------+
1 row in set (0.00 sec)

mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY)
                 DATA DIRECTORY = '/alternative/directory';
Query OK, 0 rows affected (0.03 sec)

# MySQL creates a .ibd file for the new table in a
# subdirectory that corresponding
# to the database name

db_user@ubuntu:~/alternative/directory/test$ ls
t1.ibd

Вы можете также использовать CREATE TABLE ... TABLESPACE в комбинации с DATA DIRECTORY, чтобы создать табличное пространство вне каталога данных MySQL. Чтобы сделать так, Вы должны определить innodb_file_per_table как имя табличного пространства.

CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE = innodb_file_per_table
       DATA DIRECTORY = '/alternative/directory';

Вы не должны включать innodb_file_per_table, используя этот метод.

Примечания использования

  • MySQL первоначально держит открытым файл .ibd, препятствуя Вам демонтировать устройство, но мог бы в конечном счете закрыть таблицу, если сервер занят. Бойтесь случайно демонтировать внешнее устройство, в то время как MySQL работает, или запустить MySQL, в то время как устройство отмонтировано. Попытка получить доступ к таблице, когда связанный файл .ibd отсутствует, это серьезная ошибка, которая требует перезапуска сервера.

    Перезапуск сервера снимает ошибки и предупреждения, если файл .ibd не в ожидаемом пути.

  • Не помещайте таблицы MySQL на NFS-том. NFS использует передающий сообщение протокол, чтобы писать файлы, который может вызвать несогласованность данных, если сетевые сообщения потеряны или получены не в том порядке.
  • Если Вы используете снимок LVM, копию файла или другой основанный на файле механизм, чтобы резервировать файл .ibd, всегда используйте FLUSH TABLES ... FOR EXPORT сначала, чтобы удостовериться, что все изменения, которые были буферизованы в памяти, сброшены на диск прежде, чем резервное копирование произойдет.
  • DATA DIRECTORY поддерживает использование символических ссылок, которые всегда был проблематичны и никогда не поддерживались для таблиц InnoDB tables.

16.7.6. Копирование табличных пространств к другому серверу

Этот раздел описывает, как скопировать табличные пространства file-per-table от одного сервера базы данных на другой. Свойство известно как мобильность. Эта особенность также поддерживает разделенные таблицы InnoDB.

Для информации о других методах копирования таблиц InnoDB см. раздел 16.8.3.

Есть много причин, почему Вы могли бы скопировать табличное пространство InnoDB file-per-table на другой сервер базы данных:

  • Выполнять отчеты, не создавая дополнительную нагрузку производственному серверу.

  • Настраивать идентичные данные для таблицы на новом подчиненном сервере.
  • Восстановить таблицу или раздел после проблемы или ошибки.
  • Как более быстрый способ переместить данные, чем импортирование результатов mysqldump . Данные доступны немедленно, вместо того, чтобы повторно вставлять и индексировать восстановленное.
  • Перемещать табличное пространство file-per-table на сервер получше. Например, Вы можете хотеть иметь занятые таблицы на устройстве SSD или большие таблицы на устройстве HDD высокой емкости.

Ограничения и примечания использования

  • Процедура копирования табличного пространства возможна только, когда включен параметр innodb_file_per_table, что является настройкой по умолчанию. Таблицы, находящиеся в совместно используемом системном табличном пространстве, не могут быть скопированы.

  • В процессе копирования транзакции только для чтения позволены на затронутой таблице.
  • Импортируя табличное пространство, размер страницы должен соответствовать размер страницы экземпляра импортирования.
  • ALTER TABLE ... DISCARD TABLESPACE поддержан для разделенных таблиц InnoDB и ALTER TABLE ... DISCARD PARTITION ... TABLESPACE поддержан для разделов.
  • DISCARD TABLESPACE не поддержан для табличных пространств с родительским дочерним элементом (внешний ключ первичного ключа), когда foreign_key_checks установлен в 1. Прежде, чем отказаться от табличного пространства для родительско-дочерних таблиц, установите foreign_key_checks=0. Разделенные таблицы InnoDB не поддерживают внешние ключи.
  • ALTER TABLE ... IMPORT TABLESPACE не проводит в жизнь ограничения внешнего ключа на импортированные данные. Если есть ограничения внешнего ключа между таблицами, все таблицы должны быть экспортированы в том же самом (логическом) моменте времени. Разделенные таблицы InnoDB не поддерживают внешние ключи.
  • ALTER TABLE ... IMPORT TABLESPACE и ALTER TABLE ... IMPORT PARTITION ... TABLESPACE не требуют метафайл .cfg с данными, чтобы импортировать табличное пространство. Однако, проверки метаданных не выполнены, импортируя без файла .cfg, и предупреждение, подобное следующему, будет:
    Message: InnoDB: IO Read error: (2, No such file or directory)
    Error opening '.\test\t.cfg', will attempt to import
    without schema verification
    1 row in set (0.00 sec)
    

    Способность импортировать без файла .cfg может быть более удобна, когда никакие несоответствия схемы не ожидаются. Дополнительно, способность импортировать без файла .cfg может быть полезна в сценариях восстановления катастрофического отказа, в которых метаданные не могут быть собраны в файле .ibd.

    Если файл .cfg не используется, InnoDB использует эквивалент SELECT MAX(ai_col) FROM table_name FOR UPDATE, чтобы инициализировать счетчик автоинкремента в памяти, который используется в назначении значений для столбца AUTO_INCREMENT. Иначе текущее максимальное значение счетчика автоинкремента считано из InnoDB AUTO_INCREMENT Counter Initialization.

  • Из-за ограничений метафайла с данными, о несоответствиях схемы не сообщают для типа разделения или различий в определении разделения, импортируя файлы табличного пространства для разделенных таблиц. О различиях в столбце сообщают.
  • При запуске ALTER TABLE ... DISCARD PARTITION ... TABLESPACE и ALTER TABLE ... IMPORT PARTITION ... TABLESPACE на разделенных таблицах позволены имена разделов и подразделов таблицы. Когда имя раздела определено, подраздел того раздела включен в работу.
  • Импортирование файла табличного пространства от другого сервера работает, если у обоих серверов есть статус GA, и их версии в пределах того же самого ряда. Иначе файл должен быть был создан на сервере той версии, в которую он импортирован.
  • В скриптах репликации innodb_file_per_table должна быть ON на ведущем и на ведомом устройствах.
  • В Windows InnoDB табличное пространство и имена таблиц внутренне хранятся в нижнем регистре. Чтобы избежать проблем импорта на чувствительных к регистру операционных системах, таких как Linux и UNIX, создайте все базы данных, табличные пространства и таблицы, используя строчные имена. Удобный способ достигнуть этого состоит в том, чтобы добавить следующую строку к разделу [mysqld] файла my.cnf или my.ini прежде, чем создать базы данных, табличные пространства или таблицы:
    [mysqld]
    lower_case_table_names=1
    
  • ALTER TABLE ... DISCARD TABLESPACE и ALTER TABLE ...IMPORT TABLESPACE не поддержаны с таблицами, которые принадлежат общему табличному пространству InnoDB. Для получения дополнительной информации см. CREATE TABLESPACE.
  • Формат строки по умолчанию для таблиц InnoDB настраивается параметром innodb_default_row_format. Попытка импортировать таблицу, которая явно не определяет формат строки (ROW_FORMAT) или использует ROW_FORMAT=DEFAULT, может привести к ошибке несоответствия схемы, если innodb_default_row_format на исходном сервере отличается от установки на целевом сервере. Для соответствующей информации см. раздел 16.10.2.
  • Экспортируя табличное пространство, которое зашифровано, используя особенность шифрования табличного пространства, InnoDB производит файл .cfp в дополнение к метафайлу .cfg. Файл .cfp должен быть скопирован к целевому серверу вместе с .cfg и файлом табличного пространства прежде, чем скомандовать ALTER TABLE ... IMPORT TABLESPACE на целевом сервере. .cfp содержит ключ передачи и зашифрованный ключ табличного пространства. При импорте InnoDB использует ключ передачи, чтобы дешифровать ключ табличного пространства. Для соответствующей информации см. раздел 16.7.10.

16.7.6.1. Мобильные примеры табличного пространства

Если Вы транспортируете таблицы, которые зашифрованы, используя шифрование табличного пространства см. здесь прежде, чем Вы начнете для дополнительной процедурной информации.

Пример 1: Копирование Таблицы InnoDB с одного сервера на другой

Эта процедура демонстрирует, как скопировать таблицу с одного экземпляра MySQL на другой. Та же самая процедура с незначительными корректировками может использоваться, чтобы выполнить полное табличное восстановление на том же самом сервере.

  1. На исходном сервере составьте таблицу, если ее нет:

    mysql> use test;
    mysql> CREATE TABLE t(c1 INT) engine=InnoDB;
    
  2. На целевом сервере составьте таблицу, если ее нет:
    mysql> use test;
    mysql> CREATE TABLE t(c1 INT) engine=InnoDB;
    
  3. На целевом сервере откажитесь от существующего табличного пространства. Прежде, чем табличное пространство сможет быть импортировано, InnoDB должен отказаться от табличного пространства, которое присоединено к таблице получения.
    mysql> ALTER TABLE t DISCARD TABLESPACE;
    
  4. На исходном сервере выполните FLUSH TABLES ... FOR EXPORT, чтобы создать метафайл .cfg с данными:
    mysql> use test;
    mysql> FLUSH TABLES t FOR EXPORT;
    

    Метафайл (.cfg) создается в каталоге данных InnoDB.

    FLUSH TABLES ... FOR EXPORT гарантирует, что изменения названной таблицы сброшены на диск так, чтобы двоичная табличная копия могла быть сделана в то время, как сервер работает. Когда выполняется FLUSH TABLES ... FOR EXPORT, InnoDB делает файл .cfg в том же самом каталоге базы данных, где таблица. Файл .cfg содержит метаданные, используемые для проверки схемы, импортируя файл табличного пространства.

  5. Скопируйте файлы .ibd и .cfg с исходного сервера на целевой:

    shell> scp /path/to/datadir/test/t.{ibd,cfg} destination-server:/path/to/datadir/test
    

    Файлы .ibd и .cfg должны быть скопированы прежде, чем выпустить совместно используемые блокировки, как описано в следующем шаге.

  6. На исходном сервере скомандуйте UNLOCK TABLES, чтобы выпустить блокировки, приобретенные FLUSH TABLES ... FOR EXPORT:

    mysql> use test;
    mysql> UNLOCK TABLES;
    
  7. На целевом сервере импортируйте табличное пространство:
    mysql> use test;
    mysql> ALTER TABLE t IMPORT TABLESPACE;
    

    ALTER TABLE ... IMPORT TABLESPACE не проводит в жизнь ограничения внешнего ключа на импортированные данные. Если есть ограничения внешнего ключа между таблицами, все таблицы должны быть экспортированы в том же самом (логическом) моменте времени. В этом случае Вы прекратите обновлять таблицы, закроете все транзакции, приобрете совместно используемые блокировки на таблицах и затем выполните экспортную работу.

Пример 2: Копирование разделенной таблицы InnoDB с одного сервера на другой

Эта процедура демонстрирует, как скопировать разделенную таблицу InnoDB с одного сервера на другой. Та же самая процедура с незначительными корректировками может использоваться, чтобы выполнить полное восстановление разделенной таблицы на том же самом сервере.

  1. На исходном сервере составьте разделенную таблицу, если ее нет. В следующем примере составлена таблица с тремя разделами (p0, p1, p2):

    mysql> use test;
    mysql> CREATE TABLE t1 (i int) ENGINE = InnoDB
                     PARTITION BY KEY (i) PARTITIONS 3;
    

    В каталоге /datadir/test Вы будете видеть отдельное табличное пространство (.ibd) для каждого из этих трех разделов.

    mysql> \! ls /path/to/datadir/test/
    t1#P#p0.ibd  t1#P#p1.ibd  t1#P#p2.ibd
    
  2. На целевом сервере составьте ту же самую разделенную таблицу:
    mysql> use test;
    mysql> CREATE TABLE t1 (i int) ENGINE = InnoDB
                     PARTITION BY KEY (i) PARTITIONS 3;
    

    В каталоге /datadir/test Вы будете видеть отдельное табличное пространство (.ibd) для каждого из этих трех разделов.

    mysql> \! ls /path/to/datadir/test/
    t1#P#p0.ibd  t1#P#p1.ibd  t1#P#p2.ibd
    
  3. На целевом сервере откажитесь от табличного пространства для разделенной таблицы. Прежде, чем табличное пространство сможет быть импортировано на целевом сервере, от табличного пространства, которое присоединено к таблице получения, нужно отказаться.
    mysql> ALTER TABLE t1 DISCARD TABLESPACE;
    

    Три файла .ibd, которые составляют табличное пространство для разделенной таблицы, исчезают из каталога /datadir/test.

  4. На исходном сервере выполните FLUSH TABLES ... FOR EXPORT, что создаст файл .cfg:
    mysql> use test;
    mysql> FLUSH TABLES t1 FOR EXPORT;
    

    Файлы данных, один для каждого табличного пространства (.ibd ), и метафайл (.cfg) создаются в каталоге /datadir/test на исходном сервере:

    mysql> \! ls /path/to/datadir/test/
    t1#P#p0.ibd  t1#P#p1.ibd  t1#P#p2.ibd
    t1#P#p0.cfg  t1#P#p1.cfg  t1#P#p2.cfg
    

    FLUSH TABLES ... FOR EXPORT гарантирует, что изменения названной таблицы сброшены на диск так, чтобы двоичная табличная копия могла быть сделана в то время, как сервер работает. Когда выполняется FLUSH TABLES ... FOR EXPORT, InnoDB создает файл .cfg с данными для файлов табличного пространства таблицы в том же самом каталоге базы данных, где таблица. .cfg содержат метаданные, используемые для проверки схемы, импортируя файлы табличного пространства. FLUSH TABLES ... FOR EXPORT может быть выполнен только на таблице, не на отдельном табличном разделе.

  5. Скопируйте файлы .ibd и .cfg на сервер назначения:

    shell> scp /path/to/datadir/test/t1*.{ibd,cfg}
                  destination-server:/path/to/datadir/test
    

    Файлы .ibd и .cfg должны быть скопированы прежде, чем выпустить совместно используемые блокировки, как описано в следующем шаге.

  6. На исходном сервере скомандуйте UNLOCK TABLES, чтобы снять блокировки, приобретенные FLUSH TABLES ... FOR EXPORT:

    mysql> use test;
    mysql> UNLOCK TABLES;
    
  7. На целевом сервере импортируйте табличное пространство для разделенной таблицы:
    mysql> use test;
    mysql> ALTER TABLE t1 IMPORT TABLESPACE;
    
Пример 3: Копирование табличного раздела с сервера на сервер

Эта процедура демонстрирует, как скопировать табличный раздел. Та же самая процедура с незначительными корректировками может использоваться, чтобы выполнить восстановление раздела. В следующем примере разделенная таблица с четырьмя разделами (p0, p1, p2, p3) составлена на исходном сервере. Два раздела (p2 и p3) скопированы целевому серверу.

  1. На исходном сервере составьте разделенную таблицу, если ее нет. В следующем примере составлена таблица с четырьмя разделами (p0, p1, p2, p3):

    mysql> use test;
    mysql> CREATE TABLE t1 (i int) ENGINE = InnoDB
                     PARTITION BY KEY (i) PARTITIONS 4;
    

    В каталоге /datadir/test Вы будете видеть отдельное табличное пространство (.ibd) для каждого из этих четырех разделов.

    mysql> \! ls /path/to/datadir/test/
    t1#P#p0.ibd  t1#P#p1.ibd  t1#P#p2.ibd t1#P#p3.ibd
    
  2. На целевом сервере составьте ту же самую разделенную таблицу:
    mysql> use test;
    mysql> CREATE TABLE t1 (i int) ENGINE = InnoDB
                     PARTITION BY KEY (i) PARTITIONS 4;
    

    В каталоге /datadir/test Вы будете видеть отдельное табличное пространство (.ibd) для каждого из этих четырех разделов.

    mysql> \! ls /path/to/datadir/test/
    t1#P#p0.ibd  t1#P#p1.ibd  t1#P#p2.ibd t1#P#p3.ibd
    
  3. На целевом сервере откажитесь от раздела табличного пространства, который Вы планируете импортировать с исходного сервера. Прежде, чем раздел табличного пространства сможет быть импортирован на целевом сервере, от соответствующего раздела, который присоединен к таблице получения, нужно отказаться.
    mysql> ALTER TABLE t1 DISCARD PARTITION p2, p3 TABLESPACE;
    

    Файлы .ibd для двух разделов, от которых отказываются, удалены из каталога /datadir/test на целевом сервере, оставляя следующие файлы:

    mysql> \! ls /path/to/datadir/test/
    t1#P#p0.ibd  t1#P#p1.ibd
    

    Когда ALTER TABLE ... DISCARD PARTITION ... TABLESPACE работает на разделенных таблицах имена таблиц и подразделов позволены. Когда имя раздела определено, подраздел того раздела включен в работу.

  4. На исходном сервере выполните FLUSH TABLES ... FOR EXPORT, чтобы получить файл .cfg.

    mysql> use test;
    mysql> FLUSH TABLES t1 FOR EXPORT;
    

    Файл (.cfg) для каждого раздела создается в каталоге /datadir/test на исходном сервере. Есть .cfg для каждого табличного пространства (.ibd).

    mysql> \! ls /path/to/datadir/test/
    t1#P#p0.ibd  t1#P#p1.ibd  t1#P#p2.ibd t1#P#p3.ibd
    t1#P#p0.cfg  t1#P#p1.cfg  t1#P#p2.cfg t1#P#p3.cfg
    

    FLUSH TABLES ... FOR EXPORT гарантирует, что изменения в названной таблице сброшены на диск так, чтобы двоичная табличная копия могла быть сделана в то время, как сервер работает. Когда FLUSH TABLES ... FOR EXPORT работает, InnoDB производит файл .cfg с данными для файлов табличного пространства таблицы в том же самом каталоге базы данных, где таблица. .cfg содержат метаданные, используемые для проверки схемы, импортируя файлы табличного пространства. FLUSH TABLES ... FOR EXPORT может быть выполнен только на таблице, не на отдельном табличном разделе.

  5. Скопируйте файлы .ibd и .cfg на сервер назначения. В этом примере только файлы .ibd and .cfg для разделов 2 (p2) и 3 (p3) скопированы в каталог data на сервере назначения. Другие разделы остаются на исходном сервере.

    shell> scp t1#P#p2.ibd  t1#P#p2.cfg t1#P#p3.ibd t1#P#p3.cfg \
                  destination-server:/path/to/datadir/test
    

    Файлы .ibd и .cfg должны быть скопированы прежде, чем выпустить совместно используемые блокировки, как описано в следующем шаге.

  6. На исходном сервере скомандуйте UNLOCK TABLES, чтобы выпустить блокировки, приобретенные FLUSH TABLES ... FOR EXPORT:

    mysql> use test;
    mysql> UNLOCK TABLES;
    
  7. На целевом сервере импортируйте разделы табличного пространства (p2 и p3):
    mysql> use test;
    mysql> ALTER TABLE t1 IMPORT PARTITION p2, p3 TABLESPACE;
    

    Когда ALTER TABLE ... DISCARD PARTITION ... TABLESPACE работает на разделенных таблицах имена таблиц и подразделов позволены. Когда имя раздела определено, подраздел того раздела включен в работу.

16.7.6.2. Мобильные внутренности табличного пространства

Следующая информация описывает внутренности и сообщения в журнале ошибок для процедуры копирования мобильных табличных пространств.

Когда ALTER TABLE ... DISCARD TABLESPACE выполнена на целевом сервере:

  • Таблица заблокирована в режиме X.

  • Табличное пространство отделено от таблицы.

Когда FLUSH TABLES ... FOR EXPORT выполнен на исходном сервере:

  • Таблица заблокирована в совместно используемом режиме.

  • Поток координатора чистки остановлен.
  • Грязные страницы синхронизированы с диском.
  • Табличные метаданные записаны в двоичный файл .cfg.

Ожидаемые сообщения журнала ошибок для этой работы:

2013-09-24T13:10:19.903526Z 2 [Note] InnoDB: Sync to disk of '"test"."t"' started.
2013-09-24T13:10:19.903586Z 2 [Note] InnoDB: Stopping purge
2013-09-24T13:10:19.903725Z 2 [Note] InnoDB: Writing table metadata to './test/t.cfg'
2013-09-24T13:10:19.904014Z 2 [Note] InnoDB: Table '"test"."t"' flushed to disk

Когда UNLOCK TABLES выполнен на исходном сервере:

  • Двоичный файл .cfg удален.

  • Совместно используемые блокировки на таблице выпущены, и поток координатора чистки перезапущен.

Ожидаемые сообщения журнала ошибок для этой работы:

2013-09-24T13:10:21.181104Z 2 [Note] InnoDB: Deleting the meta-data file
                              './test/t.cfg'
2013-09-24T13:10:21.181180Z 2 [Note] InnoDB: Resuming purge

Когда ALTER TABLE ... IMPORT TABLESPACE выполнен на целевом сервере, алгоритм импорта выполняет следующие операции для каждого импортируемого табличного пространства:

  • Каждая страница табличного пространства проверена на повреждение.

  • ID пространства и порядковые номера журнала (LSNs) на каждой странице обновлены.
  • Флаги утверждены, и LSN обновлен для страницы заголовка.
  • Страницы Btree обновлены.
  • Статус страницы установлен в "грязная", чтобы она была записана на диск.

Ожидаемые сообщения журнала ошибок для этой работы:

2013-07-18 15:15:01 34960 [Note] InnoDB: Importing tablespace for table
                    'test/t' that was exported from host 'ubuntu'
2013-07-18 15:15:01 34960 [Note] InnoDB: Phase I - Update all pages
2013-07-18 15:15:01 34960 [Note] InnoDB: Sync to disk
2013-07-18 15:15:01 34960 [Note] InnoDB: Sync to disk - done!
2013-07-18 15:15:01 34960 [Note] InnoDB: Phase III - Flush changes to disk
2013-07-18 15:15:01 34960 [Note] InnoDB: Phase IV - Flush complete

Вы можете также получить предупреждение, что от табличного пространства отказываются (если Вы отказались от табличного пространства для целевой таблицы) и сообщение, что статистика не может быть вычислена из-за отсутствия файла .ibd:

2013-07-18 15:14:38 34960 [Warning] InnoDB: Table "test"."t" tablespace is
                    set as discarded.
2013-07-18 15:14:38 7f34d9a37700 InnoDB: cannot calculate statistics for
                    table "test"."t" because the .ibd file is missing.
                    For help, please refer to
http://dev.mysql.com/doc/refman/5.8/en/innodb-troubleshooting.html

16.7.7. Хранение журналов отмены в отдельных табличных пространствах

Вы можете сохранить журналы отмены в одном или более отдельных табличных пространствах отмены за пределами системного табличного пространства. Это расположение отличается от конфигурации значения по умолчанию, где журнал отмены это часть системного табличного пространства. Образцы ввода/вывода для журнала отмены делают эти табличные пространства хорошими кандидатами, чтобы переместить на SSD, сохраняя системное табличное пространство на жестком диске. Пользователи не могут удалить отдельные табличные пространства, создаваемые, чтобы хранить журналы или отдельные сегменты в тех табличных пространствах. Однако, журналы отмены, сохраненные в табличных пространствах отмены, могут быть усеченными. Для получения дополнительной информации см. раздел 16.7.8.

Поскольку эти файлы обрабатывают операции ввода/вывода, прежде сделанные в системном табличном пространстве, мы расширяем определение системного табличного пространства, чтобы включать эти новые файлы.

Журналы отмены также упоминаются как сегменты отмены.

Эта особенность вовлекает следующие новые или переименованные параметры конфигурации:

Поскольку особенность журнала отмены вовлекает установку двух нединамических переменных запуска ( innodb_undo_tablespaces и innodb_undo_directory), эта опция может быть активирована только инициализируя экземпляр MySQL.

Примечания

Чтобы использовать эту функцию:

  1. Выберите путь, где хранить журналы отмены. Вы определите путь как параметр innodb_undo_directory в Вашем конфигурационном файле MySQL или скрипте запуска. Если никакой путь не определен, табличные пространства отмены создаются в каталоге данных MySQL, как определено datadir.

  2. Выберите начальное значение для innodb_undo_logs . Вы можете запустить с относительно низким значением и увеличить его в течение долгого времени, чтобы исследовать эффект.

    Один журнал отмены всегда назначается на системное табличное пространство, и 32 журнала отмены сохранены для использования временными таблицами и размещены во временном табличном пространстве (ibtmp1). Поэтому, чтобы выделить журналы отмены для табличных пространств отмены, innodb_undo_logs должен быть установлен в значение, больше 33. Например, если у Вас есть два табличных пространства отмены ( innodb_undo_tablespaces=2), innodb_undo_logs должен быть установлен в 35, чтобы назначить один журнал отмены на каждое из двух табличных пространств отмены.

    Когда Вы конфигурируете отдельные табличные пространства отмены, журнал отмены в системном табличном пространстве бездействует.

  3. Выберите ненулевое значение для innodb_undo_tablespaces. Множественные журналы отмены, определенные innodb_undo_logs, разделены между этим числом отдельных табличных пространств (файлы .ibd ). Это значение установлено для жизни сервера MySQL, так что, если Вы не уверены в оптимальном значении, повысьте его.

  4. Создайте новый экземпляр MySQL, используя значения, которые Вы выбрали в конфигурационном файле или в Вашем скрипте запуска MySQL. Используйте реалистическую рабочую нагрузку с объемом данных, подобным Вашим производственным серверам. Альтернативно, используйте мобильную функцию табличных пространств, чтобы скопировать существующие таблицы базы данных к Вашему недавно сконфигурированному экземпляру MySQL. См. раздел 16.7.6.
  5. Определите эффективность исполнения ввода/вывода интенсивных рабочих нагрузок.
  6. Периодически увеличивайте значение innodb_undo_logs и повторно делайте тесты производительности. Найдите значение, где Вы прекращаете получать улучшение в работе ввода/вывода.
  7. Разверните новый производственный сервер, используя идеальные настройки для этих опций. Настройте это как ведомый сервер в репликации или возьмите данные с предыдущего сервера.

Соображения масштабируемости

Хранение журналов отмены позволяют MySQL осуществлять ввод/вывод и оптимизацию памяти, связанную с этими транзакционными данными. Например, потому что данные об отмене написаны на диск и затем редко используются (только в случае восстановления катастрофического отказа), это не должно быть сохранено в кэш-памяти файловой системы, в свою очередь позволяя более высокий процент системной памяти выделить буферному пулу.

Типичная передовая практика SSD: хранить системное табличное пространство на жестком диске и переместить табличные пространства per-table на SSD.

Внутренности

Физические файлы табличного пространства называют undoN, где N ID пространства, включая начальные нули.

Вы можете усечь журналы отмены, которые находятся в табличных пространствах отмены. Для получения дополнительной информации см. раздел 16.7.8.

16.7.8. Усечение журналов отмены, которые находятся в табличных пространствах отмены

Вы можете усечь журналы отмены, которые находятся в табличных пространствах отмены, при условии, что следующие условия верны:

  • Ваш случай MySQL сконфигурирован минимум с двумя табличными пространствами отмены ( innodb_undo_tablespaces=2). Когда табличное пространство отмены является усеченным, оно временно отключается. Чтобы сервер функционировал, должно быть по крайней мере одно активное табличное пространство отмены. Число табличных пространств отмены определено опцией innodb_undo_tablespaces, которая может быть установлена только, когда сервер MySQL инициализирован. Значение по умолчанию 0. Проверить значение innodb_undo_tablespaces можно так:

    mysql> SELECT @@innodb_undo_tablespaces;
    +---------------------------+
    | @@innodb_undo_tablespaces |
    +---------------------------+
    | 2                         |
    +---------------------------+
    1 row in set (0.00 sec)
    
  • innodb_undo_logs , который определяет число сегментов отмены, используемых InnoDB, должен быть установлен в 35 или больше. Установка 35 или больше гарантирует, что журнал отмены, назначен на каждое из двух табличных пространств отмены. С innodb_undo_logs 35:

    • Первый сегмент отмены всегда находится в системном табличном пространстве (когда табличные пространства отмены присутствуют, этот сегмент отмены является бездействующим).

    • Сегменты отмены 2-33 находятся в совместно используемом временном табличном пространстве (ibtmp1).
    • 34-ый сегмент отмены находится в первом табличном пространстве отмены (если есть).
    • 35-ый сегмент отмены находится во втором табличном пространстве отмены (если есть).

    Есть отношения "многие к одному" между сегментами отмены и табличными пространствами отмены. Если число выделенных сегментов отмены больше 35, доаолнитльные сегменты отмены назначаются табличным пространствам круговым способом. Например, если у Вас есть 2 табличных пространства отмены (табличное пространство отмены 1 и табличное пространство отмены 2) и innodb_undo_logs=37 , табличному пространству отмены 1 и табличному пространству отмены 2 каждому назначили бы второй сегмент отмены.

    По умолчанию innodb_undo_logs 128, что является также максимальным значением. Проверить значение innodb_undo_logs можно так:

    mysql> SELECT @@innodb_undo_logs;
    +--------------------+
    | @@innodb_undo_logs |
    +--------------------+
    |  128               |
    +--------------------+
    1 row in set (0.00 sec)
    

    innodb_undo_logs динамическая глобальная переменная и может быть сконфигурирована, используя SET GLOBAL:

    mysql> SET GLOBAL innodb_undo_logs=128;
    

Включение усечения табличных пространств отмены

Чтобы усечь журналы отмены, которые находятся в табличных пространствах отмены, Вы должны сначала включить innodb_undo_log_truncate.

mysql> SET GLOBAL innodb_undo_log_truncate=ON;

Когда Вы включаете innodb_undo_log_truncate, файлы табличного пространства отмены, которые превышают предел размера, определенный innodb_max_undo_log_size, отмечены для усечения. innodb_max_undo_log_size динамическая глобальная переменная со значением по умолчанию 1024 MiB (1073741824 байт).

mysql> SELECT @@innodb_max_undo_log_size;
+----------------------------+
| @@innodb_max_undo_log_size |
+----------------------------+
|   1073741824               |
+----------------------------+
1 row in set (0.00 sec)

Вы можете сконфигурировать innodb_max_undo_log_size с использованием SET GLOBAL:

mysql> SET GLOBAL innodb_max_undo_log_size=2147483648;
Query OK, 0 rows affected (0.00 sec)

Когда innodb_undo_log_truncate включена:

  1. Табличные пространства отмены, которые превышают innodb_max_undo_log_size, отмечены для усечения. Выбор табличного пространства отмены для усечения выполнен круговым способом, чтобы не усекать то же самое табличное пространство отмены каждый раз.

  2. Сегменты отмены, находящиеся в выбранном табличном пространстве отмены, сделаны бездействующими так, чтобы они не были выделены новым транзакциям. Существующим транзакциям, которые в настоящее время используют сегменты отмены, позволяют завершиться.
  3. Система чистки освобождает сегменты отмены, которые больше не необходимы.
  4. После того, как все сегменты отмены в табличном пространстве отмены освобождены, табличное пространство отмены усечено к его начальному размеру. Начальный размер файла табличного пространства отмены составляет 10 МБ.

    Если Вы проверяете размер табличного пространства отмены после того усечения, размер файла может быть больше 10 МБ из-за непосредственного использования после завершения работы усечения. Опция innodb_undo_directory определяет местоположение файлов табличного пространства отмены. Значение по умолчанию . представляет каталог, где InnoDB создает другие файлы системного журнала по умолчанию.

    mysql> select @@innodb_undo_directory;
    +-------------------------+
    | @@innodb_undo_directory |
    +-------------------------+
    | .                       |
    +-------------------------+
    1 row in set (0.00 sec)
    
  5. Сегменты отмены включены так, чтобы они могли быть выделены новым транзакциям.

Ускорение усечения файлов табличного пространства отмены

Табличное пространство отмены не может быть усечено, пока его сегменты отмены не освобождены. Обычно система чистки освобождает сегменты отмены каждый 128-й раз. Чтобы ускорить усечение табличных пространств отмены, Вы можете использовать опцию innodb_purge_rseg_truncate_frequency, чтобы временно увеличить частоту, с которой система чистки освобождает сегменты отмены. По умолчанию innodb_purge_rseg_truncate_frequency 128, что является также максимальным значением.

mysql> select @@innodb_purge_rseg_truncate_frequency;
+----------------------------------------+
| @@innodb_purge_rseg_truncate_frequency |
+----------------------------------------+
|  128                                   |
+----------------------------------------+
1 row in set (0.00 sec)

Чтобы увеличить частоту, с которой поток чистки освобождает сегменты отмены, уменьшите значение innodb_purge_rseg_truncate_frequency:

mysql> SET GLOBAL innodb_purge_rseg_truncate_frequency=32;
Query OK, 0 rows affected (0.00 sec)

Исполнительное воздействие усечения файлов табличного пространства отмены

В то время как работа усечения табличного пространства отмены происходит, сегменты отмены в одном табличном пространстве отмены временно дезактивированы. Например, если у Вас есть 2 табличных пространства отмены ( innodb_undo_tablespaces=2) и 128 выделенных журналов отмены (innodb_undo_logs=128 ), 95 из журналов отмены находятся в двух табличных пространствах отмены (48 сегментов отмены в одном табличном пространстве отмены и 47 в другом). Если первое табличное пространство отмены взято офлайн, 48 журналов отмены сделаны бездействующими, уменьшая ресурс журнала отмены немного больше, чем наполовину. В то время, как работа усечения происходит, остающиеся журналы отмены принимают на себя всю системную нагрузку, что может привести к небольшой исполнительной деградации. Степень исполнительной деградации зависит в ряде факторов, включая:

  • Число табличных пространств отмены.

  • Число журналов отмены.
  • Размер табличного пространства отмены.
  • Скорость ввода/вывода.
  • Существующие рабочие транзакции.
  • Системная загрузка.

16.7.9. Общие табличные пространства InnoDB

Общее табличное пространство это особенность табличного пространства, которая обеспечивает следующие способности:

  • Подобно системному табличному пространству, общие табличные пространства это совместно используемые табличные пространства, которые могут хранить данные для многих таблиц.

  • У общих табличных пространств есть потенциальное преимущество памяти перед табличными пространствами file-per-table. Сервер сохраняет метаданные о табличном пространстве в памяти все время жизни табличного пространства. Многие таблицы в меньшем количестве общих табличных пространств потребляют меньше памяти для метаданных о табличном пространстве, чем то же самое число таблиц в отдельных табличных пространствах file-per-table.
  • Общие файлы с данными табличного пространства могут быть помещены в каталог относительно или независимо от каталога данных MySQL, который предоставляет Вам многие управленческие способности хранения of табличных пространств file-per-table. Как с табличными пространствами file-per-table, способность поместить файлы с данными за пределами каталога данных MySQL позволяет Вам управлять исполнением критических таблиц отдельно, используя RAID или DRBD для определенных таблиц или связывать таблицы с особыми дисками.
  • Общие табличные пространства поддерживают форматы файла Antelope и Barracuda и поэтому поддерживают все форматы строки таблицы и связанные особенности. С поддержкой обоих форматов файла у общих табличных пространств нет никакой зависимости от настроек innodb_file_format или innodb_file_per_table и при этом эти переменные не имеют никакого эффекта на общие табличные пространства.
  • Опция TABLESPACE может использоваться с CREATE TABLE, чтобы составлять таблицы в общих табличных пространствах, табличных пространствах file-per-table или в системном табличном пространстве.
  • Опция TABLESPACE может использоваться с ALTER TABLE, чтобы перемещать таблицы между общими табличными пространствами, табличными пространствами file-per-table и системным табличным пространством. Ранее не было возможно переместить таблицу от табличного пространства file-per-table к системному табличному пространству. С общей особенностью табличного пространства Вы можете теперь сделать так.

Создание общего табличного пространства

Общие табличные пространства создаются, используя CREATE TABLESPACE.

CREATE TABLESPACE tablespace_name ADD DATAFILE 'file_name'
       [FILE_BLOCK_SIZE = value]
       [ENGINE [=] engine_name]

Общее табличное пространство может быть создано в каталоге данных MySQL или в каталоге за пределами каталога данных MySQL. Чтобы избегать конфликтов с неявно создаваемыми табличными пространствами file-per-table, создание общего табличного пространства в подкаталоге в соответствии с каталогом данных MySQL не поддержано. Кроме того, создавая общее табличное пространство за пределами каталога данных MySQL, каталог должен существовать до создания табличного пространства.

Например:

Создание общего табличного пространства в каталоге данных MySQL:

mysql> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;

Создание общего табличного пространства в каталоге за пределами каталога данных MySQL:

mysql> CREATE TABLESPACE `ts1` ADD DATAFILE
                 '/my/tablespace/directory/ts1.ibd' Engine=InnoDB;

Вы можете определить путь относительно каталога данных MySQL, пока каталог табличного пространства не является подкаталогом каталога данных MySQL. В этом примере my_tablespace каталог на том же самом уровне, как каталог данных MySQL:

mysql> CREATE TABLESPACE `ts1` ADD DATAFILE '../my_tablespace/ts1.ibd'
                 Engine=InnoDB;

ENGINE = InnoDB должен быть определен как часть CREATE TABLESPACE или InnoDB должен быть определен как механизм хранения по умолчанию ( default_storage_engine=InnoDB).

Добавление таблиц к общему табличному пространству

После создания общего табличного пространства, Вы можете использовать CREATE TABLE tbl_name ... TABLESPACE [=] tablespace_name или ALTER TABLE tbl_name TABLESPACE [=] tablespace_name, чтобы добавить таблицы к табличному пространству, как показано в следующих примерах:

CREATE TABLE:

mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1
                 ROW_FORMAT=COMPACT;

ALTER TABLE:

mysql> ALTER TABLE t2 TABLESPACE ts1;

Для подробной информации о синтаксисе см. CREATE TABLE и ALTER TABLE.

Поддержка формата строки табличным пространством

Общие табличные пространства поддерживают все форматы строки таблицы (REDUNDANT, COMPACT, DYNAMIC, COMPRESSED), но сжатые и несжатые таблицы не могут сосуществовать в том же самом общем табличном пространстве из-за различных физических размеров страницы.

Для общего табличного пространства, чтобы содержать сжатые таблицы (ROW_FORMAT=COMPRESSED), FILE_BLOCK_SIZE должен быть определен, и FILE_BLOCK_SIZE должно быть допустимым сжатым размером страницы относительно innodb_page_size . Кроме того, физический размер страницы сжатой таблицы (KEY_BLOCK_SIZE) должен быть равным FILE_BLOCK_SIZE/1024. Например, если innodb_page_size=16K и FILE_BLOCK_SIZE=8K, KEY_BLOCK_SIZE из таблицы должен быть 8.

Следующая таблица показывает допустимые FILE_BLOCK_SIZE и KEY_BLOCK_SIZE для каждого innodb_page_size . FILE_BLOCK_SIZE могут также быть определены в байтах. Определить допустимое KEY_BLOCK_SIZE для данного FILE_BLOCK_SIZE можно, поделив FILE_BLOCK_SIZE на 1024. Табличное сжатие не поддерживает размеры страницы 32K и 64K. Для получения дополнительной информации о KEY_BLOCK_SIZE см. CREATE TABLE и раздел 16.9.1.2.

Таблица 16.5. FILE_BLOCK_SIZE и KEY_BLOCK_SIZE для CREATE TABLESPACE

Размер страницы InnoDB (innodb_page_size) Permitted FILE_BLOCK_SIZE Permitted KEY_BLOCK_SIZE
64K64K (65536)Сжатие не поддерживается
32K32K (32768)Сжатие не поддерживается
16K16K (16384)N/A: Если innodb_page_size равно FILE_BLOCK_SIZE, табличное пространство не может содержать сжатую таблицу.
8K (8192)8
4K (4096)4
2K (2048)2
1K (1024)1
8K8K (8192)N/A: Если innodb_page_size равно FILE_BLOCK_SIZE, табличное пространство не может содержать сжатую таблицу.
4K (4096)4
2K (2048)2
1K (1024)1
4K4K (4096)N/A: Если innodb_page_size равно FILE_BLOCK_SIZE, табличное пространство не может содержать сжатую таблицу.
2K (2048)2
1K (1024)1

Этот пример демонстрирует создание общего табличного пространства и добавление сжатой таблицы. Пример принимает значение по умолчанию innodb_page_size 16K. FILE_BLOCK_SIZE 8192 требует, чтобы у сжатой таблицы был KEY_BLOCK_SIZE 8.

mysql> CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd'
                 FILE_BLOCK_SIZE = 8192 Engine=InnoDB;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE t4 (c1 INT PRIMARY KEY) TABLESPACE ts2
                 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
Query OK, 0 rows affected (0.00 sec)

Если Вы не определяете FILE_BLOCK_SIZE, создавая общее табличное пространство, FILE_BLOCK_SIZE по умолчанию innodb_page_size. Когда FILE_BLOCK_SIZE = innodb_page_size, табличное пространство может содержать только таблицы с несжатым форматом строки (COMPACT, REDUNDANT и DYNAMIC).

Перемещение неразделенной таблицы между табличными пространствами, используя ALTER TABLE

Вы можете использовать ALTER TABLE с опцией TABLESPACE, чтобы переместить неразделенную таблица к существующему общему табличному пространству, к новому табличному пространству file-per-table или к системному табличному пространству.

Выполнение ALTER TABLE tbl_name TABLESPACE [=] tablespace_name на разделенной таблице только изменяет табличное пространство по умолчанию таблицы. Это не перемещает разделы таблицы.

Чтобы переместить неразделенную таблицу от табличного пространства file-per-table или системного табличного пространства в общее, определите название общего табличного пространства. Общее табличное пространство должно уже существовать. См. CREATE TABLESPACE.

ALTER TABLE tbl_name TABLESPACE [=] tablespace_name

Чтобы переместить неразделенную таблицу от общего табличного пространства или табличного пространства file-per-table в системное, надо определить innodb_system как имя табличного пространства.

ALTER TABLE tbl_name ... TABLESPACE [=] innodb_system

Чтобы переместить неразделенную таблицу от системного табличного пространства или общего табличного пространства в file-per-table, укажите innodb_file_per_table как имя табличного пространства.

ALTER TABLE tbl_name ... TABLESPACE [=] innodb_file_per_table

ALTER TABLE ... TABLESPACE всегда вызывает полное пересоздание таблицы, даже если атрибут TABLESPACE не изменился от его предыдущего значения.

ALTER TABLE ... TABLESPACE не поддерживает перемещение таблицы из временного табличного пространства в постоянное.

DATA DIRECTORY разрешен с CREATE TABLE ... TABLESPACE=innodb_file_per_table, но иное не поддержано для использования в комбинации с опцией TABLESPACE.

Поддержка разделов таблиц в общем пространстве

Опция TABLESPACE может использоваться, чтобы назначить отдельный табличный раздел или подраздел к общему табличному пространству, отдельному табличному пространству file-per-table или системному табличному пространству. Все разделы должны принадлежать тому же самому механизму хранения. Использование продемонстрировано в следующих примерах.

mysql> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
mysql> CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd' Engine=InnoDB;
mysql> CREATE TABLE t1 (a INT, b INT) ENGINE = InnoDB
    ->        PARTITION BY RANGE(a) SUBPARTITION BY KEY(b) (
    ->        PARTITION p1 VALUES LESS THAN (100) TABLESPACE=`ts1`,
    ->        PARTITION p2 VALUES LESS THAN (1000) TABLESPACE=`ts2`,
    ->        PARTITION p3 VALUES LESS THAN (10000) TABLESPACE `innodb_file_per_table`,
    ->        PARTITION p4 VALUES LESS THAN (100000) TABLESPACE `innodb_system`);

mysql> CREATE TABLE t2 (a INT, b INT) ENGINE = InnoDB
    ->        PARTITION BY RANGE(a) SUBPARTITION BY KEY(b) (
    ->           PARTITION p1 VALUES LESS THAN (100) TABLESPACE=`ts1`
    ->              (SUBPARTITION sp1, SUBPARTITION sp2),
    ->           PARTITION p2 VALUES LESS THAN (1000)
    ->              (SUBPARTITION sp3,
    ->               SUBPARTITION sp4 TABLESPACE=`ts2`),
    ->           PARTITION p3 VALUES LESS THAN (10000)
    ->              (SUBPARTITION sp5 TABLESPACE `innodb_system`,
    ->               SUBPARTITION sp6 TABLESPACE `innodb_file_per_table`));

Опция TABLESPACE также допустима с ALTER TABLE.

mysql> ALTER TABLE t1 ADD PARTITION (PARTITION p5 VALUES LESS
                THAN (1000000) TABLESPACE = `ts1`);

Если опция TABLESPACE = tablespace_name не определена, ALTER TABLE ... ADD PARTITION добавляет раздел к табличному пространству по умолчанию таблицы, которое может быть определено на табличном уровне во время CREATE TABLE или ALTER TABLE.

Чтобы проверить, что раздел был помещен в указанные табличные пространства, Вы можете запросить INFORMATION_SCHEMA.INNODB_SYS_TABLES:

mysql> SELECT NAME, SPACE, SPACE_TYPE
                 FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
    ->        WHERE NAME LIKE '%t1%';
+-----------------------+-------+------------+
| NAME                  | SPACE | SPACE_TYPE |
+-----------------------+-------+------------+
| test/t1#P#p1#SP#p1sp0 | 57    | General    |
| test/t1#P#p2#SP#p2sp0 | 58    | General    |
| test/t1#P#p3#SP#p3sp0 | 59    | Single     |
| test/t1#P#p4#SP#p4sp0 |  0    | System     |
| test/t1#P#p5#SP#p5sp0 | 57    | General    |
+-----------------------+-------+------------+

mysql> SELECT NAME, SPACE, SPACE_TYPE FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
    ->        WHERE NAME LIKE '%t2%';
+---------------------+-------+------------+
| NAME                | SPACE | SPACE_TYPE |
+---------------------+-------+------------+
| test/t2#P#p1#SP#sp1 |    57 | General    |
| test/t2#P#p1#SP#sp2 |    57 | General    |
| test/t2#P#p2#SP#sp3 |    60 | Single     |
| test/t2#P#p2#SP#sp4 |    58 | General    |
| test/t2#P#p3#SP#sp5 |     0 | System     |
| test/t2#P#p3#SP#sp6 |    61 | Single     |
+---------------------+-------+------------+

Перемещение табличного раздела между табличными пространствами, используя ALTER TABLE

Чтобы переместить табличное разделение в иное табличное пространство, Вы должны переместить каждый раздел, используя ALTER TABLE tbl_name REORGANIZE PARTITION.

Следующий пример демонстрирует, как переместить табличное разделение в иное табличное пространство. INFORMATION_SCHEMA.INNODB_SYS_TABLES и INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES запрошены, чтобы проверить, что разделение помещено в ожидаемое табличное пространство.

Если опция TABLESPACE = tablespace_name не определена в запросе REORGANIZE PARTITION, InnoDB перемещает разделение в табличное пространство по умолчанию таблицы. В этом примере табличное пространство ts1, которое определено на табличном уровне, является табличным пространством по умолчанию для таблицы t1. Раздел P3 перемещен от системного табличного пространства в ts1, поскольку нет опции TABLESPACE в ALTER TABLE t1 REORGANIZE PARTITION для раздела P3.

Чтобы изменить табличное пространство по умолчанию разделенной таблицы, Вы можете сделать ALTER TABLE tbl_name TABLESPACE [=] tablespace_name на разделенной таблице.

mysql> CREATE TABLESPACE ts1 ADD DATAFILE 'ts1.ibd';
mysql> CREATE TABLESPACE ts2 ADD DATAFILE 'ts2.ibd';
mysql> CREATE TABLE t1 ( a INT NOT NULL, PRIMARY KEY (a))
    ->        ENGINE=InnoDB TABLESPACE ts1
    ->        PARTITION BY RANGE (a) PARTITIONS 3 (
    ->        PARTITION P1 VALUES LESS THAN (2),
    ->        PARTITION P2 VALUES LESS THAN (4) TABLESPACE `innodb_file_per_table`,
    ->        PARTITION P3 VALUES LESS THAN (6) TABLESPACE `innodb_system`);

mysql> SELECT A.NAME as partition_name, A.SPACE_TYPE as space_type,
                 B.NAME as space_name
    ->        FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES A
    ->        LEFT JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES B
    ->        ON A.SPACE = B.SPACE WHERE A.NAME LIKE '%t1%'
                 ORDER BY A.NAME;
+----------------+------------+--------------+
| partition_name | space_type | space_name   |
+----------------+------------+--------------+
| test/t1#P#P1   | General    | ts1          |
| test/t1#P#P2   | Single     | test/t1#P#P2 |
| test/t1#P#P3   | System     | NULL         |
+----------------+------------+--------------+

mysql> ALTER TABLE t1 REORGANIZE PARTITION P1
    ->       INTO (PARTITION P1 VALUES LESS THAN (2) TABLESPACE = `ts2`);
mysql> ALTER TABLE t1 REORGANIZE PARTITION P2
    ->       INTO (PARTITION P2 VALUES LESS THAN (4) TABLESPACE = `ts2`);
mysql> ALTER TABLE t1 REORGANIZE PARTITION P3
    ->       INTO (PARTITION P3 VALUES LESS THAN (6));

mysql> SELECT A.NAME AS partition_name, A.SPACE_TYPE AS space_type,
                 B.NAME AS space_name
    ->        FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES A
    ->        LEFT JOIN INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES B
    ->        ON A.SPACE = B.SPACE WHERE A.NAME LIKE '%t1%'
                 ORDER BY A.NAME;
+----------------+------------+------------+
| partition_name | space_type | space_name |
+----------------+------------+------------+
| test/t1#P#P1   | General    | ts2        |
| test/t1#P#P2   | General    | ts2        |
| test/t1#P#P3   | General    | ts1        |
+----------------+------------+------------+

Удаление общего табличного пространства

DROP TABLESPACE используется, чтобы удалить общее табличное пространство.

Все таблицы должны быть исключены из табличного пространства до DROP TABLESPACE. Если табличное пространство не пусто, DROP TABLESPACE возвращает ошибку.

Табличное пространство не удалено автоматически, когда последняя таблица в табличном пространстве удалена. Табличное пространство должно быть удалено явно, используя DROP TABLESPACE tablespace_name.

Общее табличное пространство не принадлежит никакой особой базе данных. DROP DATABASE может удалить таблицы, которые принадлежат общему табличному пространству, но она не может удалить табличное пространство, даже если DROP DATABASE удаляет все таблицы, которые принадлежат табличному пространству. Общее табличное пространство должно быть явно, используя DROP TABLESPACE tablespace_name.

Подобно системному табличному пространству, удаление таблиц, сохраненных в общем табличном пространстве, создает свободное пространство внутренне в общем табличном пространстве файле данных .ibd, которое может использоваться только для новых данных InnoDB. Пространство не освобождено назад к операционной системе, как табличное пространство file-per-table удалено во время DROP TABLE.

Этот пример демонстрирует, как удалить общее табличное пространство. Общее табличное пространство ts1 создается с единственной таблицей. Таблица должна быть удалена прежде, чем все табличное пространство.

mysql> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts10 Engine=InnoDB;
Query OK, 0 rows affected (0.02 sec)

mysql> DROP TABLE t1;
Query OK, 0 rows affected (0.01 sec)

mysql> DROP TABLESPACE ts1;
Query OK, 0 rows affected (0.01 sec)

tablespace_name чувствительный к регистру идентификатор в MySQL.

Ограничения общего табличного пространства

  • Существующее табличное пространство не может быть изменено на общее табличное пространство.

  • Создание временных общих табличных пространств не поддержано.
  • Общие табличные пространства не поддерживают временные таблицы.
  • Копирование таблицы ALTER TABLE на таблице, которая находится в совместно используемом табличном пространстве (общее табличное пространство или системное табличное пространство) может увеличить количество места, использованного табличным пространством. Такие операции требуют такого большого количества дополнительного пространства, как данные в таблице плюс индекс. Дополнительное пространство требуется для копирования таблицы.
  • ALTER TABLE ... DISCARD TABLESPACE и ALTER TABLE ... IMPORT TABLESPACE не поддержаны для таблиц, которые принадлежат общему табличному пространству.

Для получения дополнительной информации см. раздел 14.1.16.

16.7.10. Шифрование табличного пространства InnoDB

InnoDB допускает шифрование данных для таблиц, сохраненных в табличных пространствах file-per-table. Эта особенность обеспечивает шифрование для физических файлов с данными табличного пространства.

Шифрование табличного пространства использует две архитектуры ключа шифрования ряда, состоя из основного ключа шифрования и ключей табличного пространства. Когда таблица зашифрована, ключ табличного пространства зашифрован и сохранен в заголовке табличного пространства. Когда приложение или пользователь хотят получить доступ к зашифрованным данным табличного пространства, InnoDB использует основной ключ шифрования, чтобы дешифровать ключ табличного пространства. Основной ключ шифрования сохранен в файле keyring в местоположении, определенном опцией keyring_file_data . Дешифрованная версия ключа табличного пространства никогда не изменяется, но основной ключ шифрования может быть изменен как требуется. Это действие упоминается как ротация главного ключа.

Особенность шифрования табличного пространства полагается на плагин keyring для основного управления ключом шифрования.

Шифрование табличного пространства поддерживает алгоритм Advanced Encryption Standard (AES) block-based. Это использует режим блочного шифрования Electronic Codebook (ECB) для ключевого шифрования табличного пространства и режим блочного шифрования Cipher Block Chaining (CBC) для шифрования данных.

Особенность шифрования табличного пространства, предоставленная MySQL Community Edition, не предназначена как решение для соответствия установленным требованиям. Стандарты безопасности, такие как PCI, FIPS и другие требуют, чтобы использование систем ключевого менеджмента обеспечило, управляло и защитило ключи в ключевых хранилищах или модулях безопасности аппаратных средств (HSM).

Для часто задаваемых вопросов о особенности шифрования табличного пространства см. раздел A.15 .

Предпосылки шифрования табличного пространства InnoDB

  • Плагин keyring_file должен быть установлен. Установка плагина выполнена при запуске, используя опцию --early-plugin-load. Ранняя загрузка гарантирует, что плагин доступен до инициализации InnoDB. Для установки плагина и инструкций конфигурации см. раздел 7.5.3.

    После того, как зашифрованные таблицы составлены в случае MySQL, плагин должен продолжить загружаться, используя early-plugin-load до инициализации InnoDB.

    Чтобы проверить, что плагин является активным, используйте SHOW PLUGINS или запросите INFORMATION_SCHEMA.PLUGINS :

    mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS FROM INFORMATION_SCHEMA.PLUGINS
        ->        WHERE PLUGIN_NAME LIKE 'keyring%';
    +--------------+---------------+
    | PLUGIN_NAME  | PLUGIN_STATUS |
    +--------------+---------------+
    | keyring_file | ACTIVE        |
    +--------------+---------------+
    
  • Опция innodb_file_per_table должна быть включена (значение по умолчанию). Шифрование табличного пространства поддерживает только табличные пространства file-per-table. Альтернативно, Вы можете определить опцию TABLESPACE='innodb_file_per_table', составляя зашифрованную таблицу или изменяя существующую таблицу, чтобы включить шифрование.
  • Перед использованием шифрования табличного пространства, гарантируйте, что Вы предприняли шаги, чтобы предотвратить потерю основного ключа шифрования. Если основной ключ шифрования потерян, данные в зашифрованных файлах табличного пространства восстановить нельзя. Рекомендуется, чтобы Вы создали резервную копию файла keyring немедленно после составления первой зашифрованной таблицы, прежде и после ротации главного ключа. Местоположение файла keyring определено опцией keyring_file_data . См. раздел 7.5.3.

Включение и отключение шифрования табличного пространства InnoDB

Чтобы включить шифрование для новой таблицы, укажите опцию ENCRYPTION в CREATE TABLE .

mysql> CREATE TABLE t1 (c1 INT) ENCRYPTION='Y';

Чтобы включить шифрование для существующей таблицы, укажите опцию ENCRYPTION в ALTER TABLE .

mysql> ALTER TABLE t1 ENCRYPTION='Y';

Чтобы выключить шифрование для таблицы, укажите опцию ENCRYPTION='N' в ALTER TABLE .

mysql> ALTER TABLE t1 ENCRYPTION='N';

Запланируйте все, изменяя существующую таблицу с опцией ENCRYPTION. ALTER TABLE ... ENCRYPTION пересоздает таблицу алгоритмом ALGORITHM=COPY. ALGORITM=INPLACE не поддержан.

Шифрование табличного пространства InnoDB и ротация главного ключа

Основной ключ шифрования должен периодически меняться и всякий раз, когда Вы подозреваете, что ключ, возможно, поставлен под угрозу.

Ротация главного ключа атомная работа на уровне сервера. Каждый раз, когда основной ключ шифрования меняется, все ключи табличных пространств повторно зашифрованы и сохранены назад к их соответствующим заголовкам табличного пространства. Как атомная работа, перешифрование должно пройти для всех ключей табличного пространства, как только работа начата. Если ротация главного ключа прервана отказом сервера, InnoDB продолжает процесс при перезапуске сервера.

Ротация основного ключа шифрования изменяет только основной ключ шифрования и повторно шифрует ключи табличного пространства. Это не дешифрует или повторно шифрует связанные данные о табличном пространстве.

Ротация основного ключа шифрования требует привилегии SUPER.

Чтобы сменить основной ключ шифрования:

mysql> ALTER INSTANCE ROTATE INNODB MASTER KEY;

ALTER INSTANCE ROTATE INNODB MASTER KEY поддерживает параллельный DML. Однако, это не может быть выполнено одновременно с CREATE TABLE ... ENCRYPTED или ALTER TABLE ... ENCRYPTED, блокировки взяты, чтобы предотвратить конфликты, которые могли явиться результатом параллельного выполнения этих запросов. Если один из противоречивых запросов работает, он должно завершиться прежде, чем другой сможет продолжить.

Шифрование табличного пространства InnoDB и восстановление

Если отказ сервера происходит во время ротации главного ключа, InnoDB продолжает работу при перезапуске сервера.

Плагин keyring должен быть загружен до инициализации механизма хранения, чтобы информация, необходимая, чтобы дешифровать страницы данных о табличном пространстве, могла быть получена от заголовков табличного пространства прежде инициализации InnoDB и востановления активности доступа к данным.

Когда инициализация и восстановление начинаются, ротация восстанавливается. Из-за отказа сервера, некоторые ключи табличных пространств могут уже быть зашифрованы, используя новый основной ключ шифрования. InnoDB читает данные о шифровании из каждого заголовка табличного пространства, и если данные указывают, что ключ табличного пространства зашифрован, используя старый ключ шифрования, получает старый ключ и использует это, чтобы дешифровать ключ пространства. InnoDB тогда повторно шифрует ключ табличного пространства с использованием нового основного ключа шифрования и сохраняет повторно зашифрованный ключ табличного пространства назад в заголовке.

Экспорт зашифрованных таблиц

Когда зашифрованная таблица экспортируется, InnoDB производит ключ передачи, который используется, чтобы зашифровать ключ табличного пространства. Зашифрованный ключ табличного пространства и ключ передачи сохранены в файле tablespace_name.cfp. Этот файл вместе с зашифрованным файлом табличного пространства обязан выполнять работу импорта. При импорте InnoDB использует ключ передачи, чтобы дешифровать ключ табличного пространства в tablespace_name.cfp. Подробности в разделе 16.7.6.

Шифрование табличного пространства InnoDB и репликация

  • ALTER INSTANCE ROTATE INNODB MASTER KEY поддержано в среде репликации, если ведущее устройство и ведомые устройства выполняют версию MySQL, которая поддерживает функцию шифрования табличного пространства.

  • Успешный запрос ALTER INSTANCE ROTATE INNODB MASTER KEY внесен в двоичный журнал на ведомых устройствах.
  • Если ALTER INSTANCE ROTATE INNODB MASTER KEY провалился, оно не пишется в двоичный журнал и не копируется на ведомые устройства.
  • Репликация ALTER INSTANCE ROTATE INNODB MASTER KEY терпит неудачу, если плагин keyring установлен на ведущем устройстве, но не на ведомом.
  • Если плагин keyring_file установлен на ведущем и на ведомом устройствах, но у ведомого устройства нет файла keyring, репликация ALTER INSTANCE ROTATE INNODB MASTER KEY создает файл keyring на ведомом устройстве, принимая что данные о файле не кэшируются в памяти. ALTER INSTANCE ROTATE INNODB MASTER KEY будет использовать данные о файле keyring, которые кэшируются в памяти, при наличии.

Идентификация Таблиц, которые используют шифрование табличного пространства InnoDB

Когда опция ENCRYPTION определена в CREATE TABLE или ALTER TABLE, это зарегистрировано в поле CREATE_OPTIONS в INFORMATION_SCHEMA.TABLES. Это поле может быть запрошена, чтобы идентифицировать зашифрованные таблицы.

mysql> SELECT TABLE_SCHEMA, TABLE_NAME, CREATE_OPTIONS
                 FROM INFORMATION_SCHEMA.TABLES
    ->        WHERE CREATE_OPTIONS LIKE '%ENCRYPTION="Y"%';
+--------------+------------+----------------+
| TABLE_SCHEMA | TABLE_NAME | CREATE_OPTIONS |
+--------------+------------+----------------+
| test         | t1         | ENCRYPTION="Y" |
+--------------+------------+----------------+

Примечания использования шифрования табличного пространства

  • Если сервер остановлен во время нормального функционирования, рекомендуется перезапустить сервер, используя те же самые настройки шифрования, которые были сконфигурированы ранее.

  • Первый основной ключ шифрования произведен, когда первая новая или существующая таблица зашифрована.
  • Ротация главного ключа повторно шифрует ключи табличных пространств, но не изменяет ключ табличного пространства непосредственно. Чтобы изменить ключ табличного пространства, Вы должны отключить и повторно включить шифрование с использованием ALTER TABLE tbl_name ENCRYPTION, который является ALGORITHM=COPY, которая восстанавливает таблицу.
  • Если таблица составлена с обоими опциями COMPRESSION и ENCRYPTION, сжатие выполнено прежде, чем данные о табличном пространстве зашифрованы.
  • Если файл keyring пуст или отсутствует, первое выполнение ALTER INSTANCE ROTATE INNODB MASTER KEY создает основной ключ шифрования.
  • Удаление плагина keyring_file не удаляет существующий файл keyring.
  • Рекомендуется, чтобы Вы не помещали файл keyring под каталогом, в котором лежат файлы с данными табличного пространства. Местоположение keyring определено опцией keyring_file_data .
  • Изменение keyring_file_data во время выполнения или перезапуск сервера с новым keyring_file_data может сделать ранее зашифрованные таблицы недоступными, приводя к потере данных.

Ограничения шифрования табличного пространства InnoDB

  • Advanced Encryption Standard (AES) является единственным поддержанным алгоритмом шифрования. InnoDB шифрование табличного пространства использует режим блочного шифрования Electronic Codebook (ECB) для ключевого шифрования табличного пространства и режим блочного шифрования Cipher Block Chaining (CBC) для шифрования данных.

  • Изменение атрибута таблицы ENCRYPTION делается через ALGORITHM=COPY. ALGORITHM=INPLACE не поддержан.
  • Шифрование табличного пространства поддерживает только таблицы, которые сохранены в табличных пространствах file-per-table. Шифрование не поддержано для таблиц, сохраненных в другом типе табличного пространства, включая общие табличные пространства , системное табличное пространство, табличные пространства журнала отмены и временное табличное пространство.
  • Вы не можете переместить или скопировать зашифрованную таблицу из табличного пространства file-per-table в неподдерживаемый тип табличного пространства.
  • Шифрование табличного пространства относится только к данным в табличном пространстве. Данные не зашифрованы в каких-либо журналах.

16.8. Таблицы и индексы InnoDB

16.8.1. Составление таблиц InnoDB

Чтобы создать таблицу, используйте CREATE TABLE. Вы не должны определить ENGINE=InnoDB, если InnoDB определен как механизм хранения по умолчанию. Вы могли бы все еще использовать ENGINE=InnoDB, если Вы планируете использовать mysqldump или репликацию, чтобы повторить CREATE TABLE на сервере, где механизм хранения по умолчанию не InnoDB.

-- Default storage engine = InnoDB.
CREATE TABLE t1 (a INT, b CHAR (20), PRIMARY KEY (a));
-- Backward-compatible with older MySQL.
CREATE TABLE t2 (a INT, b CHAR (20), PRIMARY KEY (a)) ENGINE=InnoDB;

Когда включена опция innodb_file_per_table, что является значением по умолчанию, таблица неявно составлена в отдельном табличном пространстве file-per-table. Наоборот, когда innodb_file_per_table выключена, таблица неявно составлена в системном табличном пространстве. Вы можете использовать CREATE TABLE ... TABLESPACE, чтобы явно создать таблицу в любом из трех типов табличного пространства.

Когда Вы создаете таблицу, MySQL создает каталог базы данных в соответствии с каталогом данных MySQL. Для таблицы, составленной в табличном пространстве file-per-table, создается файл .ibd. Таблица, создаваемая в системном табличном пространстве, составлена в существующем системном табличном пространстве файлов ibdata. Таблица, создаваемая в общем табличном пространстве, составлена в существующем общем табличном пространстве файла .ibd.

Внутренне InnoDB добавляет запись для каждой таблицы к словарю данных. Запись включает имя базы данных. Например, если таблица t1 создается в базе данных test, запись будет 'test/t1'. Это означает, что Вы можете составить таблицу с тем же самым именем (t1) в иной базе данных, и имена таблиц не сталкиваются внутри InnoDB.

Просмотр свойств таблиц

Используйте SHOW TABLE STATUS :

mysql > SHOW TABLE STATUS FROM test LIKE 't%' \G;
*************************** 1. row ***************************
 Name: t1
 Engine: InnoDB
Version: 10
 Row_format: Compact
 Rows: 0
 Avg_row_length: 0
Data_length: 16384
Max_data_length: 0
   Index_length: 0
  Data_free: 0
 Auto_increment: NULL
Create_time: 2015-03-16 15:13:31
Update_time: NULL
 Check_time: NULL
  Collation: latin1_swedish_ci
   Checksum: NULL
 Create_options:
Comment:
1 row in set (0.00 sec)

В выводе состояния Вы видите, что свойство Row format таблицы t1 Compact. Формат строки Dynamic или Compressed используют особенности InnoDB, такие как табличное сжатие и хранение вне страницы для длинных значений столбцов. Чтобы использовать эти форматы строки, Вы можете включить innodb_file_per_table (по умолчанию):

SET GLOBAL innodb_file_per_table=1;
CREATE TABLE t3 (a INT, b CHAR (20), PRIMARY KEY (a)) ROW_FORMAT=DYNAMIC;
CREATE TABLE t4 (a INT, b CHAR (20), PRIMARY KEY (a)) ROW_FORMAT=COMPRESSED;

Или Вы можете использовать CREATE TABLE ... TABLESPACE, чтобы создать таблицу InnoDB в общем табличном пространстве. Общие табличные пространства поддерживают все форматы строки. Для получения дополнительной информации см. раздел 16.7.9.

CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1 ROW_FORMAT=DYNAMIC;

CREATE TABLE ... TABLESPACE может также использоваться, чтобы создать таблицу с форматом строки Dynamic в системном табличном пространстве, а также таблицы с форматом строк Compact или Redundant.

CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE = innodb_system
       ROW_FORMAT=DYNAMIC;

Табличные свойства могут также быть запрошены, используя таблицы Information Schema:

SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES WHERE NAME='test/t1' \G
*************************** 1. row ***************************
 TABLE_ID: 45
 NAME: test/t1
 FLAG: 1
   N_COLS: 5
SPACE: 35
   ROW_FORMAT: Compact
ZIP_PAGE_SIZE: 0
SPACE_TYPE: Single

Определение первичного ключа для таблиц InnoDB

Всегда настраивайте первичный ключ для каждой таблицы, определяя столбец или столбцы, которые:

  • Ссылаются самыми важными запросами.

  • Никогда не оставляются незаполненными.
  • Никогда не имеют двойных значений.
  • Редко изменяют однажды вставленное значение.

Например, в таблице, содержащей информацию о людях, Вы не создали бы первичный ключ на (firstname, lastname) потому, что больше чем у одного человека может быть то же самое имя, у некоторых людей есть пустые фамилии, и иногда люди меняют свои имена. С очень многими ограничениями часто нет очевидного набора столбцов, чтобы использовать в качестве первичного ключа, таким образом, Вы создаете новый столбец с числовым ID, чтобы служить всем или частью первичного ключа. Вы можете объявить столбец auto-increment, чтобы значения были заполнены автоматически, когда строки вставлены:

-- The value of ID can act like a pointer between related items in different tables.
CREATE TABLE t5 (id INT AUTO_INCREMENT, b CHAR (20), PRIMARY KEY (id));
-- The primary key can consist of more than one column. Any autoinc column must come first.
CREATE TABLE t6 (id INT AUTO_INCREMENT, a INT, b CHAR (20), PRIMARY KEY (id,a));

Хотя таблица работает правильно, не определяя первичный ключ, первичный ключ связан со многими аспектами работы и является решающим аспектом проекта для любой большой или часто используемой таблицы. Рекомендуется, чтобы Вы всегда определили первичный ключ в CREATE TABLE. Если Вы составляете таблицу, вводите данные и затем выполняете ALTER TABLE, чтобы добавить первичный ключ позже, эта работа намного медленнее, чем определение первичного ключа, составляя таблицу.

16.8.2. Физическая структура строки таблиц InnoDB

Физическая структура строки таблицы зависит от формата строки, определенного, когда таблица составлена. Если формат строки не определен, формат строки по умолчанию используется. Формат строки по умолчанию определен опцией innodb_default_row_format, у которой есть значение по умолчанию DYNAMIC.

Формат REDUNDANT доступен, чтобы сохранить совместимость с более старыми версиями MySQL.

Чтобы проверить формат строки таблицы, Вы можете использовать SHOW TABLE STATUS:

mysql> SHOW TABLE STATUS IN test1\G
*************************** 1. row ***************************
 Name: t1
 Engine: InnoDB
Version: 10
 Row_format: Dynamic
 Rows: 0
 Avg_row_length: 0
Data_length: 16384
Max_data_length: 0
   Index_length: 16384
  Data_free: 0
 Auto_increment: 1
Create_time: 2016-09-14 16:29:38
Update_time: NULL
 Check_time: NULL
  Collation: latin1_swedish_ci
   Checksum: NULL
 Create_options:
Comment:

Вы можете также проверить формат строки, запрашивая INFORMATION_SCHEMA.INNODB_SYS_TABLES.

mysql> SELECT NAME, ROW_FORMAT FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
                 WHERE NAME='test1/t1';
+----------+------------+
| NAME     | ROW_FORMAT |
+----------+------------+
| test1/t1 | Dynamic    |
+----------+------------+

Характеристики формата строки Redundant

Строки в таблицах, использующие формат REDUNDANT, имеют следующие характеристики:

  • Каждый индекс содержит 6-байтовый заголовок. Заголовок используется, чтобы соединить последовательные записи, а также в блокировке на уровне строки.

  • Записи в кластеризируемом индекс содержат области для всех определяемых пользователем столбцов. Кроме того, есть 6-байтовая операционная область ID и 7-байтовая область указателя.
  • Если никакой первичный ключ не был определен для таблицы, каждый кластеризируемый индекс также содержит 6-байтовую область ID.
  • Каждый вторичный индекс также содержит все области первичного ключа, определенные для кластеризируемых индексных ключей, которые не находятся во вторичном индексе.
  • Запись содержит указатель на каждую область записи. Если полная длина областей меньше 128 байтов, указатель составляет один байт, иначе, два байта. Массив этих указателей называют каталогом записей. Область, куда эти указатели указывают, называют частью данных записи.
  • Внутренне InnoDB хранит символьные столбцы фиксированной длины, такие как CHAR(10), в формате фиксированной длины. InnoDB не усекает конечные пробелы столбцов VARCHAR.
  • Значение SQL NULL резервирует один или два байта в каталоге записей. Помимо этого, SQL NULL резервирует нулевые байты в части данных, если сохранен в столбце переменной длины. В столбце фиксированной длины это резервирует фиксированную длину столбца в части данных. Сохранение фиксированного пространства для NULL позволяет обновление столбца от значения NULL до не-NULL, не вызывая фрагментацию индексной страницы.

Характеристики формата строки COMPACT

Формат строки COMPACT уменьшает место для хранения строки приблизительно на 20% по сравнению с REDUNDANT за счет увеличения использования центрального процессора для некоторых операций. Если Ваша рабочая нагрузка типичная, которая ограничена частотами успешных обращений кэша и дисковой скоростью, COMPACT, вероятно, будет быстрее. Если рабочая нагрузка редкий случай, который ограничен скоростью центрального процессора, компактный формат мог бы быть медленнее.

Строки в таблице имеют следующие характеристики:

  • Каждая индексная запись содержит 5-байтовый заголовок, которому может предшествовать заголовок переменной длины. Заголовок используется, чтобы соединить последовательные записи, а также в блокировке на уровне строки.

  • Часть переменной длины заголовка содержит битовый вектор для того, чтобы указать столбцы NULL. Если число столбцов в индексировании, которые могут быть NULL N, битовый вектор занимает CEILING(N/8) байт. Например, если есть от 9 до 15 столбцов, которые могут быть NULL, битовый вектор занимает два байта. Столбцы, которые являются NULL, не занимают место, кроме бита в этом векторе. Часть переменной длины заголовка также содержит длины столбцов переменной длины. Каждая длина берет один или два байта, в зависимости от максимальной длины столбца. Если все столбцы в индексировании NOT NULL и имеют фиксированную длину, у заголовка нет никакой части переменной длины.
  • Для каждого не-NULL поля переменной длины заголовок содержит длину столбца в одном или двух байтах. Два байта необходимы только, если часть столбца сохранена внешне в страницах переполнения, или максимальная длина превышает 255 байтов, и фактическая длина превышает 127 байтов. Для внешне сохраненного столбца 2-байтовая длина указывает на длину внутренне сохраненной части плюс 20-байтовый указатель на внешне сохраненную часть. Внутренняя часть составляет 768 байтов, таким образом, длина 768+20. 20-байтовый указатель хранит истинную длину столбца.
  • Ззаголовок сопровождается содержанием столбцов не-NULL.
  • Записи в кластеризируемом индексе содержат области для всех определяемых пользователем столбцов. Кроме того, есть 6-байтовая операционная область ID и 7-байтовая область указателя.
  • Если никакой первичный ключ не был определен для таблицы, каждая запись кластеризируемого индекса также содержит 6-байтовую область ID.
  • Каждая запись вторичного индекса также содержит все области первичного ключа, определенные для кластеризируемого индексного ключа, которые не находятся во вторичном индексе. Если какая-либо из этих областей первичного ключа переменной длины, заголовок для каждого вторичного индекса имеет часть переменной длины, чтобы сделать запись их длин, даже если вторичный индекс определен на столбцах фиксированной длины.
  • Внутренне, для хранения наборов символов фиксрованной длины прменяются столбцы символов фиксированной длины, например, CHAR(10) в формате фиксированной длины.

    InnoDB не усекает конечные пробелы в столбцах VARCHAR.

  • Внутренне, для наборов символов переменной длины, например, utf8mb3 и utf8mb4, InnoDB использует для хранения CHAR(N) в N байт, обрезая конечные пробелы. Если байт длины CHAR(N) столбца превышает N байт, InnoDB обрезает конечные пробелы к минимуму длины байта значения столбца. Максимальная длина столбца CHAR(N) максимальная длина символа *N.

    InnoDB резервирует минимум N байт для CHAR(N). Сохранение минимального пространства N во многих случаях позволяет обновлениям столбца быть сделанными на месте, не вызывая фрагментацию индексной страницы. В сравнении, для ROW_FORMAT=REDUNDANT, столбцы CHAR(N) занимают максимальную символьную длину байта *N.

    CHAR обработан как тип переменной длины, если длина значения столбца больше чем или равна 768 байтам, что может произойти, если максимальная длина байта набора символов больше 3, как с utf8mb4. Когда обработано как тип переменной длины, значение столбца CHAR может быть выбрано для хранения вне страницы. Для получения дополнительной информации см. раздел 16.10.

    Дескриптор ROW_FORMAT=DYNAMIC и ROW_FORMAT=COMPRESSED хранят CHAR таким же образом, как ROW_FORMAT=COMPACT.

Форматы строк DYNAMIC и COMPRESSED

Форматы строк DYNAMIC и COMPRESSED это варианты формата COMPACT. Для информации об этих форматах строки см. раздел 16.10.3.

16.8.3. Перемещение или копирование таблиц InnoDB в другую машину

Этот раздел описывает методы для перемещения или копирования некоторых или всех таблиц InnoDB на другой сервер. Например, Вы могли бы переместить весь экземпляр MySQL на больший, более быстрый сервер, Вы могли бы клонировать весь экземпляр MySQL к новому ведомому серверу репликации, Вы могли бы скопировать отдельные таблицы на другой сервер, чтобы развить и проверить приложение, или к серверу хранилища данных, чтобы представить доклады.

Методы для перемещения или копирования таблиц включают:

Имена в нижнем регистре

В Windows InnoDB всегда хранит имена базы данных и таблиц внутренне в нижнем регистре. Чтобы переместить базы данных в двоичном формате из Unix в Windows или наоборот, создайте все базы данных и таблицы, используя строчные имена. Удобный способ достигнуть этого состоит в том, чтобы добавить следующую строку к группе [mysqld] файла my.cnf or my.ini прежде, чем создать любые базы данных или таблицы:

[mysqld]
lower_case_table_names=1

Мобильные табличные пространства

Мобильные табличные пространства используют FLUSH TABLES ... FOR EXPORT, чтобы скопировать таблицы. Чтобы использовать эту функцию, таблицы должны быть составлены с innodb_file_per_table в ON, чтобы каждая таблица имела свое собственное табличное пространство. Для информации об использовании см. раздел 16.7.6.

MySQL Enterprise Backup

MySQL Enterprise Backup позволяет Вам поддерживать рабочую базу данных MySQL, включая таблицы InnoDB и MyISAM, с минимальным разрушением к операциям, производя последовательный снимок базы данных. Когда MySQL Enterprise Backup копирует таблицы InnoDB, чтение и запись таблиц InnoDB и MyISAM могут продолжиться. Во время копирования MyISAM и других не-InnoDB таблиц, чтения (но не записи) к тем таблицам разрешены. Кроме того, MySQL Enterprise Backup может создать сжатые резервные файлы и поддержать подмножества таблиц InnoDB. В соединении с двоичным журналом Вы можете выполнить восстановление момента времени. MySQL Enterprise Backup включен как часть MySQL Enterprise.

Подробности в разделе 27.2 .

Копирование файлов с данными

Вы можете переместить база данных, просто копируя все соответствующие файлы, см. раздел 16.17.

Аналогично файлам MyISAM, InnoDB данные и файлы системного журнала совместимы на всех платформах, имеющих тот же самый числовой формат с плавающей запятой. Если форматы с плавающей запятой отличаются, но Вы не использовали DOUBLE в Ваших таблицах, процедура та же самая: просто скопируйте соответствующие файлы.

Соображения мобильности для файлов .ibd File-Per-Table

Когда Вы перемещаете или копируете файл .ibd, имя каталога базы данных должно быть тем же самым на целевых системах и источнике. Табличное определение, сохраненное в совместно используемом табличном пространстве включает имя базы данных. Операционные ID и порядковые номера журнала, сохраненные в файлах табличного пространства, также отличаются между базами данных.

Перемещать файл .ibd и связанную таблицу от одной базы данных к другой можно с помощью RENAME TABLE :

RENAME TABLE db1.tbl_name TO db2.tbl_name;

Если у Вас есть резервная копия файла .ibd, Вы можете восстановить ее к исходной установке MySQL следующим образом:

  1. Таблица, должно быть, не была удалена или усечена, так как Вы скопировали .ibd, табличный ID сохранен в табличном пространстве.

  2. С помощью ALTER TABLE удалите текущий файл .ibd:
    ALTER TABLE tbl_name DISCARD TABLESPACE;
    
  3. Скопируйте резервную копию файла .ibd к надлежащему каталогу базы данных.
  4. Используйте ALTER TABLE, чтобы сказать InnoDB использовать новый файл .ibd для таблицы:
    ALTER TABLE tbl_name IMPORT TABLESPACE;
    

    ALTER TABLE ... IMPORT TABLESPACE не проводит в жизнь ограничения внешнего ключа на импортированные данные.

В этом контексте копия файла .ibd удовлетворяет следующим требованиям:

  • Нет никаких нейтральных модификаций транзакциями в файле .ibd.

  • Нет не неслитых буферных записей вставки в .ibd.
  • Чистка удалила все отмеченные как удаленные записи индекса.
  • mysqld сбросил все измененные страницы .ibd из буферного пула.

Вы можете сделать чистое резервное копирование .ibd:

  1. Остановите всю деятельность mysqld и передайте все транзакции.

  2. Ждите, пока SHOW ENGINE INNODB STATUS покажет, что нет никаких активных транзакций в базе данных, и состояние основного потока InnoDB Waiting for server activity. Тогда Вы можете сделать копию файла .ibd.

Другой метод для того, чтобы сделать чистую копию .ibd:

  1. Используйте MySQL Enterprise Backup.

  2. Запустите второй сервер mysqld и позвольте ему очистить файлы .ibd в резервном копировании.

Экспорт и импорт (mysqldump)

Вы можете использовать mysqldump, чтобы вывести Ваши таблицы в дамп на одной машине и затем импортировать файлы дампа на другой машине. Используя этот метод, не имеет значения, отличаются ли форматы или содержат ли Ваши таблицы данные с плавающей запятой.

Один способ увеличить скорость этого метода состоит в том, чтобы выключить режим autocommit, импортируя данные, предполагая, что у табличного пространства есть достаточно пространства для большого сегмента отмены, который производят транзакции импорта. Сделайте передачу только после импортирования целой таблицы или сегмента таблицы.

16.8.4. Преобразование таблиц из MyISAM в InnoDB

Если Вы имеете таблицы MyISAM, которые Вы хотите преобразовать в InnoDB, рассмотрите следующие подсказки прежде, чем сделать преобразование.

Разделенные таблицы MyISAM, составленные в предыдущих версиях MySQL, несовместимы с MySQL 8.0. Такие таблицы должны быть подготовлены до обновления, удаляя разделение, или преобразовывая их в InnoDB. См. раздел 20.6.2.

Уменьшите использование памяти для MyISAM

Поскольку Вы переходите от таблиц MyISAM, понизьте значение key_buffer_size, чтобы освободить память, больше не нужную для того, чтобы кэшировать результаты. Увеличьте значение innodb_buffer_pool_size, которое выполняет подобную роль выделения кэш-памяти для InnoDB. Буферный пул кэширует табличные данные и индексы, таким образом, это действительно удваивает ускорение поисков для запросов и хранения результатов запроса в памяти для повторного использования. Для руководства относительно буферной конфигурации размера пула см. раздел 9.12.3.1.

На занятом сервере выполните тесты с выключенным кэшем запроса. Буферный пул обеспечивает подобную выгоду, таким образом, кэш запроса мог бы излишне связывать память.

Не упустите слишком длинные или короткие транзакции

Поскольку таблицы MyISAM не поддерживают транзакции, Вы, возможно, не обратили много внимания на настройку autocommit и команды COMMIT и ROLLBACK. Эти ключевые слова важны, чтобы позволить многим сеансам читать и писать таблицы InnoDB одновременно, обеспечивая существенную выгоду масштабируемости.

В то время как транзакция открыта, система сохраняет снимок данных в начале транзакции, что может вызвать существенные накладные расходы, если система вставляет, обновляет и удаляет миллионы строк, в то время как беспризорная транзакция продолжает работать. Таким образом, заботьтесь о том, чтобы избежать транзакций, которые работают слишком долго:

  • Если Вы используете mysql для интерактивных экспериментов, всегда командуйте COMMIT (чтобы завершить изменения) или ROLLBACK (чтобы отменить изменения) когда закончите. Закройте интерактивные сеансы вместо того, чтобы оставить их открытыми в течение длительных периодов, чтобы избежать долго открытых транзакций.

  • Удостоверьтесь что любые ошибочные обработчики в Вашем приложении также вызывают ROLLBACK или COMMIT.
  • ROLLBACK относительно дорогая работа, потому что операции INSERT, UPDATE и DELETE записаны в таблицы InnoDB до COMMIT, с ожиданием, что большинство изменений будет передано успешно и обратные перемотки будут редки. Экспериментируя с большими объемами данных, избегите производить изменения в больших количествах строк и затем откатывать те изменения до прежнего уровня.
  • Загружая большие объемы данных с последовательностью INSERT, периодически выполняйте COMMIT, чтобы избежать транзакций, которые длятся в течение многих часов. В типичных операциях загрузки для складирования данных, если что-то идет не так, как надо, Вы усекаете таблицу (используя TRUNCATE TABLE) и запустите с начала вместо того, чтобы делать ROLLBACK.

Предыдущие подсказки сохраняют место в памяти и дисковое пространство, которое может быть потрачено впустую во время слишком длинных транзакций. Когда транзакции короче, чем они должны быть, проблемой будет чрезмерный ввод/вывод. С каждым COMMIT MySQL удостоверяется, что каждое изменение безопасно зарегистрировано на диске, что вовлекает некоторый ввод/вывод.

  • Для большинства операций на таблицах InnoDB Вы должны использовать установку autocommit=0. С точки зрения эффективности это избегает ненужного ввода/вывода, когда Вы выпускаете большие количества последовательных INSERT, UPDATE или DELETE. С точки зрения безопасности это позволяет Вам использовать ROLLBACK, чтобы возвратить потерянные или искаженные данные, если Вы делаете ошибку в командах mysql или в обработчике исключения в Вашем приложении.

  • Время, когда autocommit=1 является подходящим для таблицы, выполняя последовательность запросов для того, чтобы произвести отчеты или проанализировать статистику. В этой ситуации нет никакого лишнего ввода/вывода, связанного с COMMIT или ROLLBACK, а InnoDB может автоматически оптимизировать рабочую нагрузку только для чтения.
  • Если Вы делаете серию связанных изменений, завершайте все те изменения сразу COMMIT в конце. Например, если Вы вставляете связанные сведения в несколько таблиц, сделайте одиночный COMMIT после произведения всех изменений. Или если Вы выполняете много последовательных INSERT, сделайте COMMIT после того, как все данные загружены, если Вы делаете миллионы INSERT, возможно разделить огромную транзакцию с помощью COMMIT каждые десять тысяч или сто тысяч отчетов, таким образом, транзакция не становится слишком большой.
  • Помните, что даже SELECT открывает транзакцию, таким образом, после выполнения некоторого отчета или отладки запросов в интерактивном mysql, выполните COMMIT или закройте mysql .

Не волнуйтесь слишком много о тупиках

Вы могли бы видеть предупреждающие сообщения о тупиках в журнале ошибок MySQL или выводе SHOW ENGINE INNODB STATUS. Несмотря на страшно звучащее имя, тупик не серьезная проблема для InnoDB и часто не требуют никакого корректирующего действия. Когда две транзакции начинают изменять многие таблицы, получая доступ к таблицам в различном порядке, они могут достигнуть состояния, где каждая транзакция ждет другую, и ни одна не может продолжить. Когда определение тупиков включено (значение по умолчанию), MySQL немедленно обнаруживает это условие, и отменяет меньшую, позволяя другой продолжиться. Если обнаружение тупика отключено, используя innodb_deadlock_detect, InnoDB полагается на innodb_lock_wait_timeout, чтобы откатить транзакции до прежнего уровня в случае тупика.

Так или иначе, Ваши приложения нуждаются в логике обработки ошибок, чтобы перезапустить транзакцию, которая насильственно отменена из-за тупика. Когда Вы переиздаете те же самые запросы SQL как прежде, оригинальная проблема синхронизации больше не применяется: или другая транзакция уже закончилась, и Ваша может продолжиться, или другая транзакция все еще происходит, и Ваша транзакция ждет, пока это не заканчивается.

Если предупреждения тупика постоянно происходят, Вы могли бы рассмотреть код программы, чтобы переупорядочить операции SQL последовательным способом, или сократить транзакции. Вы можете проверить с включенной опцией innodb_print_all_deadlocks, чтобы видеть все предупреждения тупика в журнале ошибок MySQL, а не только последнее предупреждение в SHOW ENGINE INNODB STATUS.

Подробности в разделе 16.5.5.

Запланируйте расположение хранения

Получить лучшую работу от InnoDB Вы можете, скорректировав много параметров, связанных с расположением хранения.

Когда Вы преобразовываете таблицы MyISAM, которые являются большими, часто используемыми и содержащими жизненные данные, исследуйте и рассмотрите опции innodb_file_per_table и innodb_page_size , а также параметры ROW_FORMAT и KEY_BLOCK_SIZE в CREATE TABLE.

Во время Ваших начальных экспериментов самая важная установка innodb_file_per_table. Когда эта установка включена, что является значением по умолчанию, новые таблицы неявно составлены в табличных пространствах file-per-table. В отличие от системного табличного пространства, табличные пространства file-per-table позволяют дисковому пространству использоваться операционной системой, когда таблица является усеченной или удаленной. Табличные пространства File-per-table также поддерживают строки форматов DYNAMIC и COMPRESSED и связанные особенности, такие как табличное сжатие, хранение вне страницы для длинных столбцов переменной длины и большой префикс индекса. Для получения дополнительной информации см. раздел 16.7.4.

Вы можете также сохранить таблицы в совместно используемом общем табличном пространстве, которое поддерживает многие таблицы и все форматы строки. Для получения дополнительной информации см. раздел 16.7.9.

Преобразование существующей таблицы

Преобразовать не-InnoDB таблицу, чтобы использовать InnoDB можно через ALTER TABLE:

ALTER TABLE table_name ENGINE=InnoDB;

Клонирование структуры таблицы

Вы могли бы сделать таблицу InnoDB, которая является клоном таблицы MyISAM, вместо того, чтобы делать ALTER TABLE, чтобы проверить старую и новую таблицу бок о бок перед переключением.

Создайте пустую таблицу с идентичными определениями столбца и индексов. Примените show create table table_name\G, чтобы посмотреть полный запрос CREATE TABLE. Смените ENGINE на ENGINE=INNODB.

Передача существующих данных

Передать большой объем данных в пустую таблицу, составленную как показано в предыдущем разделе, можно, вставив строки с помощью INSERT INTO innodb_table SELECT * FROM myisam_table ORDER BY primary_key_columns.

Вы можете также создать индексирование для таблицы после вставки данных. Исторически, создание новых вторичных индексов было медленной работой для InnoDB, но теперь Вы можете создать индексирование после того, как данные загружены, относительно легко и быстро.

Если Вы имеете ограничения UNIQUE на вторичные ключи, Вы можете ускорить табличный импорт, выключая проверки уникальности временно во время работы импорта:

SET unique_checks=0;
... import operation ...
SET unique_checks=1;

Для больших таблиц это сохраняет дисковый ввод/вывод потому, что InnoDB может использовать буфер изменения, чтобы записать вторичный индекс как пакет. Будьте уверены, что данные не содержат дубликаты ключа. unique_checks разрешает, но не требует, чтобы механизмы хранения проигнорировали дубликаты ключа.

Чтобы получить лучший контроль над процессом вставки, Вы могли бы вставить большие таблицы по частям:

INSERT INTO newtable SELECT * FROM oldtable
       WHERE yourkey > something AND
             yourkey <= somethingelse;

После того, как все записи были вставлены, Вы можете переименовать таблицы.

Во время преобразования больших таблиц, увеличьте размер буферного пула, чтобы уменьшить дисковый ввод/вывод, максимум до 80% физической памяти. Вы можете также увеличить размер файлов системного журнала.

Требования хранения

Если Вы намереваетесь сделать несколько временных копий своих данных в таблицах во время конверсионного процесса, рекомендуется, чтобы Вы составили таблицы в табличных пространствах file-per-table, чтобы Вы могли восстановить дисковое пространство, когда Вы удаляете таблицы. Как упомянуто ранее, когда innodb_file_per_table включена (значение по умолчанию), созданные таблицы неявно составлены в табличных пространствах file-per-table.

Преобразовываете ли Вы MyISAM непосредственно или создаете клонированную таблицу InnoDB, удостоверьтесь, что у Вас есть достаточное дисковое пространство, чтобы хранить старые и новые таблицы во время процесса. Таблицы InnoDB требуют большего количества дискового пространства, чем MyISAM. Если ALTER TABLE исчерпывает пространство, она запускает откат, а это может занять часы. Для вставок InnoDB использует буфер вставки, чтобы слить вторичные индексные записи в пакетах. Это сохраняет много дискового ввода/вывода. Для отмены не используется такой механизм, и отмена может занять в 30 раз дольше, чем вставка.

В случае безудержной отмены, если у Вас нет ценных данных в Вашей базе данных, может быть желательно уничтожить процесс базы данных, а не ждать миллионов дисковых операций ввода/вывода. Для полной процедуры см. раздел 16.20.2.

Тщательно выберите PRIMARY KEY для каждой таблицы

PRIMARY KEY это критический фактор, затрагивающий исполнение запросов MySQL и использование пространства для таблиц и индексов. У каждой строки в таблице должно быть значение первичного ключа, но ни у каких двух строк не может быть того же самого значения первичного ключа.

Вот направляющие идеи для первичного ключа, сопровождаемые более подробными объяснениями.

  • Объявите PRIMARY KEY для каждой таблицы. Как правило, это самый важный столбец, к которому Вы обращаетесь в WHERE, ища единственную строку.

  • Объявите PRIMARY KEY в CREATE TABLE вместо того, чтобы добавить это позже через ALTER TABLE.
  • Выберите столбец и его тип данных тщательно. Предпочтите числовые столбцы символьным или строкам.
  • Рассмотрите использование столбца auto-increment, если нет другого устойчивого, уникального, ненулевого, числового столбца, чтобы использовать.
  • Столбец auto-increment также хороший выбор, если есть сомнение, могло ли значение столбца первичного ключа когда-либо изменяться. Изменение значения столбца первичного ключа является дорогой работой, возможно вовлекая реконструкцию данных в пределах таблицы и в пределах каждого вторичного индекса.

Рассмотрите добавление primary key к любой таблице, у которой его еще нет. Используйте самый маленький практический числовой тип, основанный на максимальном спроектированном размере таблицы. Это может сделать каждую строку немного более компактной, что может привести к существенной экономии места для больших таблиц. Сбережения пространства умножены, если таблица имеет вторичный индекс, потому что значение первичного ключа повторено в каждом вторичном индексе. В дополнение к сокращению размера данных на диске маленький первичный ключ также позволяет большее количество совпадения данных в буферном пуле, ускоряя все виды операций и улучшая параллелизм.

Если у таблицы уже есть первичный ключ на некотором более длинном столбце, таком как VARCHAR, рассмотрите добавление нового столбца unsigned AUTO_INCREMENT и переключение первичного ключа на него, даже если на этот столбец не ссылаются в запросах. Это изменение проекта может произвести существенную экономию места во вторичном индексе. Вы можете определять прежние столбцы первичного ключа как UNIQUE NOT NULL, чтобы провести в жизнь те же самые ограничения, как PRIMARY KEY, то есть, чтобы предотвратить двойные или нулевые значения в этих столбцах.

Если Вы распространяете соответствующую информацию через много таблиц, как правило, каждая таблица использует тот же самый столбец для своего первичного ключа. Например, у базы данных персонала могло бы быть несколько таблиц, каждая с первичным ключом номера служащего. У базы данных продаж могли бы быть некоторые таблицы с первичным ключом номера заказчика и другие таблицы с первичным ключом порядкового номера. Поскольку поиски, используя первичный ключ очень быстры, Вы можете создать эффективные запросы для таких таблиц.

Если Вы не используете PRIMARY KEY, MySQL создает невидимый. Это 6-байтовое значение, которое могло бы быть более длинным, чем надо, таким образом тратя впустую место. Поскольку это скрыто, Вы не можете обратиться к этому в запросах.

Соображения потребительских свойств

Дополнительная надежность и особенности масштабируемости InnoDB действительно потребуют большего количества дискового места, чем эквивалентные таблицы MyISAM. Вы могли бы изменить столбец и определения индекса для лучшего использования пространства, уменьшенного ввода/вывода и потребления памяти, обрабатывая наборы результатов, и лучших планов оптимизации запроса, делающих эффективное использование поисков по индексу.

Если Вы действительно настраиваете числовой столбец ID для первичного ключа, используйте это значение, чтобы перекрестно сослаться со связанными значениями в любых других таблицах, особенно для запросов join. Например, вместо того, чтобы принять название страны как входное значение и сделать запросы, ищущие то же самое имя, сделайте один поиск, чтобы определить ID страны, затем сделайте другие запросы (или единственный запрос), чтобы искать релевантную информацию в нескольких таблицах. Вместо того, чтобы хранить клиента или номер изделия по каталогу как строку цифр, потенциально израсходовав несколько байтов, преобразуйте это в числовой ID для хранения и запросов. 4 байтный столбец INT может индексировать более чем 4 миллиарда элементов. Для диапазонов различных типов целого числа см. раздел 12.2.1.

Файлы, связанные с таблицами InnoDB

Файлы InnoDB требуют большей заботы, чем MyISAM:

  • Вы не должны удалить файлы ibdata, которые представляют системное табличное пространство.

  • Копирование таблицы от одного сервера на другой требует FLUSH TABLES ... FOR EXPORT и копирования table_name.cfg файла наряду с table_name.ibd.

16.8.5. Обработка AUTO_INCREMENT в InnoDB

InnoDB обеспечивает конфигурируемый механизм блокировки, который может значительно улучшить масштабируемость и исполнение запросов SQL, которые добавляют строки к таблицам со столбцами AUTO_INCREMENT. Чтобы использовать механизм AUTO_INCREMENT с таблицей InnoDB, столбец AUTO_INCREMENT должен быть определен как часть индексирования таким образом, что возможно выполнить эквивалент индексированного поиска SELECT MAX(ai_col) на таблице, чтобы получить максимальное значение столбца. Как правило, это достигнуто, делая столбец, который индексирует первый столбец некоторой таблицы.

Этот раздел описывает поведение режимов блокировки AUTO_INCREMENT, значения использования для различных настроек режима блокировки AUTO_INCREMENT и как InnoDB инициализирует счетчик AUTO_INCREMENT.

Режимы блокировки AUTO_INCREMENT

Этот раздел описывает поведение режимов блокировки AUTO_INCREMENT, и как каждый режим блокировки затрагивает репликацию. Режимы блокировки сконфигурированы при запуске, используя innodb_autoinc_lock_mode.

Следующие термины использованы в описании innodb_autoinc_lock_mode:

  • INSERT-подобные запросы

    Все запросы, которые производят новые строки в таблице, включая INSERT, INSERT ... SELECT, REPLACE, REPLACE ... SELECT и LOAD DATA. Включает простые вставки, bulk-вставки и смешанные вставки.

  • Простые вставки

    Запросы, для которых число строк, которые будут вставлены, может быть определено заранее (когда запрос первоначально обработано). Это включает однострочные и многострочные INSERT и REPLACE, у которых нет вложенного подзапроса, но не INSERT ... ON DUPLICATE KEY UPDATE.

  • Bulk-вставки

    Запросы, которыми число строк, которые будут вставлены (и число необходимых значений auto-increment) не известно заранее. Это включает INSERT ... SELECT, REPLACE ... SELECT и LOAD DATA, но не простой INSERT. InnoDB назначает новые значения для столбца AUTO_INCREMENT по одному по мере того, как каждая строка обработана.

  • Смешанные вставки

    Это простые вставки, которые определяют значение auto-increment для некоторых (но не всех) новых строк. Пример следует, где c1 столбец AUTO_INCREMENT таблицы t1:

    INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (5,'c'), (NULL,'d');
    

    Другой тип смешанных вставок: INSERT ... ON DUPLICATE KEY UPDATE, который в худшем случае является в действительности INSERT сопровождаемый UPDATE, где выделенное значение для столбца AUTO_INCREMENT может или не может использоваться во время фазы обновления.

Есть три возможных настройки для innodb_autoinc_lock_mode. Это 0, 1 или 2, соответственно для режимов traditional, consecutive или interleaved.

  • innodb_autoinc_lock_mode = 0 (режим traditional).

    Традиционный режим блокировки обеспечивает то же самое поведение, которое существовало перед тем, как параметр конфигурации innodb_autoinc_lock_mode был введен в MySQL 5.1. Традиционная возможность режима блокировки предоставлена для обратной совместимости, исполнительного тестирования и обхода проблем со смешанным режимом вставки из-за возможных различий в семантике.

    В этом режиме блокировки все INSERT-подобные запросы, получают специальную блокировку AUTO-INC на уровне таблицы для вставок в таблицы со столбцом AUTO_INCREMENT. Эта блокировка остается до конца запроса (не до конца транзакции) и гарантирует, что значения auto-increment назначены в предсказуемом и повторимом порядке на данную последовательность запросов INSERT, при этом гарантируя, что значения автоинкремента, назначенные любым данным запросом, последовательны.

    В случае основанной на запросе репликации это означает, что, когда запрос SQL копируется на ведомом сервере, те же самые значения используются для столбца auto-increment на главном сервере. Результат выполнения многократных INSERT детерминирован, и ведомое устройство воспроизводит те же самые данные, как на ведущем устройстве. Если значения auto-increment, произведенные многократным INSERT, были чередованы, результатом будут два параллельных запроса INSERT, которые недетерминированы, и не могут быть достоверно размножены к ведомому серверу, используя основанную на запросе репликацию.

    Чтобы ясно понять это, рассмотрите пример, который использует эту таблицу:

    CREATE TABLE t1 (c1 INT(11) NOT NULL AUTO_INCREMENT,
                     c2 VARCHAR(10) DEFAULT NULL,
                     PRIMARY KEY (c1)) ENGINE=InnoDB;
    

    Предположите, что есть две операции, каждая вставляет строки в таблицу со столбцом AUTO_INCREMENT. Одна транзакция использует INSERT ... SELECT, который вставляет 1000 строк, другая использует простой INSERT, который вставляет одну строку:

    Tx1: INSERT INTO t1 (c2) SELECT 1000 rows from another table ...
    Tx2: INSERT INTO t1 (c2) VALUES ('xxx');
    

    InnoDB не может сказать заранее, сколько строк будет получено от SELECT в запросе INSERT в Tx1, и это назначает значения auto-increment по одному, в то время как запрос продолжается. С блокировкой на уровне таблицы, проводимой до конца запроса, только один INSERT, относящийся к таблице t1, можно выполнить за один раз, и генерация чисел auto-increment различными запросами не чередована. Значение, произведенное для Tx1 запросом INSERT ... SELECT , будет последовательно, и (единственное) значение, используемое INSERT в Tx2, будет меньше или больше, чем все используемые для Tx1, в зависимости от того, который запрос выполняется сначала.

    Пока запросы SQL выполняют в том же самом порядке, когда повторяют из двоичного журнала (используя основанную на запросе репликацию или в скриптах восстановления), результатами будет то же самое, как было, когда Tx1 и Tx2 сначала работали. Таким образом, блокировки на уровне таблицы, проводимые до конца запроса, делают запросы INSERT, использующие auto-increment, безопасными для использования с основанной на запросе репликацией. Однако, те блокировки на уровне таблицы ограничивают параллелизм и масштабируемость, когда многократные транзакции выполняют вставки в то же самое время.

    В предыдущем примере, если не было никакой блокировки на уровне таблицы, значения столбца auto-increment, используемого для INSERT в Tx2, зависит от того, когда запрос выполняется. Если INSERT в Tx2 выполняется в то время, как INSERT в Tx1 работает (а не прежде, чем он запустится или после того, как он завершается), определенные значения auto-increment, назначенные двумя INSERT недетерминированы, и могут измениться.

    В режиме последовательной блокировки InnoDB может избегать использования на уровне таблицы блокировок AUTO-INC для простых вставок, где число строк известно заранее, и все еще сохраняет детерминированное выполнение и безопасность для основанной на запросе репликации.

    Если Вы не используете двоичный журнал, чтобы переиграть запросы SQL как часть восстановления или репликации, может использоваться режим блокировки interleaved , чтобы устранить все использование на уровне таблицы блокировки AUTO-INC для еще большего параллелизма и работы, за счет разрешения промежутков в числах auto-increment, назначенных запросом и потенциально назначением чисел, одновременно выполняемых запросов.

  • innodb_autoinc_lock_mode = 1 (режим блокировки consecutive)

    Это режим блокировки значения по умолчанию. В этом режиме bulk-вставки используют специальную блокировку AUTO-INC на уровне таблицы и держат это до конца запроса. Это относится ко всем запросам INSERT ... SELECT, REPLACE ... SELECT и LOAD DATA. Только одно запрос, держащий AUTO-INC, может выполниться за один раз.

    Простые вставки (число строк, которые будут вставлены, известно заранее) избегают на уровне таблицы блокировки AUTO-INC, получая необходимое число auto-increment под управлением mutex (легкая блокировка), который проводится только во время процесса распределения, а не до тех пор, когда запрос завершится. На уровне таблицы блокировка AUTO-INC не применяется, если AUTO-INC проводится другой транзакцией. Если другая транзакция держит AUTO-INC простая вставка ждет AUTO-INC, как будто это была bulk-вставка.

    Этот режим блокировки гарантирует, что в запросе INSERT, где число строк не известно заранее (и где числа auto-increment назначены в ходе продвижения запроса), все значения auto-increment, назначенные любым INSERT-подобным запросом, последовательны, и операции безопасны для основанной на запросе репликации.

    Проще говоря, этот режим блокировки значительно улучшает масштабируемость, будучи безопасным для использования с основанной на запросе репликацией. Далее, как с режимом блокировки traditional, числа auto-increment, назначенные любым данным запросом, последовательны. Нет никакого изменения в семантике по сравнению с режимом traditional ни для какого запроса, с одним важным исключением (ну а как же без него!).

    Исключение для смешанного режима вставки, где пользователь обеспечивает явные значения столбца AUTO_INCREMENT для некоторых, но не всех, строк в многострочной простой вставке. Для таких вставок InnoDB выделяет больше значений auto-increment, чем число строк, которые будут вставлены. Однако, все значения, автоматически назначенные, последовательно произведены (и таким образом выше) значения auto-increment, произведенного последний раз выполненным предыдущим запросом.

  • innodb_autoinc_lock_mode = 2 (режим блокировки interleaved)

    В этом режиме блокировки никакие INSERT-подобные запросы не используют на уровне таблицы блокировку AUTO-INC, и многократные запросы могут выполняться в то же самое время. Это является самым быстрым и масштабируемым режимом блокировки, но не безопасно, используя основанную на запросе репликацию или скрипты восстановления, когда запросы SQL переигрываются из двоичного журнала.

    В этом режиме блокировки значения auto-increment точно будут уникальны и монотонно увеличивающимися через все одновременно выполняющиеся INSERT-подобные запросы. Однако, потому что многократные запросы могут производить числа в то же самое время (то есть, распределение чисел interleaved), значения, произведенные для строк, вставленных любым данным запросом, возможно, не последовательны.

    Если единственное выполнение запросов простая вставка , где число строк, которые будут вставлены, известно заранее, не будет никаких промежутков в числах, произведенных для единственного запроса, за исключением смешанного режима вставок. Однако, когда bulk-вставки выполнены, могут быть промежутки в значениях, назначенных любым данным запросом.

Значения использования режима блокировки AUTO_INCREMENT

  • Применение auto-increment с репликацией.

    Если Вы используете основанную на запросе репликацию, установите innodb_autoinc_lock_mode в 0 или 1 и используйте то же самое значение на ведущем устройстве и его ведомых устройствах. Значения не будут теми же самыми на ведомых устройствах, как на ведущем устройстве, если Вы используете innodb_autoinc_lock_mode = 2 (interleaved) или конфигурации, где ведущее устройство и ведомые устройства не используют тот же самый режим блокировки.

    Если Вы используете репликацию, основанную на строке или смешанного формата, все режимы блокировки безопасны, так как основанная на строке репликация не чувствителен к порядку выполнения запросов SQL (и смешанный формат использует основанную на строке репликацию для любых запросов, которые опасны для основанной на запросе репликации).

  • Потерянные значения auto-increment и промежутки последовательности.

    Во всех режимах блокировки (0, 1 и 2), если транзакция, которая произвела значения, откатывается, те значения потеряны. Как только значение произведено для столбца, оно не может быть отменено до прежнего уровня, действительно ли выполнен INSERT-подобный запрос или отменен. Такие потерянные значения снова не использованы. Таким образом, могут быть промежутки в значениях, сохраненных в столбце AUTO_INCREMENT таблицы.

  • Определение NULL или 0 для столбца AUTO_INCREMENT.

    Во всех режимах блокировки (0, 1 и 2), если пользователь определяет NULL или 0 для столбца AUTO_INCREMENT в INSERT, InnoDB обрабатывает строку, как будто значение не было определено и производит новое значение для нее.

  • Назначение отрицательной величины столбцу AUTO_INCREMENT.

    Во всех режимах блокировки (0, 1 и 2) не определено поведение механизма auto-increment, если Вы назначаете отрицательную величину столбцу AUTO_INCREMENT.

  • Если значение AUTO_INCREMENT становится больше, чем максимальное целое число для указанного типа целого числа.

    Во всех режимах блокировки (0, 1 и 2) не определено поведение механизма auto-increment, если значение становится больше, чем максимальное целое число, которое может быть сохранено в указанном типе целого числа.

  • Промежутки в значениях для bulk-вставок.

    С опцией innodb_autoinc_lock_mode в значении 0 (traditional ) или 1 (consecutive) значения auto-increment, произведенные любым данным запросом, последовательны без промежутков, потому что на уровне таблицы блокировка AUTO-INC проводится до конца запроса, и только один такой запрос может выполниться за один раз.

    С опцией innodb_autoinc_lock_mode в значении 2 (interleaved ), могут быть промежутки в значениях, произведенных bulk-вставками, но только если там одновременно выполняются INSERT-подобные запросы.

    Для режимов блокировки 1 или 2 промежутки могут произойти между последовательными запросами, потому что для bulk-вставок точное число значений auto-increment, требуемых каждым запросм, возможно, не известно заранее, и переоценка возможна.

  • Значения Auto-increment, назначенные смешанным режимом вставок.

    Полагайте, что смешанный режим, определяет значение auto-increment для некоторых (но не всех) получающихся строк. Такой запрос ведет себя по-другому в режимах блокировки 0, 1 и 2. Например, предположим, что столбец c1 AUTO_INCREMENT в таблице t1, и что новый автоматически произведенный порядковый номер 100.

    mysql> CREATE TABLE t1 (
        ->        c1 INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
        ->        c2 CHAR(1)) ENGINE = INNODB;
    mysql> INSERT INTO t1 VALUES(1,'a'),(101,'b'),(5,'c'),(102,'d');
    

    Теперь считайте следующее смешанным режимом вставки:

    mysql> INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'), (5,'c'),
                     (NULL,'d');
    

    Если innodb_autoinc_lock_mode = 0 (traditional ), четыре новых строки:

    mysql> SELECT c1, c2 FROM t1 ORDER BY c2;
    +-----+----+
    | c1  | c2 |
    +-----+----+
    |   1 | a  |
    | 101 | b  |
    |   5 | c  |
    | 102 | d  |
    +-----+----+
    

    Следующее доступное значение 103, потому что значения автоинкремента выделены по одному, а не все в начале выполнения запроса. Этот результат верен при выполнении одновременно INSERT-подобных запросов (любого типа).

    Если innodb_autoinc_lock_mode = 1 (consecutive ), четыре новых строки также:

    mysql> SELECT c1, c2 FROM t1 ORDER BY c2;
    +-----+----+
    | c1  | c2 |
    +-----+----+
    |   1 | a  |
    | 101 | b  |
    |   5 | c  |
    | 102 | d  |
    +-----+----+
    

    Однако, в этом случае, следующее доступное значение 105, не 103, потому что четыре значения выделены в то время, когда запрос обработан, но только два используются. Этот результат верен при выполнении одновременно INSERT-подобных запросов (любого типа).

    Если innodb_autoinc_lock_mode = 2 (interleaved ), четыре новых строки:

    mysql> SELECT c1, c2 FROM t1 ORDER BY c2;
    +----+----+
    | c1 | c2 |
    +----+----+
    | 1  | a  |
    | x | b  |
    | 5  | c  |
    | y | d  |
    +----+----+
    

    Значения x и y уникальны и больше, чем любые ранее произведенные строки. Однако, определенные значения x и y зависят от числа значений auto-increment, произведенных одновременно выполняемыми запросами.

    Наконец, рассмотрите следующий запрос, сделанный, когда последний раз произведенный порядковый номер был значением 4:

    mysql> INSERT INTO t1 (c1,c2) VALUES (1,'a'), (NULL,'b'),
                     (5,'c'), (NULL,'d');
    

    При любом значении innodb_autoinc_lock_mode этот запрос производит ошибку дублирования ключа 23000 (Can't write; duplicate key in table) потому, что 5 выделено для строки (NULL, 'b') и вставка строки (5, 'c') терпит неудачу.

  • Изменение значения столбцов AUTO_INCREMENT в середине последовательности INSERT.

    В MySQL 5.7 и ранее изменение значения столбца AUTO_INCREMENT в середине последовательности INSERT могло привести к ошибке Duplicate entry. Например, если Вы запускали UPDATE, которая изменила столбец AUTO_INCREMENT к значению, большему, чем текущий максимум, последующий INSERT, который не определял неиспользованное значение auto-increment, мог столкнуться с ошибкой Duplicate entry. В MySQL 8.0 и позже, если Вы изменяете столбец AUTO_INCREMENT к значению, больше, чем текущее максимальное значение auto-increment, новое значение сохранено, и последующие INSERT выделяют значения, начиная с нового, большего значения. Это поведение продемонстрировано в следующем примере.

    mysql> CREATE TABLE t1 (
        ->        c1 INT NOT NULL AUTO_INCREMENT,
        ->        PRIMARY KEY (c1)) ENGINE = InnoDB;
    
    mysql> INSERT INTO t1 VALUES(0), (0), (3);
    mysql> SELECT c1 FROM t1;
    +----+
    | c1 |
    +----+
    |  1 |
    |  2 |
    |  3 |
    +----+
    
    mysql> UPDATE t1 SET c1 = 4 WHERE c1 = 1;
    mysql> SELECT c1 FROM t1;
    +----+
    | c1 |
    +----+
    |  2 |
    |  3 |
    |  4 |
    +----+
    
    mysql> INSERT INTO t1 VALUES(0);
    mysql> SELECT c1 FROM t1;
    +----+
    | c1 |
    +----+
    |  2 |
    |  3 |
    |  4 |
    |  5 |
    +----+
    

Инициализация счетчика InnoDB AUTO_INCREMENT

Этот раздел описывает как InnoDB инициализирует счетчики AUTO_INCREMENT.

Если Вы определяете столбец AUTO_INCREMENT для таблица, табличный объект в памяти содержит специальный счетчик, названный счетчиком auto-increment, который используется, назначая новые значения для столбца.

В MySQL 5.7 и ранее счетчик автоинкремента сохранен только в основной памяти, не на диске. Инициализируя счетчик автоинкремента после перезапуска сервера, InnoDB выполнил бы эквивалент следующего запроса о первой вставке в таблицу, содержащую столбец AUTO_INCREMENT.

SELECT MAX(ai_col) FROM table_name FOR UPDATE;

В MySQL 8.0 это не так. Текущее максимальное значение счетчика написано в журнал redo каждый раз, когда это изменяется и сохранено в приватной системной таблице механизма на каждой контрольной точке. Эти изменения делают текущее максимальное значение счетчика постоянным через перезапуски сервера.

При перезапуске сервера после нормального завершения работы InnoDB инициализирует счетчик в памяти с использованием текущего максимального значения, сохраненного в системной таблице словаря данных.

При перезапуске во время восстановления катастрофического отказа InnoDB инициализирует счетчик в памяти с использованием текущего максимального значения, сохраненного в системной таблице словаря данных, и просматривает журнал redo для значений счетчика, записанных, начиная с последней контрольной точки. Если зарегистрированное значение больше, чем встречное значение в памяти, зарегистрированное значение применено. Однако, в случае катастрофического отказа сервера, повторное использование ранее выделенного значения не может быть гарантировано. Каждый раз, когда текущее максимальное значение изменено из-за INSERT или UPDATE, новое значение записано в журнал, но если катастрофический отказ происходит прежде, чем журнал сброшен на диск, ранее выделенное значение могло быть снова использовано, когда счетчик инициализирован после того, как сервер перезапущен.

Единственное обстоятельство, когда InnoDB использует эквивалент SELECT MAX(ai_col) FROM table_name FOR UPDATE в MySQL 8.0, это инициализируя счетчик, импортируя табличное пространство без файла метаданных .cfg. Иначе текущее максимальное значение счетчика считано из файла метаданных .cfg.

В MySQL 5.7 и ранее, перезапуск сервера отменяет эффект опции AUTO_INCREMENT = N, которая может использоваться в CREATE TABLE или ALTER TABLE, чтобы установить начальное значение или изменить существующее значение, соответственно. В MySQL 8.0 перезапуск сервера не отменяет эффект AUTO_INCREMENT=N . Если Вы инициализируете автоинкремент в противоречии с определенным значением, или если Вы изменяете счетчик к большему значению, новое значение сохранено через перезапуски сервера.

ALTER TABLE ... AUTO_INCREMENT = N может изменить счетчик только к значению больше, чем текущий максимум.

В MySQL 5.7 и ранее перезапуск сервера немедленно после a ROLLBACK мог привести к повторному использованию значений автоинкремента, которые были ранее выделены отмененной транзакции, эффективно понижая текущее максимальное значение автоинкремента до прежнего уровня. В MySQL 8.0, текущее максимальное значение сохранено, предотвращая повторное использование ранее выделенных значений.

Если SHOW TABLE STATUS исследует таблицу прежде, чем счетчик будет инициализирован, InnoDB открывает таблицу и инициализирует значение, используя текущее максимальное значение автоинкремента, которое сохранено в системной таблице словаря данных. Значение сохранено в памяти для использования позже. Инициализация встречного значения использует нормальное исключительно блокирующее чтение на таблице, которое длится до конца транзакции. InnoDB следует за той же самой процедурой, инициализируя счетчик автоинкремента для недавно составленной таблицы, у которой есть определенное пользователем значение, которое больше 0.

После того, как счетчик инициализирован, если Вы явно не определяете значение автоинкремента, вставляя строку, InnoDB неявно постепенно увеличивает счетчик и назначает новое значение столбцу. Если Вы вставляете строку, которая явно определяет значение столбца auto-increment, и значение больше, чем текущее максимальное значение, счетчик установлен в указанное значение.

InnoDB использует счетчик auto-increment в памяти пока выполняется сервер. Когда сервер остановлен и перезапущен, InnoDB повторно инициализирует счетчик, как описано ранее.

Опция auto_increment_offset определяет начальную точку для значения AUTO_INCREMENT. Настройка по умолчанию 1.

Опция auto_increment_increment управляет интервалом между последовательными значениями столбцов. Настройка по умолчанию 1.

16.8.6. InnoDB и ограничения FOREIGN KEY

Этот раздел описывает различия в обработке механизма хранения InnoDB внешних ключей по сравнению с MySQL Server.

Для информации об использовании внешнего ключа и примеров см. раздел 14.1.15.3.

Определения внешнего ключа

Определения внешнего ключа для InnoDB таблицы подвергаются следующим условиям:

  • InnoDB разрешает внешнему ключу ссылаться на любой индексный столбец или группу столбцов. Однако, в таблице, на которую ссылаются, должно быть индексирование, где столбцы, на которые ссылаются, перечислены как первые столбцы в том же самом порядке.

  • InnoDB в настоящее время не поддерживает внешние ключи для таблиц с определяемым пользователем разделением. Это означает что не разделенная пользователем таблица может содержать ссылки внешнего ключа или столбцы, на которые ссылаются внешние ключи.
  • InnoDB позволяет ограничению внешнего ключа ссылаться на групповой ключ. Это расширение InnoDB стандартного SQL.

Ссылочные действия

Ссылочные действия для внешних ключей таблицы InnoDB подвергаются следующим условиям:

  • В то время, как SET DEFAULT позволен MySQL Server, это отклонено как недопустимое InnoDB. CREATE TABLE и ALTER TABLE, использующие этот пункт, не позволены на таблицах InnoDB.

  • Если есть несколько строк в родительской таблице, у которых есть то же самое значение ключа, на которое ссылаются, InnoDB во внешнем ключе проверяет, как будто другие родительские строки с тем же самым значением ключа не существуют. Например, если Вы определили ограничение RESTRICT и есть дочерняя строка с несколькими родительскими строками, InnoDB не разрешает удаление любой из тех родительских строк.
  • InnoDB выполняет располагающиеся каскадом операции через алгоритм depth-first, основанный на записях в индексах, соответствующих ограничениям внешнего ключа.
  • Если ON UPDATE CASCADE или ON UPDATE SET NULL рекурсивны, чтобы обновить ту же самую таблицу, которую это ранее обновило во время каскада, это действует как RESTRICT. Это означает, что Вы не можете использовать самоссылочные операции ON UPDATE CASCADE или ON UPDATE SET NULL. Это должно предотвратить бесконечные петли, следующие из каскадных обновлений. Самоссылочная ON DELETE SET NULL, с другой стороны, возможна, как самоссылочная ON DELETE CASCADE. Расположение каскадом операций не может быть вложено больше, чем на 15 уровней.
  • Как MySQL вообще, в запросе SQL который вставляет, удаляет или обновляет много строк, InnoDB проверяет ограничения UNIQUE и FOREIGN KEY построчно. Выполняя проверки внешнего ключа, InnoDB ставит совместно используемые блокировки на уровне строки на дочерних или родительских записях, на которые это должно смотреть. InnoDB проверяет ограничения внешнего ключа немедленно, проверка не задержана до закрытия транзакции. Согласно стандарту SQL, поведение значения по умолчанию должно быть задержано, проверяя. Таким образом, ограничения проверены только после того, как весь запрос SQL было обработан. Пока InnoDB задерживает проверку ограничения, некоторые вещи невозможны, например, удаление записи, которая обращается к себе, используя внешний ключ.

Ограничения внешнего ключа для произведенных столбцов и виртуальных индексов

  • Ограничение внешнего ключа на произведенный сохраненный столбец не может использовать ON UPDATE CASCADE, ON DELETE SET NULL, ON UPDATE SET NULL, ON DELETE SET DEFAULT или ON UPDATE SET DEFAULT.

  • Ограничение внешнего ключа не может сослаться на произведенный виртуальный столбец.
  • До MySQL 8.0.1 ограничение внешнего ключа не может сослаться на вторичный индекс, определенный на произведенном виртуальном столбце.

Использование внешнего ключа и информация об ошибке

Вы можете получить общую информацию о внешних ключах и их использовании, запрашивая таблицу INFORMATION_SCHEMA.KEY_COLUMN_USAGE, больше информации, более определенной для таблиц InnoDB, может быть найдено в таблицах INNODB_SYS_FOREIGN и INNODB_SYS_FOREIGN_COLS базы данных INFORMATION_SCHEMA.

В дополнение к SHOW ERRORS, в случае ошибочного вовлечения внешнего ключа таблицами InnoDB (обычно Error 150 в MySQL Server), Вы можете получить подробное объяснение ошибки внешнего ключа, проверяя вывод SHOW ENGINE INNODB STATUS.

16.8.7. Пределы на таблицах InnoDB

Это не хорошая идея сконфигурировать InnoDB, чтобы использовать файлы с данными или файлы системного журнала на томах NFS. Файлы могли бы быть заблокированы другими процессами и становиться недоступными к использованию MySQL.

Максимумы и минимумы

  • Таблица может содержать максимум 1017 столбцов. Виртуальные произведенные столбцы включены в этот предел.

  • Таблица может содержать максимум 64 вторичных индекса.
  • Предел длины префикса ключа 3072 байт для таблиц с форматом строк DYNAMIC или COMPRESSED .

    Предел длины префикса ключа 767 байт для таблиц с форматом строк REDUNDANT или COMPACT. Например, Вы могли бы упереться в этот лимит с префиксом столбца индекса больше, чем 191 символ на столбцах TEXT или VARCHAR , принимая набор символов utf8mb4 и максимум 4 байта для каждого символа.

    Попытка использовать длину префикса ключа, которая превышает предел, возвращает ошибку.

    Пределы, которые применяются, чтобы индексировать ключевые префиксы, также относятся к индексным ключам полного столбца.

  • Если Вы уменьшаете размер страницы до 8KB или 4KB, определяя innodb_page_size, создавая сервер MySQL, максимальная длина индексного ключа понижена пропорционально, основываясь на пределе 3072 байта для размера страницы 16 КБ. Таким образом, максимум длины ключа 1536 байтов, когда размер страницы составляет 8 КБ, и 768 байтов, когда размер страницы составляет 4 КБ.
  • Максимум 16 столбцов разрешено для столбцового индекса. Превышение предела возвращает ошибку.
    ERROR 1070 (42000): Too many key parts specified; max 16 parts allowed
    
  • Максимальная длина строки, за исключением столбцов переменной длины (VARBINARY, VARCHAR, BLOB и TEXT), немного меньше, чем половина страницы для размеров страницы 4 КБ, 8 КБ, 16 КБ и 32 КБ. Например, максимальная длина строки для значения по умолчанию innodb_page_size 16KB составляет около 8000 байт. Для размер страницы 64 КБ максимальная длина строки составляет приблизительно 16000 байт. Столбцы LONGBLOB и LONGTEXT должны быть меньше 4 ГБ, и суммарная длина строки, включая столбцы BLOB и TEXT, должна быть меньше 4GB.

    Если строка меньше чем половина страницы длиной, все это сохранено в местном масштабе в пределах страницы. Если это превышает половину страницы, столбцы переменной длины выбраны для внешнего хранения вне страницы, как описано в разделе 16.11.2.

  • Хотя InnoDB допускает размеры строки больше 65535 байтов внутренне, сам MySQL налагает предел размера строки 65 535 для объединенного размера всех столбцов:
    mysql> CREATE TABLE t (a VARCHAR(8000), b VARCHAR(10000),
        ->        c VARCHAR(10000), d VARCHAR(10000), e VARCHAR(10000),
        ->        f VARCHAR(10000), g VARCHAR(10000)) ENGINE=InnoDB;
    ERROR 1118 (42000): Row size too large. The maximum row size for the
    used table type, not counting BLOBs, is 65535. You have to change some
    columns to TEXT or BLOBs
    

    См. раздел C.10.4.

  • На некоторых старых операционных системах файлы должны быть меньше 2GB. Это не ограничение InnoDB непосредственно, но если Вы требуете большого табличного пространства, конфигурируйте это, используя несколько меньших файлов с данными, а не один большой.
  • Объединенный размер файлов системного журнала может быть до 512 ГБ.
  • Минимальный размер табличного пространства немного больше 10MB. Максимальный размер табличного пространства составляет четыре миллиарда страниц (64TB). Это также максимальный размер для таблицы.
  • Размер страницы по умолчанию в InnoDB 16 КБ. Вы можете увеличить или уменьшить размер страницы, конфигурируя опцию innodb_page_size при установке MySQL.

    Размеры страницы 32KB и 64KB поддержаны, но ROW_FORMAT=COMPRESSED не поддержан для размеров страницы больше 16 КБ. Для размеров страницы 32 КБ и 64 КБ максимальный размер записи составляет 16 КБ. Для innodb_page_size=32k размер экстента 2MB. Для innodb_page_size=64k размер экстента 4MB.

    MySQL, используя некий размер страницы не может использовать файлы с данными или файлы системного журнала от экземпляра, который использует иной размер страницы.

Ограничения на таблицы InnoDB

  • ANALYZE TABLE определяет количество элементов индекса (как выведено на экран в столбце Cardinality вывода SHOW INDEX ), делая случайные погружения к каждому из индексных деревьев и обновляя индексные оценки количества элементов соответственно. Поскольку это только оценки, повторные выполнения ANALYZE TABLE могут произвести различные числа. Это делает ANALYZE TABLE быстрым на InnoDB, но не 100% точным, потому что это не принимает все строки во внимание.

    Вы можете сделать сбор статистики ANALYZE TABLE более точным и устойчивым, включая опцию innodb_stats_persistent, как описано в разделе 16.6.10.1. Когда эта установка включена, важно выполнить ANALYZE TABLE после существенных изменений индексированных данных в столбце, потому что статистические данные не вычисляются повторно периодически (как после перезапуска сервера).

    Вы можете изменить число случайных погружений, изменяя переменную innodb_stats_persistent_sample_pages (если постоянная установка статистики включена) или innodb_stats_transient_sample_pages (если постоянная установка статистики выключена).

    MySQL использует оценки количества элементов только в оптимизации соединения. Если некоторое соединение не оптимизировано правильным способом, Вы можете попытаться использовать ANALYZE TABLE. В немногих случаях это ANALYZE TABLE не производит значения, достаточно хорошие для Ваших особых таблиц, Вы можете использовать FORCE INDEX с Вашими запросами, чтобы вызвать использование индекса или установить max_seeks_for_key , чтобы гарантировать, что MySQL предпочитает, индексные поиски сканированию таблицы. См. разделы 6.1.5 и B.5.5.

  • Если запрос или транзакции работают на таблице и ANALYZE TABLE выполнен на той же самой таблице, сопровождаемый вторым ANALYZE TABLE, второй вызов ANALYZE TABLE заблокирован, пока запрос или транзакции не завершены. Это поведение происходит потому, что ANALYZE TABLE отмечает в настоящее время загружаемое табличное определение как устаревшее, когда ANALYZE TABLE закончен. Новые запросы или транзакции (включая второй ANALYZE TABLE) должен загрузить новое табличное определение в табличный кэш, что не может произойти, пока в настоящее время рабочие запросы или транзакции не завершены, и старое табличное определение не очищено. Загрузка многократных параллельных табличных определений не поддержана.
  • SHOW TABLE STATUS не дает точную статистику по таблицам InnoDB, за исключением физического места, зарезервированного таблицей. Количество строки только грубая оценка, используемая в оптимизации SQL.
  • InnoDB не проводит внутренний подсчет строк в таблице, потому что параллельные транзакции могли бы видеть различные числа строк в то же самое время. Следовательно, SELECT COUNT(*) FROM t считает только строки, видимые текущей транзакции.

    Чтобы выполнить SELECT COUNT(*) FROM t, InnoDB кластерный индекс, что занимает время, если записи индекса не находятся полностью в буферном пуле. Для более быстрого счета Вы можете составить таблицу счетчиков и позволить Вашему приложению обновлять ее, согласно вставкам и удалениям. Однако, этот метод, возможно, не масштабируется хорошо в ситуациях, где тысячи параллельных транзакций начинают обновления той же самой таблицы. Если приблизительное количество строки достаточно, может использоваться SHOW TABLE STATUS .

    SELECT COUNT(*) FROM t вызывает единственный вызов обработчика механизма хранения, чтобы просмотреть кластеризируемый индекс и возвращает количество строк. Эта оптимизация очевидна в выводе EXPLAIN для SELECT COUNT(*) FROM t, который сообщает Select tables optimized away:

    mysql> EXPLAIN SELECT COUNT(*) FROM t1\G
    *************************** 1. row ***************************
     id: 1
      select_type: SIMPLE
    table: NULL
       partitions: NULL
     type: NULL
    possible_keys: NULL
    key: NULL
      key_len: NULL
    ref: NULL
     rows: NULL
     filtered: NULL
    Extra: Select tables optimized away
    
  • Столбец AUTO_INCREMENT ai_col должен быть определен как часть индексирования таким образом, что возможно выполнить эквивалент индексного SELECT MAX(ai_col ) поиска на таблице, чтобы получить максимальное значение столбца. Как правило, это достигнуто, делая столбец первым столбцом индекса некоторой таблицы.
  • InnoDB устанавливает исключительную блокировку на конце индексирования, связанного со столбцом AUTO_INCREMENT, инициализируя ранее указанный столбец AUTO_INCREMENT таблицы.

    С innodb_autoinc_lock_mode=0 InnoDB использует специальный режим блокировки таблицы AUTO-INC, где блокировка получена и проведена до конца текущего запроса SQL, получая доступ к счетчику auto-increment. Другие клиенты не могут вставить в таблицу в то время, как табличная блокировка AUTO-INC проводится. То же самое поведение происходит для bulk-вставок с innodb_autoinc_lock_mode=1. На уровне таблицы блокировки AUTO-INC не используются с innodb_autoinc_lock_mode=2. Подробности в разделе 16.8.5.

  • Когда столбец целого числа AUTO_INCREMENT исчерпывает значения, последующий INSERT возвращает ошибку дубликата ключа. Это общее поведение MySQL, подобное MyISAM.
  • DELETE FROM tbl_name не восстанавливает таблицу, но вместо этого удаляет все строки поштучно.
  • Каскадные действия внешнего ключа не активируют триггеры.
  • Вы не можете составить таблицу с именем столбца, которое соответствует названию внутреннего столбца InnoDB (включая DB_ROW_ID, DB_TRX_ID, DB_ROLL_PTR, и DB_MIX_ID). Это ограничение применяется к использованию имен в любом регистре.
    mysql> CREATE TABLE t1 (c1 INT, db_row_id INT) ENGINE=INNODB;
    ERROR 1166 (42000): Incorrect column name 'db_row_id'
    

Блокировка и транзакции

  • LOCK TABLES приобретает две блокировки на каждой таблице, если innodb_table_locks=1 (значение по умолчанию). В дополнение к табличному уровню MySQL, это также приобретает табличную блокировку InnoDB. MySQL до 4.1.2 не приобретал табличную блокировку InnoDB, старое поведение может быть выбрано, устанавливая innodb_table_locks=0. Если табличная блокировка InnoDB не приобретена, LOCK TABLES завершается, даже если некоторые записи таблиц блокируются другими транзакциями.

    В MySQL 8.0 innodb_table_locks=0 не имеет никакого эффекта для таблиц, заблокированных явно с LOCK TABLES ... WRITE. Это действительно имеет эффект для таблиц, заблокированных для чтения или записи через LOCK TABLES ... WRITE неявно (например, через триггеры) или LOCK TABLES ... READ.

  • Все блокировки, проводимые транзакцией, выпущены, когда транзакция передана или прервана. Таким образом, не имеет большого смысла вызывать LOCK TABLES на таблицах InnoDB в режиме autocommit=1 потому что приобретенные табличные блокировки были бы немедленно выпущены.
  • Вы не можете заблокировать дополнительные таблицы в середине транзакции потому, что LOCK TABLES выполняет неявные COMMIT и UNLOCK TABLES.
  • Предел на изменяющие данные транзакции 96 * 1023 параллельных транзакции, которые производят записи отмены. 32 из 128 сегментов отмены назначены не-redo журналам для транзакций, которые изменяют временные таблицы и связанные объекты. Это означает, что максимальное количество параллельных изменяющих данные транзакций составляет 96K. Предел 96K предполагает, что транзакции не изменяют временные таблицы. Если все изменяющие данные транзакции также изменяют временные таблицы, предел составляет 32K параллельных транзакций.

16.8.8. Кластеризируемый и вторичный индексы

У каждой таблицы InnoDB есть специальный кластеризируемый индекс, где данные для строк хранятся. Как правило, кластеризируемый индекс синонимичен с первичным ключом. Чтобы получить лучшую работу от запросов, вставок и других операций базы данных, Вы должны понять, как использовать кластеризируемый индекс, чтобы оптимизировать наиболее распространенный поиск и операции DML для каждой таблицы.

  • Когда Вы определяете PRIMARY KEY на Вашей таблице, InnoDB использует это как кластеризируемый индекс. Определите первичный ключ для каждой таблицы, которую Вы составляете. Если нет никакого логического уникального и ненулевого столбца или набора столбцов, добавьте новый столбец auto-increment, значения которого заполнены автоматически.

  • Если Вы не определяете PRIMARY KEY для Вашей таблицы MySQL определяет местонахождение первого индекса UNIQUE, где все ключевые столбцы NOT NULL и использует это как кластеризируемый индекс.
  • Если таблица не имеет PRIMARY KEY или подходящий индекс UNIQUE, InnoDB внутренне производит кластеризируемый скрытый индекс на синтетическом столбце, содержащем значения идентификаторов строки. Строки упорядочены по ID, которые InnoDB назначает строкам в такой таблице. ID строки 6-байтовая область, которая увеличивается монотонно, когда новые строки вставлены. Таким образом, строки, упорядоченные ID строки, находятся физически в порядке вставки.

Как кластеризируемый индекс ускоряет запросы

Доступ к строке через кластеризируемый индекс быстр, потому что поиск приводит непосредственно к странице со всеми данными о строке. Если таблица является большой, кластеризируемый индекс часто уменьшает дисковую нагрузку ввода/вывода по сравнению с организациями хранения, которые хранят данные о строке, используя иную страницу для индексной записи. Например, MyISAM использует один файл для строк данных и другой для индексных записей.

Как вторичный индекс связан с кластеризируемым

Все индексирует кроме кластеризируемого известны как вторичные. В InnoDB каждая запись во вторичном индексе содержит столбцы первичного ключа для строки, так же как столбцы, определенные для вторичного индекса. InnoDB применяет это значение первичного ключа, чтобы искать строку в кластеризируемом индексе.

Если первичный ключ длинен, вторичные индексы используют больше пространства, таким образом, выгодно иметь короткий первичный ключ.

См. подробности в разделах 9.3.2, 9.3, 9.5 и 9.3.2.

16.8.9. Индексы InnoDB FULLTEXT

Индексы FULLTEXT создаются на основанных на тексте столбцах (CHAR, VARCHAR или TEXT), чтобы ускорить запросы и операции DML на данных в пределах тех столбцов, опуская любые слова, которые определены как stopword.

Индекс FULLTEXT может быть определен как часть CREATE TABLE или добавлен позже с использованием ALTER TABLE или CREATE INDEX.

Полнотекстовый поиск выполнен, используя MATCH() ... AGAINST. Подробности в разделе 13.9.

Проект индекса Full-Text

Индексы InnoDB FULLTEXT имеют проект инвертированного индекса. Инвертированные индексы хранят список слов, и для каждого слова, список документов, в которых появляется слово. Чтобы поддержать поиск близости, информация о положении для каждого слова также сохранена, как смещение байта.

Таблицы полнотекстового индекса

Для каждого индекса FULLTEXT ряд индексных таблиц создается, как показано в следующем примере:

CREATE TABLE opening_lines (id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY
       KEY, opening_line TEXT(500), author VARCHAR(200),
       title VARCHAR(200), FULLTEXT idx (opening_line)) ENGINE=InnoDB;

mysql> SELECT table_id, name, space from
                 INFORMATION_SCHEMA.INNODB_SYS_TABLES
                 WHERE name LIKE 'test/%';
+----------+----------------------------------------------------+-------+
| table_id | name                                               | space |
+----------+----------------------------------------------------+-------+
|  333     | test/FTS_0000000000000147_00000000000001c9_INDEX_1 |   289 |
|  334     | test/FTS_0000000000000147_00000000000001c9_INDEX_2 |   290 |
|  335     | test/FTS_0000000000000147_00000000000001c9_INDEX_3 |   291 |
|  336     | test/FTS_0000000000000147_00000000000001c9_INDEX_4 |   292 |
|  337     | test/FTS_0000000000000147_00000000000001c9_INDEX_5 |   293 |
|  338     | test/FTS_0000000000000147_00000000000001c9_INDEX_6 |   294 |
|  330     | test/FTS_0000000000000147_BEING_DELETED            |   286 |
|  331     | test/FTS_0000000000000147_BEING_DELETED_CACHE      |   287 |
|  332     | test/FTS_0000000000000147_CONFIG                   |   288 |
|  328     | test/FTS_0000000000000147_DELETED                  |   284 |
|  329     | test/FTS_0000000000000147_DELETED_CACHE            |   285 |
|  327     | test/opening_lines                                 |   283 |
+----------+----------------------------------------------------+-------+

Первые шесть таблиц представляют инвертированный индекс и упоминаются, как вспомогательные индексные таблицы. Когда поступающие документы размечены, отдельные слова (также называемые токенами) вставлены в индексные таблицы наряду с информацией о положении и связанным Document ID (DOC_ID). Слова полностью сортированы и разделены среди этих шести индексных таблиц, основываясь на весе вида набора символов первого символа слова.

Инвертированный индекс разделен на шесть вспомогательных индексных таблицы, чтобы поддержать параллельное создание индексов. По умолчанию два потока размечают, сортируют и вставляют слова и связанные данные в таблицы. Число потоков конфигурируемое с использованием опции innodb_ft_sort_pll_degree. Создавая FULLTEXT на больших таблицах, рассмотрите увеличивание числа потоков.

Имена таблиц предварительно установлены с префиксом FTS_ и постфиксом INDEX_*. Каждая таблица связана с индексированной таблицей значением в имени индексной таблицы, которое соответствует table_id индексированной таблицы. Например, table_id из test/opening_lines 327 для которого шестнадцатеричное значение 0x147. Как показано в предыдущем примере, 147 появляется в названиях индексных таблиц, которые связаны с test/opening_lines.

Значение представляющее index_id индекса FULLTEXT также появляется в именах вспомогательных индексных таблиц. Например, во вспомогательном имени таблицы test/FTS_0000000000000147_00000000000001c9_INDEX_1 это 1c9, в десятичном виде 457. Индекс определен в таблице opening_lines (idx) и может быть идентифицирован, запрашивая из таблицы INFORMATION_SCHEMA.INNODB_SYS_INDEXES его значение (457).

mysql> SELECT index_id, name, table_id, space
                 from INFORMATION_SCHEMA.INNODB_SYS_INDEXES
                 WHERE index_id=457;
+----------+------+----------+-------+
| index_id | name | table_id | space |
+----------+------+----------+-------+
|  457     | idx  |  327     |   283 |
+----------+------+----------+-------+

Индексные таблицы сохранены в их собственном табличном пространстве, если основная таблица составлена в табличном пространстве file-per-table.

Другие индексные таблицы, показанные в предыдущем примере, используются для обработки удаления и для того, чтобы сохранить внутреннее состояние индекса FULLTEXT.

  • FTS_*_DELETED и FTS_*_DELETED_CACHE: Хранят ID (DOC_ID) для документов, которые удалены, но чьи данные еще не удалены из полнотекстового индекса. FTS_*_DELETED_CACHE версия в памяти для FTS_*_DELETED.

  • FTS_*_BEING_DELETED и FTS_*_BEING_DELETED_CACHE : Хранят ID (DOC_ID) для документов, которые удалены, но чьи данные в настоящее время находятся в процессе того, чтобы быть удаленными из полнотекстового индекса. FTS_*_BEING_DELETED_CACHE версия в памяти для FTS_*_BEING_DELETED.
  • FTS_*_CONFIG: Хранит информацию о внутреннем состоянии индекса FULLTEXT. Что наиболее важно, это хранит FTS_SYNCED_DOC_ID, который идентифицирует документы, которые были разобраны и сброшены на диск. В случае восстановления катастрофического отказа значения FTS_SYNCED_DOC_ID используются, чтобы идентифицировать документы, которые не сброшены на диск, чтобы документы могли быть повторно разобраны и добавлены назад к кэшу индекса FULLTEXT. Чтобы смотреть данные в этой таблице, запросите таблицу INFORMATION_SCHEMA.INNODB_FT_CONFIG.

Кэш полнотекстового индекса

Когда документ вставлен, он размечен, и отдельные слова и связанные данные вставлены в таблицу, чтобы рассмотреть размеченные данные для недавно вставленных строк. Этот процесс, даже для маленьких документов, мог привести к многочисленным небольшим вставкам во вспомогательные таблицы, делая параллельный доступ к этим таблицам предметом спора. Чтобы избежать этой проблемы, InnoDB использует кэш индекса FULLTEXT, чтобы временно кэшировать табличные вставки для недавно вставленных строк. Эта структура в кэш-памяти содержит вставки, пока кэш не заполнится, и затем пакетом сбрасывает их на диск (к вспомогательной индексной таблице). Вы можете запросить таблицу INFORMATION_SCHEMA.INNODB_FT_INDEX_CACHE, чтобы смотреть размеченные данные для недавно вставленных строк.

Поведение кэширования и пакета избегает частых обновлений вспомогательных таблиц, которые могли привести к параллельным проблемам доступа во время занятой вставки и обновления. Метод группирования также избегает многократных вставок для того же самого слова и минимизирует двойные записи. Вместо того, чтобы сбросить каждое слово индивидуально, вставки для того же самого слова слиты и сбрасываются на диск как единственная запись, улучшая эффективность вставки, в то время как размер индексных таблиц как можно меньше.

Переменная innodb_ft_cache_size используется, чтобы сконфигурировать размер кэша (на основе таблицы), который затрагивает, как часто полнотекстовый индексный кэш сбрасывается. Вы можете также определить глобальный предел размера кэша для всех таблиц в приведенном примере, используя опцию innodb_ft_total_cache_size.

Полнотекстовый индексный кэш хранит ту же самую информацию, как и вспомогательные индексные таблицы. Однако, полнотекстовый индексный кэш кэширует только размеченные данные для недавно вставленных строк. Данные, которые уже сброшены на диск (к полнотекстовым вспомогательным таблицам) не возвращены в кэш когда запрошены. Данные во вспомогательных таблицах запрошены непосредственно, и результаты из вспомогательных таблиц слиты с результатами из кэша прежде, чем быть возвращенными.

ID документа и столбец FTS_DOC_ID

InnoDB использует уникальный идентификатор документа, называемый Document ID (DOC_ID), чтобы отобразить слова в полнотекстовом индекс на записи, где слово появляется. Отображение требует столбца FTS_DOC_ID в индексированной таблице. Если FTS_DOC_ID не определен, InnoDB автоматически добавляет скрытый столбец FTS_DOC_ID, когда полнотекстовый индекс создается. Следующий пример демонстрирует это поведение.

Следующее табличное определение не включает FTS_DOC_ID:

CREATE TABLE opening_lines (id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY
       KEY, opening_line TEXT(500), author VARCHAR(200),
       title VARCHAR(200)) ENGINE=InnoDB;

Когда Вы создаете полнотекстовый индекс, используя CREATE FULLTEXT INDEX, предупреждение возвращено, которое сообщает о том, что InnoDB переделывает таблицу, чтобы добавить столбец FTS_DOC_ID.

mysql> CREATE FULLTEXT INDEX idx ON opening_lines(opening_line);
Query OK, 0 rows affected, 1 warning (0.19 sec)
Records: 0  Duplicates: 0  Warnings: 1

mysql> SHOW WARNINGS;
+---------+------+--------------------------------------------------+
| Level   | Code | Message                                          |
+---------+------+--------------------------------------------------+
| Warning |  124 | InnoDB rebuilding table to add column FTS_DOC_ID |
+---------+------+--------------------------------------------------+

То же самое предупреждение возвращено, используя ALTER TABLE, чтобы добавить полнотекстовый индекс к таблице, которая не имеет столбца FTS_DOC_ID. Если Вы создаете полнотекстовый индекс через CREATE TABLE и не определяете FTS_DOC_ID, InnoDB добавляет скрытый столбец FTS_DOC_ID без предупреждения.

Определение FTS_DOC_ID в CREATE TABLE уменьшает время, требуемое, чтобы создать полнотекстовый индекс на таблице, которая уже загружена данными. Если столбец FTS_DOC_ID определен на таблице до загрузки данных, таблица и индекс не должны быть переделаны, чтобы добавить новый столбец. InnoDB создает скрытый столбец FTS_DOC_ID наряду с уникальным индексом (FTS_DOC_ID_INDEX) на столбце FTS_DOC_ID. Если Вы хотите создать свой собственный FTS_DOC_ID, столбец должен быть определен как BIGINT UNSIGNED NOT NULL и назван FTS_DOC_ID (все буквы большие), как в следующем примере:

Столбец FTS_DOC_ID не должен быть определен как AUTO_INCREMENT, но AUTO_INCREMENT мог сделать загрузку данных легче.

CREATE TABLE opening_lines (
       FTS_DOC_ID BIGINT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
       opening_line TEXT(500), author VARCHAR(200), title VARCHAR(200))
       ENGINE=InnoDB;

Если Вы хотите определять FTS_DOC_ID самостоятельно, Вы ответственны за управление столбцом, чтобы избежать пустых или двойных значений. Значения FTS_DOC_ID не могут быть снова использованы, что означает, что значения FTS_DOC_ID должны когда-либо увеличиваться.

Произвольно Вы можете создать необходимый уникальный FTS_DOC_ID_INDEX на столбце FTS_DOC_ID.

CREATE UNIQUE INDEX FTS_DOC_ID_INDEX on opening_lines(FTS_DOC_ID);

Если Вы не создаете FTS_DOC_ID_INDEX, InnoDB создает это автоматически.

Разрешенный промежуток между используемым самым большим значением FTS_DOC_ID и новым значением FTS_DOC_ID 65535.

Обработка удаления полнотекстового индекса

Удаление записи, у которой есть полнотекстовый индекс, может привести к многочисленным маленьким удалениям во вспомогательных индексных таблицах, делая параллельный доступ к этим таблицам предметом спора. Чтобы избежать этой проблемы, Document ID (DOC_ID) из удаленного документа зарегистрирован в спецтаблице FTS_*_DELETED всякий раз, когда запись удалена из индексированной таблицы, и запись остается в полнотекстовом индексе. Перед возвращением результатов запроса, информация в FTS_*_DELETED используется, чтобы отфильтровать удаленные Document ID. Выгода этого проекта то, что удаления быстры и недороги. Недостаток состоит в том, что размер индекса не был немедленно уменьшен после удаления записей. Чтобы удалить полнотекстовые индексные записи, надо выполнить OPTIMIZE TABLE на индексированной таблице с innodb_optimize_fulltext_only=ON, чтобы восстановить полнотекстовый индекс.

Обработка транзакций Full-Text

Индексы FULLTEXT имеют специальные операционные характеристики управляемости, описывающие поведение кэширования и пакетной обработки данных. Определенно, обновления и вставки на индексе FULLTEXT обработаны в момент закрытия транзакции, что означает, что поиск FULLTEXT может видеть только переданные данные. Следующий пример демонстрирует это поведение. FULLTEXT возвращает результат после того, как вставленные строки переданы.

mysql> CREATE TABLE opening_lines (
                 id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
                 opening_line TEXT(500), author VARCHAR(200),
                 title VARCHAR(200), FULLTEXT idx (opening_line))
                 ENGINE=InnoDB;
mysql> BEGIN;
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO opening_lines(opening_line,author,title) VALUES
   ('Call me Ishmael.','Herman Melville','Moby-Dick'),
   ('A screaming comes across the sky.','Thomas Pynchon','Gravity\'s Rainbow'),
   ('I am an invisible man.','Ralph Ellison','Invisible Man'),
   ('Where now? Who now? When now?','Samuel Beckett','The Unnamable'),
   ('It was love at first sight.','Joseph Heller','Catch-22'),
   ('All this happened, more or less.','Kurt Vonnegut','Slaughterhouse-Five'),
   ('Mrs. Dalloway said she would buy the flowers herself.','Virginia Woolf','Mrs. Dalloway'),
   ('It was a pleasure to burn.','Ray Bradbury','Fahrenheit 451');
Query OK, 8 rows affected (0.00 sec)
Records: 8  Duplicates: 0  Warnings: 0

mysql> SELECT COUNT(*) FROM opening_lines WHERE MATCH(opening_line)
                 AGAINST('Ishmael');
+----------+
| COUNT(*) |
+----------+
| 0        |
+----------+

mysql> COMMIT;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT COUNT(*) FROM opening_lines WHERE MATCH(opening_line)
                 AGAINST('Ishmael');
+----------+
| COUNT(*) |
+----------+
| 1        |
+----------+

Контроль полнотекстовых индексов

Вы можете контролировать и исследовать специальные относящиеся к обработке текстов аспекты InnoDB FULLTEXT, запрашивая следующие таблицы INFORMATION_SCHEMA:

Вы можете также рассмотреть основную информацию для индексов FULLTEXT и таблиц, запрашивая INNODB_SYS_INDEXES и INNODB_SYS_TABLES .

См. раздел 16.14.4.

16.8.10. Физическая структура индексов InnoDB

За исключением пространственного индекса, индексы InnoDB это структуры данных B-tree. Пространственный индекс использует R-tree, которые являются специализированными структурами данных для того, чтобы индексировать многомерные данные. Индексные записи сохранены в страницах листа их структуры данных B-tree или R-tree. Размер по умолчанию индексной страницы составляет 16 КБ.

Когда новые записи вставлены в кластеризируемый индекс, InnoDB попытается оставить 1/16 страницы свободной для будущих вставок и обновлений. Если индексные записи вставлены в последовательном порядке (возрастание или убывание), получающиеся индексные страницы полны на 15/16. Если записи вставлены в случайном порядке, страницы полны от 1/2 до 15/16.

InnoDB выполняет оптовую загрузку, когда создает B-tree индексов. Этот метод создания индекса известен как сортированный индекс. innodb_fill_factor определяет процент пространства на каждой странице B-дерева, который заполнен во время создания сортированного индекса с остающимся пространством, сохраненным для будущего роста. Создание сортированного индекса не поддержанр для пространственного индекса. Для получения дополнительной информации см. раздел 16.8.11. innodb_fill_factor устанавливает 1/16 пространства в кластеризируемых индексных страницах свободным для будущего роста.

Если коэффициент заполнения индексной страницы понижается ниже MERGE_THRESHOLD, который составляет 50% по умолчанию, если не определен InnoDB пробует сократить индексное дерево, чтобы освободить страницу. MERGE_THRESHOLD относится к B-tree и R-tree. Подробности в разделе 16.6.11.

Вы можете сконфигурировать размер страницы для всех табличных пространств InnoDB, задав опцию innodb_page_size прежде, чем создать экземпляр. Как только размер страницы установлен, Вы не можете изменить его. Поддержанные размеры составляют 64KB, 32KB, 16KB (значение по умолчанию), 8KB и 4KB, соответствуя значениям опции 64k, 32k, 16k, 8k и 4k.

16.8.11. Создание сортированного индекса

InnoDB выполняет оптовую загрузку вместо того, чтобы вставить каждую запись в то время, когда создает индекс. Этот метод известен как создание сортированного индекса. Сортированный индекс не поддержан для пространственного индекса.

Есть три фазы создания индекса. В первой фазе кластеризируемый индекс просмотрен, и индексные записи произведены и добавлены к буферу. Когда буфер сортировки становится полным, записи сортированы и записаны во временный промежуточный файл. Этот процесс также известен как run. Во второй фазе, с одним или более выполнениями, записанными во временный промежуточный файл, сортировка слиянием выполнена на всех записях в файле. В третьей и заключительной фазе сортированные записи вставлены в B-tree.

До введения сортированных индексов записи были вставлены в B-tree поштучно, используя insert API. Этот метод вовлекал открытие B-tree курсора, чтобы найти позицию вставки, а затем вставку записей в страницу B-tree, используя оптимистическуювставку. Если бы вставка потерпела неудачу из-за полной страницы, то пессимистическая вставка была бы выполнена, которая вовлекает открытие курсора B-tree, разделение и слияние узлов B-tree по мере необходимости, чтобы найти пространство для входа. Недостатки этого метод создания индексирования являются стоимостью поиска позиции вставки и постоянного разделения и слияния узлов B-tree.

Сортированный индекс использует восходящий подход к созданию индекса. С этим подходом ссылка на самую правую страницу листа проводится на всех уровнях B-tree. Самая правая страница листа в необходимой глубине B-tree выделена, и записи вставлены согласно их сортированному порядку. Как только страница листа полна, указатель узла приложен к родительской странице, и страница листа выделена для следующей вставки. Этот процесс продолжается, пока все записи не вставлены, что может привести к вставкам до уровня корня. Когда страница выделена, ссылка на ранее прикрепленную страницу листа выпущена, и недавно выделенная страница листа становится самой правой страницей листа (и новым значением по умолчанию места для вставки).

Резервирование места на страницах B-tree для будущего роста индекса

Чтобы отложить пространство для будущего индексного роста, Вы можете использовать опцию innodb_fill_factor, чтобы зарезервировать процент пространства страницы B-tree. Например, установка innodb_fill_factor в 80 резервирует 20 процентов пространства в страницах B-tree во время создания сортированного индекса. Эта установка относится к страницам листа и не к страницам листа B-tree. Это не относится к внешним страницам, используемым для TEXT или BLOB. Количество пространства, которое сохранено, не может быть точно сконфигурировано, поскольку innodb_fill_factor интерпретируется как подсказка, а не жесткий предел.

Создание сортированного индекса и поддержка Fulltext Index

Создание сортированного индекса поддерживается для индексов fulltext. Ранее SQL использовался, чтобы вставить записи в индексы fulltext.

Создание сортированного индекса и сжатые таблицы

Для сжатых таблиц предыдущие метод создания индекса добавляет записи в сжатые и в несжатые страницы. Когда журнал модификации (представляющий свободное пространство на сжатой странице) станет полным, сжатая страница будет пересжата. Если бы сжатие потерпело неудачу из-за недостатка места, то страница была бы разделена. С сортированным индексом записи добавлены только к несжатым страницам. Когда несжатая страница становится полной, она сжата. Адаптивное дополнение используется, чтобы гарантировать, что сжатие преуспевает в большинстве случаев, но если сжатие терпит неудачу, страница разделена, и сжатие предпринято снова. Этот процесс продолжается, пока сжатие не пройдет успешно. Для дополнительной информации о сжатии страниц B-Tree см. раздел 16.9.1.5.

Создание сортированного индекса и журнал Redo

Журнал Redo выключен во время создания сортированного индекса. Вместо этого есть контрольная точка, чтобы гарантировать, что индексирование может противостоять катастрофическому отказу. Контрольная точка вызывает запись всех грязных страниц на диск. Во время создания сортированного индекса поток уборщика страницы вызван периодически, чтобы сбросить грязные страницы, чтобы гарантировать, что работа контрольной точки может быть обработана быстро. Обычно поток уборщика сбрасывает грязные страницы, когда число чистых страниц падает ниже порога набора. При создании сортированного индекса грязные страницы сбрасываются быстро, чтобы уменьшить издержки контрольной точки.

Создание сортированного индекса и статистика оптимизатора

Создание сортированного индекса может привести к статистическим данным, которые отличаются от произведенных предыдущим методом создания индекса, используемым в более ранних выпусках MySQL. Различие в статистике, которое, как ожидают, не затронет рабочую нагрузку, происходит из-за различного алгоритма, который используется, чтобы заполнить индекс.

16.9. Таблица InnoDB и сжатие страницы

Этот раздел предоставляет информацию о табличном сжатии и особенности сжатия страницы. Особенность сжатия страницы также упоминается как прозрачное сжатие страницы.

Используя функции сжатия InnoDB, Вы можете составить таблицы, где данные хранятся в сжатой форме. Сжатие может помочь улучшить сырую работу и масштабируемость. Сжатие означает, что меньше данных передано между диском и памятью, и занимает меньше места на диске и в памяти. Выгода усилена для таблиц с вторичными индексами , потому что индексные данные сжаты также. Сжатие может быть особенно важным для устройств хранения данных SSD из-за их низкой емкости.

16.9.1. Табличное сжатие InnoDB

Этот раздел описывает табличное сжатие, которое поддержано таблицами, которые находятся в табличных пространствах file_per_table или общих табличных пространствах . Табличное сжатие включено, используя атрибут ROW_FORMAT=COMPRESSED с CREATE TABLE или ALTER TABLE.

16.9.1.1. Краткий обзор табличного сжатия

Поскольку процессоры и кэш-память увеличили в скорости больше, чем дисковые устройства хранения данных, много рабочих нагрузок являются зависящими от диска. Сжатие данных приводит к меньшему размеру базы данных, уменьшенному вводу/выводу и улучшенной пропускной способности, при маленькой стоимости увеличенного использования центрального процессора. Сжатие особенно ценно для интенсивных чтением приложений, на системах с достаточным количеством RAM, чтобы сохранить часто используемые данные в памяти.

Таблица, составленная с ROW_FORMAT=COMPRESSED может использовать меньший размер страницы на диске, чем сконфигурировано innodb_page_size . Меньшие страницы требуют меньше ввода/вывода, который особенно ценен для устройств SSD.

Сжатый размер страницы определен через параметр KEY_BLOCK_SIZE в CREATE TABLE или ALTER TABLE . Различный размер страницы требует, чтобы таблица была помещена в табличное пространство file-per-table или в общее табличное пространство, а не в системное табличное пространство, поскольку системное табличное пространство не может сохранить сжатые таблицы. Для получения дополнительной информации см. разделы 16.7.4 и 16.7.9.

Уровень сжатия не зависит от KEY_BLOCK_SIZE. Поскольку Вы определяете меньшие значения для KEY_BLOCK_SIZE, Вы извлекаете пользу ввода/вывода из все более и более меньших страниц. Но если Вы определяете значение, которое является слишком маленьким, будут лишние накладные расходы, чтобы реорганизовать страницы, когда значения данных не могут быть сжаты достаточно, чтобы разместить много строк в каждой странице. Есть жесткий предел нижнего размера KEY_BLOCK_SIZE, который может быть для таблицы, основанный на длинах ключевых столбцов для каждого из индексов. Определите значение, которое является слишком маленьким, и CREATE TABLE или ALTER TABLE не сработают.

В буферном пуле сжатые данные проводятся в маленьких страницах, с размером страницы, основанным на KEY_BLOCK_SIZE. Для извлечения или обновления значений столбцов MySQL также создает несжатую страницу в буферном пуле с несжатыми данными. В буферном пуле любые обновления несжатой страницы также переписаны назад к эквивалентной сжатой странице. Вы, возможно, должны были бы измерить свой буферный пул, чтобы приспособить дополнительные данные и сжатых и несжатых страниц, хотя несжатые страницы вычеркиваются из буферного пула, когда пространство необходимо, и затем разсжаты снова при следующем доступе.

16.9.1.2. Составление сжатых таблиц

Сжатые таблицы могут быть составлены в табличных пространствах file-per-table или в общих табличных пространствах . Табличное сжатие недоступно для системного табличного пространства. Системное табличное пространство (файлы .ibdata) может содержать создаваемые пользователем таблицы, но оно также содержит внутренние системные данные, которые никогда не сжимаются. Таким образом, сжатие применяется только к таблицам и индексам, сохраненным в file-per-table или общих табличных пространствах.

Составление сжатой таблицы в табличном пространстве File-Per-Table

Чтобы создать сжатую таблицу в табличном пространстве file-per-table, innodb_file_per_table должен быть включен (значение по умолчанию). Вы можете установить эти параметры в конфигурационном файле MySQL (my.cnf или my.ini) или динамически с использованием SET.

После настройки опции innodb_file_per_table определите параметр ROW_FORMAT=COMPRESSED, KEY_BLOCK_SIZE или оба в CREATE TABLE или ALTER TABLE, чтобы составить сжатую таблицу в табличном пространстве file-per-table.

Например, Вы могли бы использовать следующие запросы:

SET GLOBAL innodb_file_per_table=1;
CREATE TABLE t1 (c1 INT PRIMARY KEY) ROW_FORMAT=COMPRESSED
       KEY_BLOCK_SIZE=8;
Составление сжатой таблицы в общем табличном пространстве

Чтобы создать сжатую таблицу в общем табличном пространстве, FILE_BLOCK_SIZE должен быть определен для общего табличного пространства, которое определено, когда табличное пространство создается. FILE_BLOCK_SIZE должно быть допустимым сжатым размером страницы относительно innodb_page_size, размер страницы сжатой таблицы, определенной параметром KEY_BLOCK_SIZE в CREATE TABLE или ALTER TABLE должен быть равным FILE_BLOCK_SIZE/1024. Например, если innodb_page_size=16384 и FILE_BLOCK_SIZE=8192, KEY_BLOCK_SIZE должен быть 8. Для получения дополнительной информации см. раздел 16.7.9.

Следующий пример демонстрирует создание общего табличного пространства и добавление сжатой таблицы. Пример принимает значение по умолчанию innodb_page_size 16K. FILE_BLOCK_SIZE = 8192 требует, чтобы у сжатой таблицы был KEY_BLOCK_SIZE = 8.

mysql> CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd'
                 FILE_BLOCK_SIZE = 8192 Engine=InnoDB;
Query OK, 0 rows affected (0.01 sec)

mysql> CREATE TABLE t4 (c1 INT PRIMARY KEY) TABLESPACE ts2
                 ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
Query OK, 0 rows affected (0.00 sec)
Примечания
  • Если Вы определяете ROW_FORMAT=COMPRESSED, Вы можете опустить KEY_BLOCK_SIZE, KEY_BLOCK_SIZE по умолчанию установится к половине innodb_page_size .

  • Если Вы определяете допустимое значение KEY_BLOCK_SIZE, Вы можете опустить ROW_FORMAT=COMPRESSED, сжатие включено автоматически.
  • Чтобы определить лучшее значение для KEY_BLOCK_SIZE, как правило, Вы создаете несколько копий той же самой таблицы с различными значениями для этого параметра, затем измеряете размер получающегося файла .ibd. Для общих табличных пространств имейте в виду, что понижение таблицы не уменьшает размер файла .ibd общего табличного пространства и при этом не возвращает дисковое пространство к операционной системе. Для получения дополнительной информации см. раздел 16.7.9.
  • KEY_BLOCK_SIZE обработано как подсказка, иной размер может использоваться InnoDB в случае необходимости. Для табличных пространств file-per-table KEY_BLOCK_SIZE может быть только меньше или равным innodb_page_size . Если Вы определяете значение больше, чем innodb_page_size , указанное значение проигнорировано, предупреждение выпущено и KEY_BLOCK_SIZE установлен в половину innodb_page_size . Если innodb_strict_mode=ON, определение недопустимого KEY_BLOCK_SIZE возвращает ошибку. Для общих табличных пространств допустимые значения KEY_BLOCK_SIZE зависят от FILE_BLOCK_SIZE. Подробности в разделе 16.7.9.
  • InnoDB поддерживает размеры страницы 32 k и 64 k, но эти размеры страницы не поддерживают сжатие. Для получения дополнительной информации обратитесь к описанию innodb_page_size .
  • Значение по умолчанию несжатого размера страниц 16KB. В зависимости от комбинации значений опций MySQL использует размер страницы 1KB, 2KB, 4KB, 8KB или 16KB для файла с данными табличного пространства (файл .ibd). Фактический алгоритм сжатия не затронут KEY_BLOCK_SIZE, значение определяет, насколько большой каждый сжатый кусок, что в свою очередь затрагивает, сколько строк может быть упаковано в каждую сжатую страницу.
  • Составляя сжатую таблицу в табличном пространстве file-per-table установка KEY_BLOCK_SIZE равным размеру страницы, как правило, не приводит к большому сжатию. Например, установка KEY_BLOCK_SIZE=16 обычно не приводила бы к большому сжатию, начиная с нормального размера страницы 16KB. Эта установка может все еще быть полезной для таблиц с многими большими столбцами BLOB, VARCHAR или TEXT, потому что такие значения часто сжимаются хорошо, и могли бы поэтому потребовать меньшего количества страниц переполнения, как описано в разделе 16.9.1.5. Для общих табличных пространств KEY_BLOCK_SIZE равный размеру страницы не разрешен. Для получения дополнительной информации см. раздел 16.7.9.
  • Все индексы таблицы (включая кластеризируемый индекс) сжаты, используя тот же самый размер страницы, как определено в CREATE TABLE или ALTER TABLE. Табличные признаки ROW_FORMAT и KEY_BLOCK_SIZE не часть синтаксиса CREATE INDEX для таблиц InnoDB и проигнорированы, если они определены (хотя если определены, они появятся в выводе SHOW CREATE TABLE ).
  • Для связанных с работой параметров конфигурации см. раздел 16.9.1.3.

Ограничения на сжатые таблицы
  • Сжатые таблицы не могут быть сохранены в системное табличное пространство.

  • Общие табличные пространства могут содержать много таблиц, но сжатые и несжатые таблицы не могут сосуществовать в пределах того же самого общего табличного пространства.
  • Сжатие относится ко всей таблице и всем связанным индексам, а не к отдельным строкам, несмотря на имя параметра ROW_FORMAT.
  • InnoDB не поддерживает сжатые временные таблицы. Когда innodb_strict_mode включен (значение по умолчанию), CREATE TEMPORARY TABLE возвращает ошибку, если указан ROW_FORMAT=COMPRESSED или KEY_BLOCK_SIZE. Если innodb_strict_mode отключен, предупреждения выпущены, и временная таблица составлена, используя несжатый формат строки. Те же самые ограничения относятся к ALTER TABLE на временных таблицах.

16.9.1.3. Настройка сжатия для таблиц InnoDB

Потому что эффективность сжатия зависит от природы Ваших данных, Вы можете принять решения, которые затрагивают исполнение сжатых таблиц:

  • Какие таблицы сжать.

  • Какой сжатый размер страницы использовать.
  • Скорректировать ли размер буферного пула, основываясь на технических характеристиках во время выполнения, таких как количество времени, которое система тратит на сжатие и разсжатие данных. Походит ли рабочая нагрузка больше на хранилище данных (прежде всего запросы) или система OLTP (соединение запросов и DML).
  • Если система выполняет операции DML на сжатых таблицах, и способ, которым распределены данные, приводит к дорогим отказам сжатия во времени выполнения, Вы могли бы скорректировать дополнительные усовершенствованные параметры конфигурации.

Когда Вы готовы провести долгосрочное тестирование и поместить сжатые таблицы в производство см. раздел 16.9.1.4 для способов проверить эффективность выбора в условиях реального мира.

Когда использовать сжатие

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

Характеристики данных и сжатие

Ключевой детерминант эффективности сжатия в сокращении размера файлов с данными является природой данных. Вспомните, что сжатие работает, идентифицируя повторные строки байтов в блоке данных. Полностью рандомизированные данные худший случай. Типичные данные часто повторяют значения, там сжатие эффективно. Строки символов часто сжимаются хорошо, независимо от типа столбца CHAR, VARCHAR, TEXT или BLOB. С другой стороны, таблицы, содержащие главным образом двоичные данные (целые числа или числа с плавающей запятой) или данные, которые ранее сжаты (например, изображения JPEG или PNG), возможно, не сжимаются хорошо, значительно или вообще.

Вы выбираете, включить ли сжатие для каждой таблицы InnoDB. Таблица и весь индекс используют тот же самый (сжатый) размер страницы. Могло бы случиться так, что that the первичный ключ (кластеризируемый) индекс, который содержит данные для всех столбцов таблицы, сжимается эффективнее, чем вторичный индекс. Для тех случаев, где есть длинные строки, использование сжатия могло бы привести к длинным значениям столбцов, сохраненным вне страницы, как обсуждает раздел 16.10.3. Те страницы переполнения можно сжать хорошо. Для многих приложений некоторые таблицы сжимаются эффективнее, чем другие, и Вы могли бы найти, что Ваша рабочая нагрузка выступает лучше всего только с подмножеством сжатых таблиц.

Чтобы определить, сжать ли особую таблицу, проведите эксперименты. Вы можете получить грубую оценку того, как эффективно Ваши данные могут быть сжаты при использовании утилиты, которая осуществляет сжатие LZ77 (такой, как gzip или WinZip) на копии файла .ibd для несжатой таблицы. Вы можете ожидать, что будет меньше сжатия от MySQL для таблицы, чем от основанных на файле инструментов сжатия, потому что MySQL сжимает данные в кусках, основанных на размере страницы, 16KB по умолчанию. В дополнение к пользовательским данным формат страницы включает некоторые внутренние системные данные, которые не сжаты. Основанные на файле утилиты сжатия могут исследовать намного большие куски данных, и так найти повторные строки в огромном файле, чем MySQL может найти в отдельной странице.

Другой способ проверить сжатие на определенной таблице состоит в том, чтобы скопировать некоторые данные от Вашей несжатой таблицы в подобную сжатую таблицу (имеющую все те же индексы) в табличном пространстве file-per-table и смотреть на размер получающегося файла .ibd:

use test;
set global innodb_file_per_table=1;
set global autocommit=0;

-- Create an uncompressed table with a million or two rows.
create table big_table as select * from information_schema.columns;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
commit;
alter table big_table add id int unsigned not null primary key auto_increment;
show create table big_table\G
select count(id) from big_table;

-- Check how much space is needed for the uncompressed table.
\! ls -l data/test/big_table.ibd

create table key_block_size_4 like big_table;
alter table key_block_size_4 key_block_size=4 row_format=compressed;

insert into key_block_size_4 select * from big_table;
commit;

-- Check how much space is needed for a compressed table
-- with particular compression settings.
\! ls -l data/test/key_block_size_4.ibd

Этот эксперимент произвел следующие числа, которые, конечно, могли значительно измениться в зависимости от Вашей структуры таблицы и данных:

-rw-rw----  1 cirrus  staff  310378496 Jan  9 13:44 data/test/big_table.ibd
-rw-rw----  1 cirrus  staff   83886080 Jan  9 15:10 data/test/key_block_size_4.ibd

Чтобы понять, эффективно ли сжатие для Вашей особой рабочей нагрузки:

  • Для простых тестов, используйте MySQL без других сжатых таблиц и выполните запросы для таблицы INFORMATION_SCHEMA.INNODB_CMP .

  • Для более тщательно продуманных тестов, вовлекающих рабочие нагрузки с многими сжатыми таблицами, выполните запросы на таблице INFORMATION_SCHEMA.INNODB_CMP_PER_INDEX. Поскольку статистика в INNODB_CMP_PER_INDEX дорого собирается, Вы должны включить параметру конфигурации innodb_cmp_per_index_enabled прежде, чем запросить ту таблицу, и Вы могли бы ограничить такое тестирование сервером развития или некритическим ведомым сервером.
  • Выполните некоторые типичные запросы SQL для сжатой таблицы, которую Вы проверяете.
  • Исследуйте отношение успешных операций сжатия к полным операциям сжатия, запрашивая INFORMATION_SCHEMA.INNODB_CMP или INFORMATION_SCHEMA.INNODB_CMP_PER_INDEX и сравнивая COMPRESS_OPS с COMPRESS_OPS_OK.
  • Если высокий процент операций сжатия успешен, таблица могла бы быть хорошим кандидатом на сжатие.
  • Если Вы получаете высокий процент отказов сжатия, Вы можете корректировать опции innodb_compression_level, innodb_compression_failure_threshold_pct и innodb_compression_pad_pct_max как описано в разделе 16.9.1.6 и пробовать дальнейшие тесты.

Сжатие базы данных против сжатия приложения

Решите, сжать ли данные в Вашем приложении или в таблице, не используйте оба типа сжатия для тех же самых данных. Когда Вы сжимаете данные в приложении и храните результаты в сжатой таблице, дополнительная экономия пространства крайне маловероятна, и двойное сжатие только тратит впустую циклы центрального процессора.

Сжатие в базе данных

Когда включено, табличное сжатие MySQL является автоматическим и относится ко всем столбцам. Столбцы могут все еще быть проверены с такими операторами, как LIKE, и операции сортировки могут все еще использовать индекс, даже когда индексированные значения сжаты. Поскольку индекс часто существенная фракция полного размера базы данных, сжатие могло привести к существенной экономии в хранении, вводе/выводе или времени процессора. Операции сжатия и декомпрессии происходят на сервере базы данных, который, вероятно, является сильной системой, которая измерена, чтобы обработать ожидаемую загрузку.

Сжатие в приложении

Если Вы сжимаете данные, такие как текст в Вашем приложении, прежде, чем это будет вставлено в базу данных, Вы могли бы сохранить заголовок для данных, которые не сжимаются хорошо, сжимая некоторые столбцы. Этот подход использует циклы центрального процессора для сжатия на машине клиента, а не сервере базы данных, который мог бы быть подходящим для распределенного приложения со многими клиентами, или где у машины клиента есть запасные циклы центрального процессора.

Гибридный подход

Конечно, возможно объединить эти подходы. Для некоторых приложений может быть уместно использовать некоторые сжатые таблицы и некоторые несжатые таблицы. Может быть лучшим внешне сжать некоторые данные (и сохранить в несжатых таблицах) и позволить MySQL сжимать другие таблицы приложения. Как всегда, грамотный проект и реальное тестирование ценны в достижении правильного решения.

Характеристики рабочей нагрузки и сжатие

В дополнение к выбору, какие таблицы сжать (и размер страницы), рабочая нагрузка это другой ключевой детерминант работы. Если приложение в основном читает, а не обновлено, меньше страниц должно быть реорганизовано и повторно сжато после того, как индексная страница исчерпывает место для страницы в журнале модификаций, который MySQL поддерживает для сжатых данных. Если обновления преобладающе изменяют неиндексированные столбцы или те, которые содержат BLOB или большие строки, которые сохранены вне страницы, издержки сжатия могут быть приемлемыми. Если единственные изменения таблицы INSERT, которые используют монотонно увеличивающийся первичный ключ, и есть немногие вторичные индексы, есть небольшая потребность реорганизовать и повторно сжать индексные страницы. Так как MySQL может помечать как удаленные и удалять строки на сжатых страницах на месте, изменяя несжатые данные, операцииDELETE на таблице относительно эффективны.

Для некоторой окружающей среды время, чтобы загрузить данные, может быть столь же важным, как извлечение во время выполнения. Особенно в окружающей среде хранилища данных много таблиц могут быть только для чтения или чтения главным образом. В тех случаях это могло бы или не могло бы быть приемлемым заплатить цену сжатия с точки зрения увеличенного времени загрузки, если получающиеся сбережения в меньшем количестве дисковых чтений или в стоимости хранения не являются существенными.

Сжатие работает лучше всего, когда время центрального процессора доступно для сжатия и разсжатия данных. Таким образом, если Ваша рабочая нагрузка ввод/вывод, а не центральный процессор, сжатие может улучшить эффективность работы. Когда Вы проверяете потребительские свойства с различными конфигурациями сжатия, проверяйте на платформе, подобной запланированной конфигурации производственной системы.

Характеристики конфигурации и сжатие

Чтение и запись страниц базы данных с диска являются самым медленным аспектом работы. Сжатие пытается уменьшить ввод/вывод при использовании времени центрального процессора, чтобы сжать данные, и является самым эффективным, когда ввод/вывод относительно недостаточный ресурс по сравнению с циклами процессора.

Когда страница сжатой таблицы находится в памяти, MySQL часто использует дополнительную память, как правило 16 КБ, в буферном пуле для несжатой копии страницы. Адаптивный алгоритм LRU пытается сбалансировать использование памяти между сжатыми и несжатыми страницами, чтобы принять во внимание, работает ли рабочая нагрузка в манере I/O или CPU. Однако, конфигурация с большей памятью, посвященной буферному пулу, имеет тенденцию работать лучше, когда используется сжатие таблицы, чем конфигурация, где память чрезвычайно ограничена.

Выбор сжатого размера страницы

Оптимальная установка сжатого размера страницы зависит от типа и распределения данных, которые содержат индекс и таблица. Сжатый размер страницы должен всегда быть больше, чем максимальный размер записи, или операции могут потерпеть неудачу.

Устанавливая сжатый размер страницы слишком большим, затратите некоторое пространство, но страницы не должны быть сжаты часто. Если сжатый размер страницы установлен слишком маленьким, вставки или обновления могут потребовать отнимающего много времени пересжатия, и узлы B-tree, вероятно, придется разделять чаще, приводя к большим файлам с данными и менее эффективной индексации.

Как правило, Вы устанавливаете сжатый размер страницы в 8K или 4K. Учитывая, что максимальный размер строки для таблицы InnoDB составляет приблизительно 8K, KEY_BLOCK_SIZE=8 обычно безопасный выбор.

16.9.1.4. Контроль сжатия во время выполнения

Полные потребительские свойства, центральный процессор и использование ввода/вывода и размер дисковых файлов это хорошие индикаторы того, как эффективно сжатие для Вашего приложения. Этот раздел основывается на совете из раздела 16.9.1.3 и показывает, как найти проблемы, которые не могли бы проявиться во время начального тестирования.

Вы можете контролировать работу сжатия во время выполнения, используя таблицы Information Schema , описанные в примере 16.10. Эти таблицы отражают внутреннее пользование памяти и уровни сжатия, используемого повсюду.

Таблица INNODB_CMP сообщает о информацию о деятельности сжатия для каждого сжатого размера страницы (KEY_BLOCK_SIZE). Информация в этих таблицах в масштабе всей системы: это суммирует статистику сжатия через все сжатые таблицы в Вашей базе данных. Вы можете использовать эти данные, чтобы помочь решить, сжать ли таблицу, исследуя эти таблицы, когда ни к каким другим сжатым таблицам не получают доступ. Это вовлекает относительно низкие издержки на сервере, таким образом, Вы могли бы периодически запрашивать это на производственном сервере, чтобы проверить полную эффективность сжатия.

Таблица INNODB_CMP_PER_INDEX сообщает о информацию о деятельности сжатия для отдельных таблиц и индексов. Эта информация предназначена и более полезна для того, чтобы оценить эффективность сжатия и диагностировать исполнительные проблемы одной таблицы или индекса за один раз. Поскольку каждая таблица представлена как кластеризируемый индекс, MySQL не делает большое различие между таблицами и индексами в этом контексте. Таблица INNODB_CMP_PER_INDEX действительно вовлекает существенные издержки, таким образом, это является более подходящим для серверов развития, где Вы можете сравнить эффекты различных рабочих нагрузок, данных и настроек сжатия в изоляции. Чтобы принять меры против наложения этого контроля на издержки, Вы должны включить опцию innodb_cmp_per_index_enabled прежде, чем Вы сможете запросить таблицу INNODB_CMP_PER_INDEX.

Ключевые статистические данные являются числом, и количеством времени на выполнение сжатия. Так как MySQL разделяет узлы B-tree, когда они слишком полны, чтобы содержать сжатые данные после модификации, сравните число успешных операций сжатия с числом таких операций вообще. Основываясь на информации в таблицах INNODB_CMP и INNODB_CMP_PER_INDEX , Вы могли бы произвести изменения в своей конфигурации аппаратных средств, скорректировать размер буферного пула, выбрать иной размер страницы или выбрать набор таблиц, чтобы сжать.

Если количество времени центрального процессора, требуемого для сжатия высоко, изменение на быстрый центральный процессор может помочь улучшить работу с теми же самыми данными, рабочую нагрузку приложения и набор сжатых таблиц. Увеличение размера буферного пула могло бы также помочь работе, так, чтобы несжатые страницы могли остаться в памяти, уменьшая потребность разсжимать страницы, которые существуют в памяти только в сжатой форме.

Большое количество операций сжатия (по сравнению с числом INSERT, UPDATE и DELETE в Вашем приложении и размером базы данных), может указать, что некоторые из Ваших сжатых таблиц обновляются слишком сильно для эффективного сжатия. Если это так, выберите больший размер страницы или разберитесь, которые таблицы Вы сжимаете.

Если число успешных операций сжатия (COMPRESS_OPS_OK) выше процента общего количества операций сжатия (COMPRESS_OPS), тогда система, вероятно, работает хорошо. Если отношение низко, то MySQL реорганизует, пересжимает и разделяет узлы B-tree чаще, чем желательно. В этом случае избегайте сжимать некоторые таблицы или увеличьте KEY_BLOCK_SIZE для некоторых из сжатых таблиц. Вы могли бы выключить сжатие для таблиц, которые заставляют число неудачных сжатий в Вашем приложении составлять больше 1%-2%. Такое отношение отказа могло бы быть приемлемым во время временной работы, такой как загрузка данных.

16.9.1.5. Как работает сжатие для таблиц InnoDB

Этот раздел описывает некоторые внутренние детали выполнения сжатия для таблиц InnoDB. Информация, представленная здесь, может быть полезной в настройке для работы, но не необходима, чтобы знать для основного использования сжатия.

Алгоритмы сжатия

Некоторые операционные системы осуществляют сжатие на уровне файловой системы. Файлы, как правило, делятся на блоки фиксированного размера, которые сжаты в блоки переменного размера, который легко приводит к фрагментации. Каждый раз, когда что-то в блоке изменено, целый блок повторно сжат прежде, чем он будет записан на диск. Эти свойства делают этот метод сжатия неподходящим для использования в интенсивной обновляемой системе базы данных.

MySQL осуществляет сжатие с помощью известной библиотеки zlib, которая осуществляет алгоритм сжатия LZ77. Этот алгоритм сжатия является зрелым, здравым и эффективным в использовании центрального процессора и в сокращении размера данных. Алгоритм без потерь, чтобы оригинальные несжатые данные могли всегда быть восстановлены от сжатой формы. Сжатие LZ77 работает, находя последовательности данных, которые повторены в пределах данных, которые будут сжаты. Образцы значений в Ваших данных определяют, как хорошо они сжимаются, но типичные пользовательские данные часто сжимаются на 50% или даже лучше.

В отличие от сжатия, выполненного приложением или особенностями сжатия некоторых других систем управления базой данных, сжатие InnoDB применяется к пользовательским данным и индексам. Во многих случаях индекс может составить 40-50% полного размера базы данных, таким образом, это различие является существенным. Когда сжатие работает хорошо на наборе данных, размер файлов с данными InnoDB (табличное пространство file-per-table общее табличное пространство файлы .idb) ужимает на 25%-50%. В зависимости от рабочей нагрузки, эта меньшая база данных может в свою очередь привести к сокращению ввода/вывода и увеличению пропускной способности по скромной стоимости с точки зрения увеличенного использования центрального процессора. Вы можете скорректировать баланс между уровнем сжатия и нагрузкой на центральный процессор, изменяя параметр innodb_compression_level.

Хранение данных InnoDB и сжатие

Все пользовательские данные в таблицах InnoDB хранятся в страницах, включающих индекс B-tree (кластеризируемый индекс). В некоторых других системах базы данных этот тип индекса назван index-organized table. Каждая строка в индексном узле содержит значение (определенное пользователем или произведенное системой) первичного ключа и все другие столбцы таблицы.

Вторичные индексы в InnoDB также B-tree, содержащие пары значений: ключ индекса и указатель на строку в кластеризируемом индексе. Указатель фактически значение первичного ключа таблицы, который используется, чтобы получить доступ к кластеризируемому индексу, если столбцы кроме индексного ключа и первичного ключа требуются. Вторичный индекс должен всегда соответствовать на единственной странице B-дерева.

Сжатие узлов B-дерева (кластеризируемого и вторичного индексов) обработано отлично от сжатия страниц переполнения, используемых, чтобы хранить столбцы VARCHAR, BLOB или TEXT, как объяснено в следующих разделах.

Сжатие страниц B-дерева

Поскольку они часто обновляются, страницы B-дерева требуют специального режима. Важно минимизировать число раз разделения узлов B-дерева, так же как минимизировать потребность разсжать и повторно сжать их контент.

Один метод, который использует MySQL, должен поддержать некоторую информацию о системе в узле B-дерева в несжатой форме, таким образом облегчая определенные оперативные обновления. Например, это позволяет строкам быть отмеченными для удаления и удаленными без любой работы подсистемы сжатия.

Кроме того, MySQL пытается избежать ненужного и пересжатия индексных страниц, когда они изменены. В пределах каждой страницы B-дерева система сохраняет несжатый журнал изменений, чтобы сделать запись изменений, произведенных в странице. Обновления и вставки небольших записей могут быть записаны в этот журнал модификации не требуя, чтобы вся страница была полностью восстановлена.

Когда пространство для журнала модификации заканчивается, InnoDB разжимает страницу, применяет изменения и повторно сжимает страницу. Если пересжатие терпит неудачу (ситуация, известная как отказ сжатия), узлы B-дерева разделены, и процесс повторен до успеха.

Чтобы избежать частых отказов сжатия в интенсивных по записи рабочих нагрузках, что касается приложений OLTP, MySQL иногда резервирует некоторое пустое место (дополнение) в странице, чтобы журнал модификации заполнился скорее, и страница повторно сжата, в то время как есть все еще достаточно места, чтобы избежать разделения. Количество дополнения пространства, оставленного в каждой странице, изменяется, поскольку система отслеживает частоту разделений страницы. На занятом сервере, делающем частые записи сжатых таблиц, Вы можете корректировать опции innodb_compression_failure_threshold_pct и innodb_compression_pad_pct_max и точно настроить этот механизм.

Вообще, MySQL требует, чтобы каждая страница B-дерева в таблице InnoDB могла вместить по крайней мере две записи. Для сжатых таблиц было смягчено это требование. Страницы листа узлов B-дерева (из первичного ключа или вторичного) должны вмещать только одну запись, но что она должна заполниться, в несжатой форме, в журнале модификации для страницы. Если innodb_strict_mode ON, MySQL проверяет максимальный размер строки во время CREATE TABLE или CREATE INDEX. Если строка не соответствует, следующее сообщение об ошибке выпущено: ERROR HY000: Too big row.

Если Вы составляете таблицу, когда innodb_strict_mode OFF, и последующий INSERT или UPDATE пытается создать индексную запись, которая не помещается в размер сжатой страницы, работа терпит неудачу с ERROR 42000: Row size too large . Это сообщение об ошибке не называет индекс, для которого запись является слишком большой, или упоминает длину индексной записи или максимального размера записи на этой индексной странице. Чтобы решить эту проблему, пересоздайте таблицу с помощью ALTER TABLE и выберите больший сжатый размер страницы (KEY_BLOCK_SIZE), сократите префикс столбца индекса или отключите сжатие полностью с ROW_FORMAT=DYNAMIC или ROW_FORMAT=COMPACT.

innodb_strict_mode не применимо к общим табличным пространствам, которые также поддерживают сжатые таблицы. Управленческие правила табличного пространства для общих табличных пространств строго проведены в жизнь, независимо от innodb_strict_mode . Подробности в разделе 14.1.16.

Сжатие BLOB, VARCHAR и TEXT

В таблице столбцы BLOB, VARCHAR и TEXT, которые не являются частью первичного ключа, могут быть сохранены на отдельно выделенных страницах переполнения. Мы именуем эти столбцы столбцы вне страницы. Их значения сохранены в отдельно-связанных списках страниц переполнения.

Для таблиц, составленных с ROW_FORMAT=DYNAMIC или ROW_FORMAT=COMPRESSED, значения BLOB, TEXT или VARCHAR могут быть сохранены полностью вне страницы, в зависимости от их длины и длины всей строки. Для столбцов, которые сохранены вне страницы, кластеризируемые индексные записи содержит только 20-байтовые указатели на страницы переполнения, один на столбец. Сохранены ли какие-либо столбцы вне страницы, зависит от размера страницы и полного размера строки. Когда строка является слишком длинной, чтобы поместиться полностью в пределах страницы кластеризируемого индекса, MySQL выбирает самые длинные столбцы для хранения вне страницы на кластеризируемой индексной странице. Как отмечено выше, если строка не помещается отдельно на сжатой странице, происходит ошибка.

Для таблиц, составленных в ROW_FORMAT=DYNAMIC или ROW_FORMAT=COMPRESSED, столбцы TEXT и BLOB, которые меньше или равны 40 байтам, всегда сохранены местно.

Таблицы с ROW_FORMAT=REDUNDANT и ROW_FORMAT=COMPACT сохраняют первые 768 байтов столбцов BLOB, VARCHAR и TEXT в кластеризируемой индексной записи наряду с первичным ключом. 768-байтовая приставка сопровождается 20-байтовым указателем на страницы переполнения, которые содержат остальную часть значения столбца.

Когда таблица находится в формате COMPRESSED, все данные, написанные на страницу переполнения, сжаты как есть , то есть, MySQL применяет алгоритм сжатия zlib ко всему элементу данных. Кроме данных, сжатые страницы переполнения содержат несжатый заголовок и метку конца, включающую контрольную сумму страницы и ссылку на следующую страницу переполнения. Поэтому, очень существенная экономия хранения может быть получена для больших BLOB, TEXT или VARCHAR, если данные очень сжимаемы, как это часто бывает с текстовыми данными. Данные изображений (к примеру, JPEG), как правило, уже сжаты и не извлекают выгоду из сохранения в сжатой таблице, двойное сжатие может потратить впустую циклы центрального процессора для небольшой или никакой экономии пространства.

Страницы переполнения имеют тот же самый размер, как другие страницы. Строка, содержащая десять столбцов, сохраненная вне страницы, занимает десять страниц переполнения, даже если полная длина столбцов составляет только 8K. В несжатой таблице десять несжатых страниц переполнения занимают 160K. В сжатой таблице с размером страницы 8K они занимают только 80K. Таким образом, часто более эффективно использовать сжатый формат таблицы для таблиц с длинными значениями столбцов.

Для табличных пространств file-per-table, используя размера сжатой страницы 16K, можно уменьшить затраты ввода/вывода для BLOB, VARCHAR или TEXT, потому что такие данные часто сжимаются хорошо, и могли бы поэтому потребовать меньшего количества страниц переполнения, даже при том, что узлы самого B-дерева берут так много страниц в несжатой форме. Общие табличные пространства не поддерживают размер сжатой страницы 16K (KEY_BLOCK_SIZE). Подробности в разделе 16.7.9.

Сжатие и буферный пул

В сжатой таблице каждая сжатая страница соответствует несжатой странице 16K (или меньшего размера, если innodb_page_size задана). Чтобы получить доступ к данным в странице, MySQL читает сжатую страницу с диска, если это еще не находится в буферном пуле, затем разсжимает страницу к оригинальной форме. Этот раздел описывает, как InnoDB управляет буферным пулом относительно страниц сжатых таблиц.

Чтобы минимизировать ввод/вывод и уменьшить потребность расжимать страницу, буферный пул содержит сжатую и несжатую форму страницы базы данных. Чтобы создать место для других необходимых страниц базы данных, MySQL может вычеркнуть из буферного пула несжатую страницу, оставляя сжатую страницу в памяти. Или, если к странице не получили доступ некоторое время, сжатая форма страницы могла бы быть записана на диск, освобождая пространство для других данных. Таким образом, в любой момент времени буферный пул мог бы содержать сжатые и несжатые формы страницы, только сжатую форму страницы, или ни одной.

MySQL отслеживает, какие страницы хранятся в памяти, а какие можно вычеркнуть с применением алгоритма (LRU), чтобы горячие (часто используемые) данные имели тенденцию оставаться в памяти. Когда к сжатым таблицам получают доступ, MySQL использует адаптивный алгоритм LRU, чтобы достигнуть соответствующего баланса сжатых и несжатых страниц в памяти. Этот адаптивный алгоритм чувствителен к тому, работает ли система в нагрузке I/O-bound или CPU-bound. Цель состоит в том, чтобы избежать тратить слишком много времени обработки на распаковку страниц, когда центральный процессор занят, и избегать делать лишний ввод/вывод, когда у центрального процессора есть запасные циклы, которые могут использоваться для того, чтобы разсжать сжатые страницы (которые могут уже быть в памяти). Когда система I/O-bound, алгоритм предпочитает вычеркивать несжатую копию страницы, а не обе копии, делать больше места для других дисковых страниц. Когда система лимитирована центральным процессором, MySQL предпочитает вычеркивать сжатую и несжатую страницу, чтобы больше памяти могло использоваться для горячих страниц.

Сжатие и файлы системного журнала Redo

Прежде, чем сжатая страница записана в файл с данными, MySQL пишет копию страницы в redo-журнал (если это было повторно сжато с прошлого раза, это было записано в базе данных). Это сделано, чтобы гарантировать, что журналы, применимы для восстановления катастрофического отказа, даже в маловероятном случае что библиотека zlib обновлена, и это изменение начинает проблему совместимости со сжатием данных. Поэтому, некоторое увеличение размера файлов системного журнала или потребность в более частых контрольных точках может ожидаться, используя сжатие. Количество увеличения размера файла системного журнала или частоты контрольной точки зависит от числа изменений сжатых страниц.

Чтобы создать сжатую таблицу в табличном пространстве innodb_file_per_table должен быть включен. Нет никакой зависимости от innodb_file_per_table, составляя сжатую таблицу в общем табличном пространстве. Для получения дополнительной информации см. раздел 16.7.9.

16.9.1.6. Сжатие для рабочих нагрузок OLTP

Традиционно сжатие рекомендовалась прежде всего для рабочих нагрузок только для чтения, например, для хранилища данных . Распространение устройств хранения данных SSD, которые являются быстрыми, но относительно маленькими и дорогими, делает сжатие привлекательным также для OLTP: высокий трафик, интерактивные веб-сайты могут уменьшить свои требования хранения и свои операции в секунду ввода/вывода (IOPS) при использовании сжатых таблиц с приложениями, которые действительно часто используют INSERT, UPDATE и DELETE.

Эти параметры конфигурации позволяют Вам корректировать способ, которым сжатие работает с акцентом на работу и масштабируемость для разных действий:

  • innodb_compression_level позволяет Вам менять степень сжатия или вниз. Более высокое значение позволяет Вам вместить большее количество данных на устройство хранения, за счет большего количества времени центрального процессора во время сжатия. Нижнее значение позволяет Вам уменьшать загрузку центрального процессора, когда место для хранения не будет важно, или Вы ожидаете, что данные не особенно сжимаемы.

  • innodb_compression_failure_threshold_pct определяет предел для отказов сжатия во время обновлений сжатой таблицы. Когда этот порог превышен, MySQL начинает оставлять дополнительное свободное пространство в пределах каждой новой сжатой страницы, динамически корректируя количество свободного пространства до процента размера страницы, определенного innodb_compression_pad_pct_max.
  • innodb_compression_pad_pct_max позволяет Вам корректировать максимальное количество пространства, сохраненного в пределах каждой страницы , чтобы сделать запись изменений сжатых строк, не пережимая всю страницу снова. Чем выше значение, тем больше изменений может быть зарегистрировано, не сжимая повторно страницу. MySQL использует переменное количество свободного пространства для страниц в пределах каждой сжатой таблицы, только когда определяемый процент операций сжатия сбоит во время выполнения, требуя, разделить сжатую страницу.
  • innodb_log_compressed_pages позволяет Вам отключать запись образов пересжатых страниц журнал redo. Пересжатие может произойти, когда изменения произведены в сжатых данных. Эта опция включена по умолчанию, чтобы предотвратить повреждение, которое могло произойти, если иная версия zlib используется во время восстановления. Если Вы уверены, что версия zlib не будет изменяться, отключите innodb_log_compressed_pages, чтобы уменьшить журнал redo для рабочих нагрузок, которые изменяют сжатые данные.

Поскольку работа со сжатыми данными иногда вовлекает хранение сжатых и несжатых версий страницы в памяти в то же самое время, используя сжатие с рабочей нагрузкой OLTP-стиля, будьте готовы увеличить значение опции innodb_buffer_pool_size.

16.9.1.7. Предупреждения синтаксиса сжатия SQL и ошибки

Этот раздел описывает предупреждения и ошибки, с которыми Вы можете столкнуться, используя табличную функцию сжатия с табличными пространствами file-per-table и общими табличными пространствами.

Предупреждения синтаксиса сжатия SQL и ошибки для табличных пространств File-Per-Table

Когда innodb_strict_mode включен (значение по умолчанию), определение ROW_FORMAT=COMPRESSED или KEY_BLOCK_SIZE в CREATE TABLE или ALTER TABLE производит следующую ошибку, если innodb_file_per_table отключен.

ERROR 1031 (HY000): Table storage engine for 't1' doesn't have this option

Таблица не составлена, если текущая конфигурация не разрешает использовать сжатые таблицы.

Когда innodb_strict_mode отключен, определение ROW_FORMAT=COMPRESSED или KEY_BLOCK_SIZE в CREATE TABLE или ALTER TABLE производят следующие предупреждения, если innodb_file_per_table отключен.

mysql> SHOW WARNINGS;
+---------+------+---------------------------------------------------------------+
| Level   | Code | Message                                                       |
+---------+------+---------------------------------------------------------------+
| Warning | 1478 | InnoDB: KEY_BLOCK_SIZE requires innodb_file_per_table.        |
| Warning | 1478 | InnoDB: ignoring KEY_BLOCK_SIZE=4.                            |
| Warning | 1478 | InnoDB: ROW_FORMAT=COMPRESSED requires innodb_file_per_table. |
| Warning | 1478 | InnoDB: assuming ROW_FORMAT=DYNAMIC.                          |
+---------+------+---------------------------------------------------------------+

Эти сообщения только предупреждения, не ошибки, и таблица составлена без сжатия, как будто опции не были определены.

Поведение non-strict позволяет Вам импортировать файл mysqldump в базу данных, которая не поддерживает сжатые таблицы, даже если исходная база данных содержала сжатые таблицы. В этом случае MySQL составляет таблицу в ROW_FORMAT=DYNAMIC.

Чтобы импортировать файл дампа в новую базу данных и обновить таблицы, поскольку они существуют в оригинальной базе данных, гарантируюйте, что у сервера есть надлежащая установка для innodb_file_per_table.

Признак KEY_BLOCK_SIZE разрешен только, когда ROW_FORMAT определен как COMPRESSED или опущен. Определение KEY_BLOCK_SIZE с любым другим ROW_FORMAT производит предупреждение, которое Вы можете рассмотреть с SHOW WARNINGS. Однако, таблица несжата: указанное KEY_BLOCK_SIZE проигнорировано).

УровеньCodeСообщение
Предупреждение1478 InnoDB: ignoring KEY_BLOCK_SIZE=n unless ROW_FORMAT=COMPRESSED.

Если Вы работаете с innodb_strict_mode, комбинация KEY_BLOCK_SIZE с любым ROW_FORMAT, кроме COMPRESSED, производит ошибку, а не предупреждение, и таблица не составлена.

Таблица 16.6 обеспечивает краткий обзор опций ROW_FORMAT и KEY_BLOCK_SIZE, которые используются с CREATE TABLE или ALTER TABLE.

Table 16.6. Опции ROW_FORMAT и KEY_BLOCK_SIZE

ОпцияКак использоватьОписание
ROW_FORMAT=REDUNDANT Формат хранения, используемый до MySQL 5.0.3Менее эффективный, чем ROW_FORMAT=COMPACT, для обратной совместимости.
ROW_FORMAT=COMPACTФормат хранения по умолчанию, начиная с MySQL 5.0.3Хранит префикс 768 байтов длинных значений столбцов в кластеризируемой индексной странице, с остающимися байтами, сохраненными в странице переполнения.
ROW_FORMAT=DYNAMIC Храните значения в пределах кластеризируемой индексной страницы, если они там поместятся, в противном случае хранит только 20-байтовый указатель на страницу переполнения (никакого префикса).
ROW_FORMAT=COMPRESSED Сжимает таблицу и индексы с использованием zlib.
KEY_BLOCK_SIZE=n Определяет сжатый размер страницы 1, 2, 4, 8 или 16 килобайтов, подразумевает ROW_FORMAT=COMPRESSED. Для общих табличных пространств KEY_BLOCK_SIZE равный размеру страницы не разрешен.

Таблица 16.7 суммирует состояния ошибки, которые происходят с определенными комбинациями параметров конфигурации и опций в CREATE TABLE или ALTER TABLE и то, как опции появляются в выводе SHOW TABLE STATUS.

Когда innodb_strict_mode OFF, MySQL создает или изменяет таблицу, но игнорирует определенные настройки как показано ниже. Вы можете видеть предупреждающие сообщения в журнале ошибок MySQL. Когда innodb_strict_mode ON, эти указанные комбинации опций производят ошибки, и таблица не составлена или изменена. Чтобы видеть полное описание состояния ошибки, скомандуйте SHOW ERRORS:

mysql> CREATE TABLE x (id INT PRIMARY KEY, c INT)
    -> ENGINE=INNODB KEY_BLOCK_SIZE=33333;
ERROR 1005 (HY000): Can't create table 'test.x' (errno: 1478)

mysql> SHOW ERRORS;
+-------+------+-------------------------------------------+
| Level | Code | Message                                   |
+-------+------+-------------------------------------------+
| Error | 1478 | InnoDB: invalid KEY_BLOCK_SIZE=33333.     |
| Error | 1005 | Can't create table 'test.x' (errno: 1478) |
+-------+------+-------------------------------------------+

Таблица 16.7. Предупреждения и ошибки CREATE/ALTER TABLE, когда InnoDB Strict Mode OFF

СинтаксисПредупреждение или состояние ошибки Результирующий ROW_FORMAT, как показано в SHOW TABLE STATUS
ROW_FORMAT=REDUNDANTНет REDUNDANT
ROW_FORMAT=COMPACTНетCOMPACT
ROW_FORMAT=COMPRESSED, ROW_FORMAT=DYNAMIC или KEY_BLOCK_SIZE указанПроигнорирован для табличных пространств file-per-table, если включена innodb_file_per_table . Общие табличные пространства поддерживают все форматы строки. См. раздел 16.7.9. Формат строки по умолчанию для file-per-table, указанный формат строки для общего табличного пространства
Неправильный KEY_BLOCK_SIZE (не 1, 2, 4, 8 или 16) KEY_BLOCK_SIZE пропущен Указанный формат строки или формат строки по умолчанию
ROW_FORMAT=COMPRESSED и допустимый KEY_BLOCK_SIZE определеныНет, используется определенный KEY_BLOCK_SIZECOMPRESSED
KEY_BLOCK_SIZE определен с форматом строки REDUNDANT, COMPACT или DYNAMIC KEY_BLOCK_SIZE пропущенREDUNDANT, COMPACT или DYNAMIC
ROW_FORMAT не REDUNDANT, COMPACT, DYNAMIC или COMPRESSED Проигнорирован, если признан анализатором MySQL. Иначе ошибка. Формат строки значения по умолчанию или N/A

Когда innodb_strict_mode ON, MySQL отклоняет недопустимый ROW_FORMAT или KEY_BLOCK_SIZE и выдает ошибку. Строгий режим ON по умолчанию. Когда innodb_strict_mode OFF, MySQL выдает предупреждения вместо ошибок для проигнорированных недопустимых параметров.

Невозможно видеть выбранный KEY_BLOCK_SIZE через SHOW TABLE STATUS. SHOW CREATE TABLE покажет KEY_BLOCK_SIZE (даже если это было проигнорировано, составляя таблицу). Реальный сжатый размер страницы таблицы не может быть выведен на экран MySQL.

Предупреждения синтаксиса сжатия SQL и ошибки для общих табличных пространств
  • Если FILE_BLOCK_SIZE не был определен для общего табличного пространства, когда табличное пространство создавалось, табличное пространство не может содержать сжатые таблицы. Если Вы пытаетесь добавить сжатую таблицу, ошибка возвращена, как показано в следующем примере:

    mysql> CREATE TABLESPACE `ts1` ADD DATAFILE 'ts1.ibd' Engine=InnoDB;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> CREATE TABLE t1 (c1 INT PRIMARY KEY) TABLESPACE ts1
                     ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=8;
    ERROR 1478 (HY000): InnoDB: Tablespace `ts1` cannot
                        contain a COMPRESSED table
    
  • Попытка добавить таблицу с недопустимым KEY_BLOCK_SIZE к общему табличному пространству возвращает ошибку, как показано в следующем примере:
    mysql> CREATE TABLESPACE `ts2` ADD DATAFILE 'ts2.ibd'
                     FILE_BLOCK_SIZE = 8192 Engine=InnoDB;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> CREATE TABLE t2 (c1 INT PRIMARY KEY) TABLESPACE ts2
                     ROW_FORMAT=COMPRESSED KEY_BLOCK_SIZE=4;
    ERROR 1478 (HY000): InnoDB: Tablespace `ts2` uses block size 8192 and cannot
                        contain a table with physical page size 4096
    

    Для общих табличных пространств KEY_BLOCK_SIZE из таблицы должно быть равным FILE_BLOCK_SIZE из табличного пространства, разделенного на 1024. Например, если FILE_BLOCK_SIZE 8192, то KEY_BLOCK_SIZE 8.

  • Попытка добавить таблицу с несжатым форматом строки к общему табличному пространству, сконфигурированному, чтобы сохранить сжатые таблицы, возвращает ошибку, как показано в следующем примере:
    mysql> CREATE TABLESPACE `ts3` ADD DATAFILE 'ts3.ibd'
                     FILE_BLOCK_SIZE = 8192 Engine=InnoDB;
    Query OK, 0 rows affected (0.01 sec)
    
    mysql> CREATE TABLE t3 (c1 INT PRIMARY KEY) TABLESPACE ts3
                     ROW_FORMAT=COMPACT;
    ERROR 1478 (HY000): InnoDB: Tablespace `ts3` uses block size 8192 and cannot
                        contain a table with physical page size 16384
    

innodb_strict_mode не применимо к общим табличным пространствам. Управленческие правила табличного пространства для общих табличных пространств строго проведены в жизнь независимо от innodb_strict_mode . Подробности в разделе 14.1.16.

16.9.2. Сжатие страницы InnoDB

InnoDB поддерживает сжатие на уровне страницы для таблиц, которые находятся в табличных пространствах file-per-table. Эта особенность упоминается как Прозрачное сжатие страницы. Сжатие страницы включено, определяя COMPRESSION в CREATE TABLE или ALTER TABLE. Поддержанные алгоритмы сжатия включают Zlib и LZ4.

Поддержанные платформы

Сжатие страницы поддержано на Windows с NTFS, и на следующем подмножестве MySQL-поддержанных платформ Linux, где уровень ядра оказывает поддержку hole punching:

  • RHEL 7 и полученные дистрибутивы, которые используют версию ядра 3.10.0-123 или выше.

  • OEL 5.10 (UEK2) ядро версии 2.6.39 или выше.
  • OEL 6.5 (UEK3) kernel version 3.8.13 или выше.
  • OEL 7.0 kernel version 3.8.13 или выше.
  • SLE11 kernel version 3.0-x
  • SLE12 kernel version 3.12-x
  • OES11 kernel version 3.0-x
  • Ubuntu 14.0.4 LTS kernel version 3.13 или выше.
  • Ubuntu 12.0.4 LTS kernel version 3.2 или выше.
  • Debian 7 kernel version 3.2 или выше.

Все доступные файловые системы для данного дистрибутива Linux, возможно, не поддерживают hole punching.

Как сжатие страницы работает

Когда страница написана, она сжата, используя указанный алгоритм сжатия. Если сжатие терпит неудачу, данные записаны как есть.

Hole Punch в Linux

В Linux размер блока файловой системы это размер модуля, используемый для hole punching. Поэтому сжатие страницы работает только, если данные о странице могут быть сжаты к размеру, который меньше или равен размеру страницы минус размер блока файловой системы. Например, если innodb_page_size=16K и размер блока файловой системы составляет 4K, данные о странице должны в сжатом виде быть меньше или равны 12K.

Hole Punch в Windows

В Windows основная инфраструктура для sparse-файлов основана на сжатии NTFS. Размер Hole punching это модуль сжатия NTFS, который в 16 раз больше размером кластера NTFS. Размеры кластера и их модули сжатия показаны в следующей таблице:

Таблица 16.8. Размер кластера и модули сжатия NTFS

Размер кластераМодуль сжатия
512 байт8 KB
1 KB16 KB
2 KB32 KB
4 KB64 KB

Сжатие страницы на системах Windows работает, если данные о странице могут быть сжаты к размеру, который меньше или равен размеру страницы минус размер модуля сжатия.

Размер кластера NTFS по умолчанию составляет 4K, для которого размер модуля сжатия составляет 64K. Это означает, что сжатие страницы не обладает никаким преимуществом для Windows NTFS, поскольку максимум innodb_page_size 64K.

Для сжатия страницы под Windows файловая система должна быть создана с размером кластера меньше 4K, и innodb_page_size должен быть, по крайней мере, двойным размером модуля сжатия. Например, для сжатия страницы в Windows Вы могли создать файловую систему с размером кластера 512 байтов (у которого есть модуль сжатия 8 КБ) и инициализировать InnoDB с innodb_page_size 16K или больше.

Включение сжатия страницы

Чтобы включить сжатие страницы, определите атрибут COMPRESSION в CREATE TABLE :

CREATE TABLE t1 (c1 INT) COMPRESSION="zlib";

Вы можете также включить сжатие страницы в ALTER TABLE. Но ALTER TABLE ... COMPRESSION только обновляет признак сжатия табличного пространства. Записи в табличное пространство, которые происходят после установки нового алгоритма сжатия, используют новую установку, но чтобы применять новый алгоритм сжатия к существующим страницам, Вы должны пересоздать таблицу с использованием OPTIMIZE TABLE .

ALTER TABLE t1 COMPRESSION="zlib";
OPTIMIZE TABLE t1;

Отключение сжатия страницы

Чтобы отключить сжатие страницы, установите COMPRESSION=None через ALTER TABLE. Записи в табличное пространство, которые происходят после установки COMPRESSION=None, больше не используют сжатие страницы. Чтобы распаковать существующие страницы, Вы должны пересоздать таблицу с использованием OPTIMIZE TABLE после установки COMPRESSION=None.

ALTER TABLE t1 COMPRESSION="None";
OPTIMIZE TABLE t1;

Метаданные о сжатии страницы

Метаданные о сжатии страницы найдены в таблице INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES в следующих столбцах:

  • FS_BLOCK_SIZE: Размер блока файловой системы, который является размером модуля, используемым для hole punching.

  • FILE_SIZE: Размер файла, который представляет максимальный размер несжатого файла.
  • ALLOCATED_SIZE: Фактический размер файла, который является количеством места, выделенного на диске.

Примените SHOW CREATE TABLE , чтобы смотреть текущую установку сжатия страницы (Zlib, Lz4 или None). Таблица может содержать соединение страниц с различными настройками сжатия.

В следующем примере метаданные о сжатии страницы для таблицы служащих получены от INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES.

# Create the employees table with Zlib page compression
CREATE TABLE employees (emp_no INT NOT NULL, birth_date DATE NOT NULL,
                        first_name VARCHAR(14) NOT NULL,
                        last_name VARCHAR(16) NOT NULL,
                        gender ENUM ('M','F') NOT NULL,
                        hire_date DATE NOT NULL, PRIMARY KEY (emp_no))
                        COMPRESSION="zlib";

# Insert data (not shown)
# Query page compression metadata in INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES

mysql> SELECT SPACE, NAME, FS_BLOCK_SIZE, FILE_SIZE, ALLOCATED_SIZE FROM
                 INFORMATION_SCHEMA.INNODB_SYS_TABLESPACES
                 WHERE NAME='employees/employees'\G
*************************** 1. row ***************************
SPACE: 45
NAME: employees/employees
FS_BLOCK_SIZE: 4096
FILE_SIZE: 23068672
ALLOCATED_SIZE: 19415040

Метаданные о сжатии страницы для таблицы служащих показывают, что очевидный размер файла составляет 23068672 байта, в то время как фактический размер файла (со сжатием страницы) составляет 19415040 байт. Размер блока файловой системы составляет 4096 байтов, что является размером блока, используемым для hole punching.

Ограничения сжатия страницы и примечания использования

  • Сжатие страницы отключено, если размер блока файловой системы (или размер модуля сжатия в Windows) * 2 > innodb_page_size .

  • Сжатие страницы не поддержано для таблиц, которые находятся в совместно используемых табличных пространствах, которые включают системное табличное пространство, временное табличное пространство и общие табличные пространства.
  • Сжатие страницы не поддержано для табличных пространств журнала отмены.
  • Сжатие страницы не поддержано для страниц журнала redo.
  • Страницы R-дерева, которые используются для пространственного индекса, не сжаты.
  • Страницы, которые принадлежат сжатым таблицам (ROW_FORMAT=COMPRESSED) оставлены как есть.
  • Во время восстановления обновленные страницы записаны в несжатой форме.
  • Загрузка сжатого табличного пространства на сервере, который не поддерживает алгоритм сжатия, который использовался, вызывает ошибку ввода/вывода.
  • Прежде, чем откатиться к более ранней версии MySQL, который не делает сжатия страниц, распакуйте таблицы, которые используют функцию сжатия страницы. Чтобы распаковать таблицу, скомандуйте ALTER TABLE ... COMPRESSION=None и OPTIMIZE TABLE.
  • Сжатые странично табличные пространства могут быть скопированы между Linux и серверами Windows, если алгоритм сжатия, который использовался, доступен на обоих серверах.
  • Сохранение сжатия страницы, перемещая сжатый файл табличного пространства от одного узла до другого требует утилиты, которая сохраняет sparse-файлы.
  • Лучшее сжатие страницы может быть достигнуто на аппаратных средствах Fusion-io с NVMFS, чем на других платформах, поскольку NVMFS разработан, чтобы использовать в своих интересах функциональность punch hole.
  • Использование функции сжатия страницы с большим размером страницы и относительно маленьким размером блока файловой системы может привести к увеличению записи. Например, максимальный размер страницы InnoDB 64 КБ с размером блока файловой системы 4 КБ может улучшить сжатие, но может также увеличить требование к буферному пулу, приводя к увеличенному вводу/выводу.

16.10. Форматы хранения и строки InnoDB

Этот раздел обсуждает InnoDB, такие как табличное сжатие, хранение вне страницы длинных значений столбцов переменной длины и большой индексный ключевой префикс, контролируемые форматом строки таблицы InnoDB. Это также обсуждает соображения о том, как выбрать правильный формат строки и совместимость форматов строки между выпусками MySQL.

16.10.1. Краткий обзор хранения строки InnoDB

Хранение для строк и связанных столбцов затрагивает работу для запросов и операций DML. Поскольку больше строк вписывается в единственную дисковую disk страницу, запросы и индексные поиски могут работать быстрее, меньше кэш-памяти требуется в буферном пуле InnoDB и меньше ввода/вывода нужно, чтобы записывать обновленные значения для числовых и коротких строковых столбцов.

Данные в каждой таблице InnoDB разделены на страницы. Страницы, которые составляют каждую таблицу, расположены в структуре данных дерева, названной индекс B-tree. Табличные данные и вторичные индексы применяют этот тип структуры. Индекс B-tree, который представляет всю таблицу, известен как кластеризируемый индекс, который организован согласно столбцам первичного ключа. Узлы индексной структуры данных содержат значения всех столбцов в той строке (для кластеризируемого индекса) или индексные столбцы и столбцы первичного ключа (для вторичного индекса).

Столбцы переменной длины исключение из этого правила. Столбцы BLOB и VARCHAR слишком длинные, чтобы поместиться на странице B-дерева, сохранены на отдельно выделенных дисковых страницах, названных страницами переполнения . Мы называем такие столбцы столбцами вне страницы. Значения этих столбцов сохранены в отдельно-связанных списках страниц переполнения, и у каждого такого столбца есть свой собственный список из одной или более страниц переполнения. В некоторых случаях префикс длинного значения столбца сохранен в B-дереве, чтобы избежать тратить впустую место и избавиться от необходимости читать отдельную страницу.

Следующие разделы описывают, как сконфигурировать формат строки таблицы, чтобы управлять, как сохранены значения столбцов переменной длины. Конфигурация формата строки также решает доступность табличного сжатия и поддержки больших префиксов индексных ключей.

16.10.2. Определение формата строки для таблицы

Формат строки по умолчанию определен параметром innodb_default_row_format, у которого есть значение по умолчанию DYNAMIC. Формат строки по умолчанию используется, когда табличная опция ROW_FORMAT не определена явно, или когда определено ROW_FORMAT=DEFAULT.

Формат строки таблицы может быть определен явно, используя табличную опцию ROW_FORMAT в CREATE TABLE или ALTER TABLE:

CREATE TABLE t1 (c1 INT) ROW_FORMAT=DYNAMIC;

Явно определенный ROW_FORMAT переопределяет неявное значение по умолчанию. Определение ROW_FORMAT=DEFAULT эквивалентно использованию неявного значения по умолчанию.

Опция innodb_default_row_format может быть установлена динамически:

mysql> SET GLOBAL innodb_default_row_format=DYNAMIC;

Допустимые значения innodb_default_row_format включают DYNAMIC, COMPACT и REDUNDANT. Формат строки COMPRESSED, который не поддержан для использования в системном табличном пространстве, не может быть определен как значение по умолчанию. Это может быть определено только явно в CREATE TABLE или ALTER TABLE. Попытка установить innodb_default_row_format в COMPRESSED возвращает эту ошибку:

mysql> SET GLOBAL innodb_default_row_format=COMPRESSED;
ERROR 1231 (42000): Variable 'innodb_default_row_format'
can't be set to the value of 'COMPRESSED'

Недавно составленные таблицы используют формат строки, определенный innodb_default_row_format, когда ROW_FORMAT не определена явно или когда ROW_FORMAT=DEFAULT. Например, следующие CREATE TABLE используют формат строки, определенный innodb_default_row_format.

CREATE TABLE t1 (c1 INT);
CREATE TABLE t2 (c1 INT) ROW_FORMAT=DEFAULT;

Когда опция ROW_FORMAT не определена явно, или когда ROW_FORMAT=DEFAULT, любая операция, которая пересоздает таблицу, также тихо изменяет формат строки таблицы к формату, определенному innodb_default_row_format.

Пересоздающие таблицу операции включают ALTER TABLE с использованием ALGORITHM=COPY или ALTER TABLE с использованием ALGORITM=INPLACE, где табличное восстановление требуется. См. таблицу 16.9 для краткого обзора состояния операций DDL. OPTIMIZE TABLE тоже пересоздает таблицу.

Следующий пример демонстрирует восстанавливающую таблицу работу, которая тихо изменяет формат строки таблицы, составленной без явно определенного формата строки.

mysql> SELECT @@innodb_default_row_format;
+-----------------------------+
| @@innodb_default_row_format |
+-----------------------------+
| dynamic                     |
+-----------------------------+

mysql> CREATE TABLE t1 (c1 INT);
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
                   WHERE NAME LIKE 'test/t1' \G
*************************** 1. row ***************************
 TABLE_ID: 54
 NAME: test/t1
 FLAG: 33
   N_COLS: 4
SPACE: 35
   ROW_FORMAT: Dynamic
ZIP_PAGE_SIZE: 0
   SPACE_TYPE: Single

mysql> SET GLOBAL innodb_default_row_format=COMPACT;
mysql> ALTER TABLE t1 ADD COLUMN (c2 INT);
mysql> SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
                   WHERE NAME LIKE 'test/t1' \G
*************************** 1. row ***************************
 TABLE_ID: 55
 NAME: test/t1
 FLAG: 1
   N_COLS: 5
SPACE: 36
   ROW_FORMAT: Compact
ZIP_PAGE_SIZE: 0
   SPACE_TYPE: Single

Рассмотрите следующие потенциальные проблемы прежде, чем изменить формат строки существующих таблиц с REDUNDANT или COMPACT на DYNAMIC.

  • REDUNDANT и COMPACT поддерживают префикс индексного ключа максимум в 767 байт, тогда как DYNAMIC и COMPRESSED допускают префикс индексного ключа в 3072 байт. В среде репликации, если innodb_default_row_format установлен в DYNAMIC на ведущем устройстве и в COMPACT на ведомом устройстве, следующий запрос DDL, который явно не определяет формат строки, работает на ведущем устройстве, но терпит неудачу на ведомом устройстве:

    CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 VARCHAR(5000), KEY i1(c2(3070)));
    

    Подробности в разделе 16.8.7.

  • Импортирование таблицы, которая явно не определяет формат строки, заканчивается ошибкой несоответствия схемы, если innodb_default_row_format на исходном сервере отличается от установки на целевом сервере. Для получения дополнительной информации, обратитесь к ограничениям, обрисованным в общих чертах в разделе 16.7.6.

Чтобы смотреть формат строки таблицы, скомандуйте SHOW TABLE STATUS или запросите INFORMATION_SCHEMA.TABLES .

SELECT * FROM INFORMATION_SCHEMA.INNODB_SYS_TABLES
         WHERE NAME LIKE 'test/t1' \G

Формат строки определяет физическую структуру строки. См. раздел 16.8.2.

16.10.3. Форматы строки DYNAMIC и COMPRESSED

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

Сохранены ли какие-либо столбцы вне страницы, зависит от размера страницы и полного размера строки. Когда строка является слишком длинной, InnoDB выбирает самые длинные столбцы для хранения вне страницы, пока записи кластеризируемого индекса помещаются на странице B-tree. Столбцы TEXT и BLOB, которые меньше или равны 40 байтам, всегда сохранены на месте.

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

Формат строки COMPRESSED использует подобные внутренние детали для хранения вне страницы, как DYNAMIC с дополнительными соображениями в плане сжатых данных таблицы и индекса и использования меньших размеров страницы. С COMPRESSED опция KEY_BLOCK_SIZE управляет, сколько данных столбца хранится в кластеризируемом индексе, а сколько помещено на страницах переполнения. Для полного изложения формата COMPRESSED см. раздел 16.9.

DYNAMIC и COMPRESSED поддерживают префикс индексного ключа в 3072 байт.

Таблицы, которые используют COMPRESSED могут быть создан в табличных пространствах file-per-table или общих табличных пространствах . Системное табличное пространство не поддерживает формат строки COMPRESSED. Чтобы сохранить таблицу COMPRESSED в табличном пространстве file-per-table, параметр innodb_file_per_table должен быть включен. Опция innodb_file_per_table не применима к общим табличным пространствам. Общие табличные пространства поддерживают все форматы строки, но сжатые и несжатые таблицы не могут сосуществовать в том же самом общем табличном пространстве из-за различных физических размеров страницы. Для получения дополнительной информации об общих табличных пространствах см. раздел 16.7.9.

Таблицы DYNAMIC могут быть сохранены в табличных пространствах file-per-table, общих табличных пространствах и системном табличном пространстве. Чтобы сохранить DYNAMIC в системном табличном пространстве, Вы можете отключить innodb_file_per_table и использовать CREATE TABLE или ALTER TABLE или Вы можете использовать табличную опцию TABLESPACE [=] innodb_system с CREATE TABLE или ALTER TABLE не имея необходимость изменять innodb_file_per_table . Опция innodb_file_per_table неприменима к общим табличным пространствам, и при этом они неприменимы, используя опцию TABLESPACE [=] innodb_system, чтобы сохранить таблицы DYNAMIC в системном табличном пространстве.

InnoDB не поддерживает сжатые временные таблицы. Когда innodb_strict_mode включен (значение по умолчанию), CREATE TEMPORARY TABLE возвращает ошибку, если задан ROW_FORMAT=COMPRESSED или KEY_BLOCK_SIZE. Если innodb_strict_mode выключен, предупреждения выпущены, и временная таблица составлена, используя несжатый формат строки.

DYNAMIC и COMPRESSED это варианты COMPACT и поэтому обрабатывают CHAR аналогично подходу COMPACT. Подробности в разделе 16.8.2.

16.10.4. Форматы строки COMPACT и REDUNDANT

Таблицы, которые используют COMPACT или REDUNDANT, хранят первые 768 байт столбцов переменной длины (VARCHAR, VARBINARY, BLOB и TEXT) в индексной записи в пределах узла B-tree с остатком, сохраненным в страницах переполнения.

Для таблиц, определенных с ROW_FORMAT=COMPACT, CHAR обработан как столбец переменной длины, если длина значения столбца больше или равна 768 байтам, что может произойти, если максимальная длина байта набора символов больше 3, как это с utf8mb4.

Для COMPACT или REDUNDANT , если значение столбца составляет 768 байтов или меньше, никакая страница переполнения не нужна и некоторая экономия во вводе/выводе может получиться, так как значение находится в узле B-дерева. Это работает хорошо на относительно коротких BLOB, но может заставить узлы B-дерева заполняться данными, а не значениями ключа, уменьшая их эффективность. Таблицы со многими столбцами BLOB могут заставить узлы B-дерева становиться слишком полными данными и содержать слишком мало строк, заставляя все индексировать менее эффективно, чем если бы строки были короче или если значения столбцов были сохранены вне страницы.

Формат строки по умолчанию DYNAMIC, как определено опцией innodb_default_row_format. См. раздел 16.10.3.

Для информации о физической структуре строки таблиц, которые используют форматы REDUNDANT или COMPACT, см. раздел 16.8.2.

16.11. Управление вводом/выводом и местом в файлах

Как DBA, Вы должны управлять дисковым вводом/выводом, чтобы препятствовать перегрузке подсистемы ввода/вывода и управлять дисковым пространством, чтобы избежать переполнения устройства хранения данных. Модель ACID требует определенного количества ввода/вывода, который мог бы казаться избыточным, но помогает гарантировать надежность данных. В пределах этих ограничений InnoDB предпринимает попытки оптимизировать базу данных и организацию дисковых файлов, чтобы минимизировать количество дискового ввода/вывода. Иногда, ввод/вывод отложен, пока база данных не освободится или пока все должно быть приведено в последовательное состояние, как во время перезапуска базы данных после быстрого завершения работы.

Этот раздел обсуждает основные соображения для ввода/вывода и дискового пространства с таблицами MySQL InnoDB):

  • Управление количеством фонового ввода/вывода улучшает работу запроса.

  • Включение или отключение опций, которые обеспечивают дополнительную длительность за счет дополнительного ввода/вывода.
  • Организация таблиц во многие маленькие файлы, несколько больших файлов или комбинацию обоих вариантов.
  • Балансирование размера файлов системного журнала против деятельности ввода/вывода, которая происходит, когда файлы системного журнала становятся полными.
  • Как реорганизовать таблицу для оптимальной работы запроса.

16.11.1. Дисковый ввод/вывод

InnoDB использует асинхронный дисковый ввод/вывод где только возможно, создавая много потоков, чтобы обработать операции ввода/вывода, разрешая другим операциям базы данных продолжиться в то время, как ввод/вывод все еще происходит. На Linux и платформах Windows InnoDB использует доступные функции OS и библиотеки, чтобы выполнить нативный асинхронный ввод/вывод. На других платформах InnoDB все еще использует потоки ввода/вывода, но потоки могут фактически ждать запросов ввода/вывода, этот метод известен как симулированный асинхронный ввод/вывод.

Чтение вперед

Если InnoDB может решить, что есть высокая вероятность, что данные могли бы скоро быть необходимы, это выполняет операции чтения вперед, чтобы принести те данные в буферный пул так, чтобы это было доступно в памяти. Обращение с несколькими большими запросами чтения для непрерывных данных может быть более эффективным чем обращение с несколькими маленькими. Есть две эвристики чтения вперед в InnoDB:

  • В последовательном чтении вперед, если InnoDB знает, что образец доступа к сегменту в табличном пространстве последователен, это отправляет заранее пакет чтений страниц базы данных системе ввода/вывода.

  • В случайном чтении вперед, если InnoDB знает, что некоторая область в табличном пространстве, кажется, находится в процессе того, чтобы быть полностью считанной в буферный пул, это отправляет остающиеся чтения в систему ввода/вывода.

Подробности в разделе 16.6.3.5.

Буфер Doublewrite

InnoDB использует новый метод сброса файла, вовлекающий структуру, названную буфер doublewrite, который включен по умолчанию в большинстве случаев (innodb_doublewrite=ON ). Это добавляет безопасности восстановлению после отключения электричества катастрофического отказа и улучшает работу относительно большинства вариантов Unix, уменьшая потребность в операциях fsync().

Перед записью страниц в файл с данными InnoDB сначала пишет их в непрерывной области табличного пространства, названной буфером doublewrite. Только после завершения записи в буфер doublewrite, делается запись страниц на их надлежащие позиции в файле с данными. Если есть катастрофический отказ процесса mysqld или чего-то еще в середине записи страницы, InnoDB может позже найти хорошую копию страницы в буфере doublewrite во время восстановления.

Если системные файлы табличного пространства (файлы ibdata ) расположены на устройствах Fusion-io, которые поддерживают атомные записи, буферизация doublewrite автоматически отключена, и Fusion-io используются для всех файлов с данными. Поскольку буферная установка doublewrite глобальна, doublewrite-буферизация также отключена для файлов с данными, находящихся на не-Fusion-io аппаратных средствах. Эта функция поддерживается только на аппаратных средствах Fusion-io NVMFS в Linux. Чтобы в полной мере воспользоваться этой особенностью, установите innodb_flush_method в O_DIRECT.

16.11.2. Управление пространством файла

Файлы с данными, которые Вы определяете в конфигурационном файле, используя опцию innodb_data_file_path создают системное табличное пространство. Файлы логически связаны, чтобы сформировать системное табличное пространство. В использовании нет никакого чередования. Вы не можете определить, где в пределах системного табличного пространства Ваши таблицы выделены. В создаваемом системном табличном пространстве InnoDB выделяет место, начиная с первого файла с данными.

Чтобы избежать проблем, которые идут с хранением всех таблиц и индексов в системном табличном пространстве, Вы можете включить опцию innodb_file_per_table (значение по умолчанию), которая хранит каждую недавно составленную таблицу в отдельном файле табличного пространства (с расширением .ibd). Для таблицы, сохраненной этим путем, есть меньше фрагментации в пределах дискового файла, и когда таблица усечена, пространство возвращено к операционной системе вместо того, чтобы все еще быть сохраненным InnoDB в пределах системного табличного пространства. Для получения дополнительной информации см. раздел 16.7.4.

Вы можете также сохранить таблицы в общих табличных пространствах . Общие табличные пространства это совместно используемые табличные пространства, создаваемые с CREATE TABLESPACE. Они могут быть созданы за пределами каталога данных MySQL, способны к хранению многих таблиц и поддерживают таблицы всех форматов строки. Для получения дополнительной информации см. раздел 16.7.9.

Страницы, сегменты и табличные пространства

Каждое табличное пространство состоит из страниц. У каждого табличного пространства в случае MySQL есть тот же самый размер страницы. По умолчанию у всех табличных пространств есть размер страницы 16KB, Вы можете уменьшить размер страницы до 8 КБ или 4 КБ, определяя опцию innodb_page_size , когда Вы создаете экземпляр MySQL. Вы можете также увеличить размер страницы до 32 КБ или 64 КБ. Для получения дополнительной информации обратитесь к описанию опции innodb_page_size.

Страницы сгруппированы в экстенты размера 1 МБ для страниц до 16 КБ в размере (64 последовательных страницы по 16 КБ, 128 страниц по 8KB или 256 страниц по 4KB). Для размера страницы 32 КБ размер экстента 2MB. Для размера страницы 64KB размер экстента 4MB. Файлы в табличном пространстве называют сегментами в InnoDB. Эти сегменты отличаются от сегмента отмены, который фактически содержит много сегментов табличного пространства.

Когда сегмент растет в табличном пространстве, InnoDB выделяет первые 32 страницы по одной. После этого InnoDB начинает выделять целые экстенты сегменту. InnoDB может добавить до 4 экстентов за один раз к большому сегменту, чтобы гарантировать хорошее размещение данных.

Два сегмента выделены для каждого индекса. Один для безлистных узлов B-tree, другой для узлов с листьями. Хранение узлов листа непрерывными на диске улучшает последовательные операции ввода/вывода, потому что эти узлы листа содержат фактические табличные данные.

Некоторые страницы в табличном пространстве содержат битовые массивы других страниц, и поэтому несколько экстентов в табличном пространстве InnoDB не могут быть выделено сегментам в целом, только как отдельные страницы.

Когда Вы запрашиваете доступное свободное пространство в табличном пространстве посредством SHOW TABLE STATUS, InnoDB сообщает экстенты, которые определенно свободны в табличном пространстве. InnoDB всегда имеет в запасе некоторые экстенты для уборки и других внутренних целей, эти сохраненные экстенты не включены в свободное пространство.

Когда Вы удаляете данные из таблицы, InnoDB сокращает соответствующее B-дерево индексов. Становится ли освобожденное пространство доступным другим пользователям, зависит от того, освобождаются ли отдельные страницы или экстенты в табличном пространстве. Удаление таблицы или удаление всех строк из нее будет освобождать пространство другим пользователям, но помните, что удаленные строки физически удалены только чисткой, которая происходит автоматически через некоторое время после того, как они больше не нужны для операционных отмен или последовательных чтений. См. раздел 16.3.

Как страницы касаются строк таблицы

Максимальная длина строки немного меньше, чем половина страницы базы данных для 4KB, 8KB, 16KB и 32KB innodb_page_size . Например, максимальная длина строки немного меньше, чем 8 КБ для значения по умолчанию 16 КБ размера страницы InnoDB. Для страниц 64 КБ максимальная длина строки немного меньше 16 КБ.

Если строка не превышает максимальную длину строки, все это сохранено в местном масштабе в пределах страницы. Если строка превышает максимальную длину строки, столбцы переменной длины выбраны для внешнего хранения вне страницы в пределах максимального предела длины строки. Внешнее хранение вне страницы для столбцов переменной длины отличается форматом строки:

  • COMPACT и REDUNDANT

    Когда столбец переменной длины выбран для внешнего хранения вне страницы, InnoDB хранит первые 768 байтов в местном масштабе в строке, а остальные внешне в странице переполнения. У каждого такого столбца есть свой собственный список страниц переполнения. 768-байтовый префикс сопровождается 20-байтовым значением, которое хранит истинную длину столбца и указывает на список переполнения, где остальная часть значения сохранена. См. раздел 16.10.4.

  • DYNAMIC и COMPRESSED

    Когда столбец переменной длины выбран для внешнего хранения вне страницы, InnoDB хранит 20-байтовый указатель в местном масштабе в строке, а остальное внешне в странице переполнения. См. раздел 16.10.3.

Столбцы LONGBLOB и LONGTEXT должны быть меньше 4 ГБ, и суммарная длина строки, включая BLOB и TEXT, должна быть меньше 4 ГБ.

16.11.3. Контрольные точки InnoDB

Создание Ваших очень больших файлов системного журнала может уменьшить дисковый ввод/вывод во время установки контрольных точек. Часто имеет смысл устанавливать полный размер файлов системного журнала столь же большим, как буферный пул или еще больше.

Как обработка контрольной точки работает

InnoDB осуществляет механизм контрольной точки, известный как нечеткая установка контрольных точек. InnoDB сбрасывает измененные страницы базы данных из буферного пула в маленьких пакетах. Нет никакой потребности сбрасывать буферный пул в одном огромном пакете, который разрушил бы обработку пользовательских запросов SQL во время процесса установки контрольных точек.

Во время восстановления катастрофического отказа InnoDB ищет метку контрольной точки, записанную в файлы системного журнала. Это знает, что все модификации базы данных перед меткой присутствуют в образе базы данных на диске. Тогда InnoDB просматривает файлы системного журнала вперед от контрольной точки, применяя зарегистрированные модификации к базе данных.

16.11.4. Дефрагментация таблиц

Случайные вставки или удаления из вторичного индекса могут заставить индексирование становится фрагментированным. Фрагментация означает, что физическое упорядочивание индексных страниц на диске не близко к индексному упорядочиванию записей на страницах, или что есть много неиспользованных страниц в блоках на 64 страницы, которые были выделены индексу.

Один признак фрагментации: что таблица занимает больше места, чем она должна занимать. То, сколько это точно, трудно определить. Все данные InnoDB и индексы сохранены в B-tree, и их коэффициент заполнения может измениться от 50% до 100%. Другой признак фрагментации: сканирование таблицы, такое как это, занимает больше времени, чем должно:

SELECT COUNT(*) FROM t WHERE non_indexed_column <> 12345;

Предыдущий запрос требует, чтобы MySQL выполнил полное сканирование таблицы, самый медленный тип запроса для большой таблицы.

Чтобы убыстрить индексные просмотры, Вы можете периодически выполнять нулевой ALTER TABLE, которая заставляет MySQL восстанавливать таблицу:

ALTER TABLE tbl_name ENGINE=INNODB

Вы можете также использовать ALTER TABLE tbl_name FORCE, чтобы выполнить нулевую работу, которая восстанавливает таблицу.

ALTER TABLE tbl_name ENGINE=INNODB и ALTER TABLE tbl_name FORCE используют online DDL (ALGORITHM=COPY). Подробности в разделе 16.12.1.

Другой способ выполнить работу дефрагментации состоит в том, чтобы использовать mysqldump , чтобы вывести таблицу в дамп, удалить таблицу и перезагрузить ее из файла дампа.

Если вставки в индекс всегда растут, а записи удалены только из конца, управленческий алгоритм InnoDB гарантирует, что фрагментация в индексе не происходит.

16.11.5. Восстановление дискового пространства с TRUNCATE TABLE

Чтобы восстановить дисковое пространство операционной системы, усекая таблицу, эта таблица должна быть сохранена в ее собственном файле .ibd. Для таблицы, которая будет сохранена в ее собственном файле .ibd, innodb_file_per_table должен быть включен, когда таблица составлена. Дополнительно не может быть ограничения внешнего ключа между таблицей для усечения и другими таблицами, иначе TRUNCATE TABLE выдаст ошибку. Ограничение внешнего ключа между двумя столбцами в той же самой таблице, однако, разрешено.

Когда таблица является усеченной, она удалена и пересоздана в новом файле .ibd, а освобожденное пространство возвращено операционной системе. Это в отличие от усечения таблиц, которые сохранены в пределах системного табличного пространства (таблицы, составленные, когда innodb_file_per_table=OFF) и таблиц, сохраненных в совместно используемых общих табличных пространствах, где только InnoDB может использовать освобожденное пространство после того, как таблица усечена.

Способность усечь таблицы и возвратить дисковое пространство операционной системе также означает, что физические резервные копии могут быть меньшими. Усечение таблиц, которые сохранены в системном табличном пространстве (таблицы, составленные, когда innodb_file_per_table=OFF) или в общем табличном пространстве оставляет блоки неиспользуемого места в табличном пространстве.

16.12. InnoDB и Online DDL

online DDL улучшает много типов ALTER TABLE , чтобы избежать табличного копирования или блокирования операций DML в то время, как DDL происходит.

Особенность online DDL обладает следующими преимуществами:

  • Это улучшает отклик и доступность в занятых производственных средах, где создание таблицы, недоступной в течение многих минут или часов, не практично.

  • Это позволяет Вам корректировать баланс между работой и параллелизмом во время работы DDL, выбирая, блокировать ли доступ к таблице полностью (LOCK=EXCLUSIVE), позволить запросы, но не DML (LOCK=SHARED) или позволить полный доступ запросам и DML к таблице (LOCK=NONE). Когда Вы опускаете LOCK или определяете LOCK=DEFAULT, MySQL позволяет такой большой параллелизм, насколько возможно, в зависимости от типа работы.
  • Выполнение оперативных изменений, где только возможно, вместо того, чтобы создать новую копию таблицы, избегает временных увеличений использования дискового пространства и ввода/вывода, связанного с копированием таблицы.

16.12.1. Обзор Online DDL

Исторически, много операций DDL в таблицах InnoDB были дороги. Многие ALTER TABLE работали, составляя новую, пустую, таблицу, определенную с требуемыми табличными опциями и индексами, затем копируя существующие строки к новой таблице поштучно, обновляя индексирование по мере того, как строки были вставлены. После того, как все строки оригинальной таблицы были скопированы, старая таблица была удалена, а копия переименована с названием оригинальной таблицы.

MySQL 5.5 и MySQL 5.1 с InnoDB Plugin оптимизировали CREATE INDEX и DROP INDEX, чтобы избегать копирующего таблицу поведения. Та особенность была известна, как быстрое создание индекса . MySQL 5.6 улучшил много других типов ALTER TABLE, чтобы избежать копировать таблицу. Другое улучшение позволило запросам SELECT INSERT, UPDATE и DELETE (DML) продолжиться в то время, как таблица изменяется. В MySQL 5.7 ALTER TABLE RENAME INDEX был также улучшен, чтобы избежать табличного копирования. Эта комбинация особенностей теперь известна как online DDL.

Этот механизм также означает, что Вы можете вообще ускорить полный процесс создания и загрузки таблицы, составляя таблицу без вторичного индекса, затем добавляя, вторичный индекс после того, как данные загружены.

Хотя никакие изменения синтаксиса не требуются в CREATE INDEX или DROP INDEX, некоторые факторы затрагивают работу и семантику этой работы (см. раздел 16.12.9).

Возможность online DDL в MySQL 5.6 улучшила много операций DDL, которые прежде требовали табличной копии или блокировали операции DML на таблице. Таблица 16.9 показывает изменения ALTER TABLE как особенность DDL онлайн относится к каждому запросу.

За исключением параметров разделения в ALTER TABLE, online DDL для разделенных таблиц следуют тем же самым правилам, которые относятся к обычным таблицам. Для получения дополнительной информации см. раздел 16.12.8.

  • Столбец In-Place? показывает, которые операции позволяют ALGORITHM=INPLACE.

  • Столбец Copies Table? показывает, которые операции в состоянии избежать дорогой копирующей таблицу работы. Этот столбец главным образом обратен In-Place? за исключением того, что несколько операций позволяют ALGORITHM=INPLACE, но все еще вовлекают некоторое количество табличного копирования.
  • Столбец Allows Concurrent DML? показывает, которые операции могут быть выполнены полностью онлайн. Вы можете определить LOCK=NONE, чтобы утверждать, что полный параллелизм позволен во время DDL, но MySQL автоматически позволяет этот уровень параллелизма, когда можно. Когда параллельный DML позволен, параллельные запросы также всегда позволяются.
  • Столбец Allows Concurrent Queries? показывает, которые DDL-операции DDL позволяются запросам на таблице в то время, как работа происходит. Параллельный запрос позволен во время всех онлайн операции DDL. Вы можете определить LOCK=SHARED, чтобы утверждать, что параллельные запросы позволены во время DDL, но MySQL автоматически позволяет этот уровень параллелизма когда возможно.
  • Столбец Примечания объясняет любые исключения такие, как тогда, когда ответ зависит от установки параметра конфигурации или некоторого другого пункта в запросе DDL. Значения Yes* и No* указывают, что ответ зависит от этих дополнительных примечаний.

Таблица 16.9. Резюме состояния онлайн для операций DDL

ОперацияIn-Place? Copies Table? Allows Concurrent DML?Allows Concurrent Query? Примечания
CREATE INDEX , ADD INDEX Yes*No*Да ДаНекоторые ограничения для индекса FULLTEXT.
ADD FULLTEXT INDEXДаNo* НетДа Создание первого индекса FULLTEXT для таблицы, вовлекает табличную копию, если нет столбца FTS_DOC_ID. Последующие индексы FULLTEXT на той же самой таблице могут быть созданы оперативно.
ADD SPATIAL INDEX ДаНет НетДа Оптовая загрузка не поддержана.
RENAME INDEX ДаНет ДаДа Только изменяет табличные метаданные.
DROP INDEX ДаНет ДаДа Только изменяет табличные метаданные.
OPTIMIZE TABLE ДаДа ДаДа ALGORITHM=COPY используется, если old_alter_table=1 или включена опция mysqld --skip-new. OPTIMIZE TABLE использует онлайн DDL (ALGORITHM=INPLACE), не поддерживая таблицы с индексами FULLTEXT.
Установить значение по умолчанию для столбца. ДаНет ДаДа Только изменяет табличные метаданные.
Изменить для столбца значение auto-increment. ДаНетДа ДаИзменяет значение, сохраненное в памяти, а не в файле с данными.
Добавить ограничение внешнего ключаYes*No* ДаДа Чтобы избежать копировать таблицу, отключите foreign_key_checks во время создания ограничения.
Удалить ограничение внешнего ключаДаНет ДаДа foreign_key_checks может быть включена или отключена.
Переименовать столбецYes* No*Yes*Да Чтобы позволить параллельный DML, сохраните тот же самый тип данных и измените только имя столбца. ALGORITHM=INPLACE не поддержан для того, чтобы переименовать произведенный столбец.
ДобавитьYes* Yes*Yes*Да Параллельный DML не позволен, добавляя столбец auto-increment. Хотя ALGORITHM=INPLACE позволен, данные реорганизованы существенно, таким образом, это все еще дорогая работа. ALGORITHM=INPLACE поддержан для того, чтобы добавить произведенный виртуальный столбец, но не для того, чтобы добавить произведенный сохраненный столбец. Добавление произведенного виртуального столбца не требует табличной копии.
Удалить столбецДа Yes*ДаДа Хотя ALGORITHM=INPLACE позволен, данные реорганизованы существенно, таким образом, это все еще дорогая работа. ALGORITHM=INPLACE поддержан для того, чтобы удалить произведенный столбец. Удаление произведенного виртуального столбца не требует табличной копии.
Reorder columnsДа ДаДаДа Хотя ALGORITHM=INPLACE позволен, данные реорганизованы существенно, таким образом, это все еще дорогая работа.
Изменить свойства ROW_FORMAT ДаДаДа Да Хотя ALGORITHM=INPLACE позволен, данные реорганизованы существенно, таким образом, это все еще дорогая работа.
Изменить свойства KEY_BLOCK_SIZE ДаДаДа Да Хотя ALGORITHM=INPLACE позволен, данные реорганизованы существенно, таким образом, это все еще дорогая работа.
Сделать столбец NULL ДаДаДа Да Хотя ALGORITHM=INPLACE позволен, данные реорганизованы существенно, таким образом, это все еще дорогая работа.
Сделать столбец NOT NULL Yes*ДаДа ДаSTRICT_ALL_TABLES или STRICT_TRANS_TABLES SQL_MODE требуется для работы. Работа терпит неудачу, если столбец содержит значения NULL. Сервер запрещает изменения столбцов внешнего ключа, у которых есть потенциал, чтобы вызвать потерю ссылочной целостности. Для получения дополнительной информации см. раздел 14.1.7. Хотя ALGORITHM=INPLACE позволен, данные реорганизованы существенно, таким образом, это все еще дорогая работа.
Изменить тип столбцаNo* Yes*НетДа Исключение: VARCHAR может быть увеличен, используя онлайн ALTER TABLE.
Добавить primary keyYes*Да ДаДа Хотя ALGORITHM=INPLACE позволен, данные реорганизованы существенно, таким образом, это все еще дорогая работа. ALGORITHM=INPLACE не позволен при определенных условиях, если столбцы должны быть преобразованы в NOT NULL. См. Пример 16.9.
Удалить primary key и добавить другойДаДа ДаДа ALGORITHM=INPLACE позволен только, когда Вы добавляете новый первичный ключ в том же самом ALTER TABLE.
Удалить primary keyНетДа НетДа Ограничения применяются, когда Вы удаляете первичный ключ, не добавляя новый в том же самом ALTER TABLE.
Сменить набор символовНет ДаНетДа Пересоздает таблицу, если новая кодировка символов отличается.
Определить набор символовНет ДаНет ДаПересоздает таблицу, если новая кодировка символов отличается.
Пересоздать с опцией FORCE ДаДаДа ДаALGORITHM=COPY используется, если old_alter_table=1 или включена опция mysqld --skip-new. Пересоздание таблицы с использованием онлайн DDL (ALGORITHM=INPLACE) не поддержано для таблиц с индексами FULLTEXT.
Пересоздать с null ALTER TABLE ... ENGINE=INNODBДа ДаДаДа ALGORITHM=COPY используется, если old_alter_table=1 или включена опция mysqld --skip-new. Пересоздание таблицы с использованием онлайн DDL (ALGORITHM=INPLACE) не поддержано для таблиц с индексами FULLTEXT.
Установить постоянные опции статистики на уровне таблицы (STATS_PERSISTENT, STATS_AUTO_RECALC STATS_SAMPLE_PAGES). ДаНетДа Да Только изменяет табличные метаданные.

Следующие разделы показывают основной синтаксис и примечания использования, связанные с DDL онлайн, для каждой из главных операций, которые могут быть выполнены с параллельным DML:

Вторичные индексы

  • Создание вторичных индексов: CREATE INDEX name ON table (col_list) или ALTER TABLE table ADD INDEX name (col_list). Создание индекса FULLTEXT все еще требует блокировки таблицы.

  • Удаление вторичных индексов: DROP INDEX name ON table; или ALTER TABLE table DROP INDEX name

Создание и удаление вторичного индекса на таблице пропускает копирующее таблицу поведение.

Таблица остается доступной для чтения и записи в то время, как индекс создается или удаляется. CREATE INDEX или DROP INDEX заканчивается только после того, как все транзакции, которые получают доступ к таблице, завершены, чтобы начальное состояние индекса отразило новое содержание таблицы. Ранее изменение таблицы в то время, как индекс создается или удаляется, как правило, приводило к тупику, который отменял INSERT, UPDATE или DELETE.

Свойства столбца

  • Установите значение по умолчанию для столбца: ALTER TABLE tbl ALTER COLUMN col SET DEFAULT literal или ALTER TABLE tbl ALTER COLUMN col DROP DEFAULT

    Значения по умолчанию для столбцов сохранены в словаре данных.

  • Изменение значения auto-increment для столбца: ALTER TABLE table AUTO_INCREMENT=next_value;

    Особенно в распределенной системе, используя репликацию, Вы иногда сбрасываете счетчик автоинкремента для таблицы к определенному значению. Следующая строка, вставленная в таблицу, использует указанное значение для своего столбца auto-increment. Вы могли бы также использовать этот метод в окружающей среде складирования данных, где Вы периодически очищаете все таблицы и перезагружаете их и можете перезапустить последовательность автоинкремента от 1.

  • Переименование столбца: ALTER TABLE tbl CHANGE old_col_name new_col_name datatype

    Когда Вы сохраняете тот же самый тип данных и параметр [NOT] NULL, только изменяя имя столбца, эта работа может всегда выполняться онлайн.

    Вы можете также переименовать столбец, который является частью ограничения внешнего ключа. Определение внешнего ключа автоматически обновлено, чтобы использовать новое имя столбца. Переименование столбца, участвующего во внешнем ключе, работает только с оперативным режимом ALTER TABLE. Если Вы используете ALGORITHM=COPY или некоторое другое условие заставляет команду использовать ALGORITHM=COPY негласно, ALTER TABLE потерпит неудачу.

  • Изменение размера VARCHAR, используя оперативное ALTER TABLE , как в этом примере:
    ALTER TABLE t1 ALGORITHM=INPLACE, CHANGE COLUMN c1 c1 VARCHAR(255);
    

    Число байтов длины, требуемое столбцом VARCHAR, должно остаться тем же самым. Для VARCHAR от 0 до 255, один байт длины обязан кодировать значение. Для VARCHAR в 256 байт или больше надо два байта. В результате оперативный ALTER TABLE допускает только увеличение VARCHAR от 0 до 255 байт или увеличение размера от значения, равного или большего 256 байтов. Оперативный ALTER TABLE не поддерживает увеличение VARCHAR от значения меньше 256 байт до значения, равного или больше 256 байтов. В этом случае число необходимых байтов длины изменилось бы от 1 до 2, что поддержано только табличной копией (ALGORITHM=COPY). Например, попытка изменить размер столбца VARCHAR от 255 до 256, используя оперативный ALTER TABLE возвратила бы ошибку:

    ALTER TABLE t1 ALGORITHM=INPLACE, CHANGE COLUMN c1 c1 VARCHAR(256);
    ERROR 0A000: ALGORITHM=INPLACE is not supported. Reason: Cannot change
    column type INPLACE. Try ALGORITHM=COPY.
    

    Уменьшение размера VARCHAR, используя оперативный ALTER TABLE не поддержано. Уменьшение VARCHAR требует табличной копии (ALGORITHM=COPY).

Внешние ключи

  • Добавление или удаление ограничения внешнего ключа:

    ALTER TABLE tbl1 ADD CONSTRAINT fk_name
          FOREIGN KEY index (col1)
          REFERENCES tbl2(col2)
          referential_actions;
    ALTER TABLE tbl DROP FOREIGN KEY fk_name;
    

    Удаление внешнего ключа может быть выполнено онлайн с включенной или выключенной опцией foreign_key_checks. Создание внешнего ключа онлайн требует выключения foreign_key_checks.

    Если Вы не знаете названия ограничений внешнего ключа на особую таблицу, делаете следующее запрос и находите имя ограничения в параметре CONSTRAINT для каждого внешнего ключа:

    show create table table\G
    

    Или запросите таблицу information_schema.table_constraints и используйте столбцы constraint_name и constraint_type, чтобы идентифицировать имена внешнего ключа.

    Вы можете также удалить внешний ключ и его связанный индекс в единственном запросе:

    ALTER TABLE table DROP FOREIGN KEY constraint,
          DROP INDEX index;
    

Если внешние ключи уже присутствуют в измененной таблице (то есть, это дочерняя таблица, содержащая любой FOREIGN KEY ... REFERENCE), дополнительные ограничения относятся к операциям онлайн DDL, даже те, которые непосредственно не вовлекают столбцы внешнего ключа:

  • ALTER TABLE на дочерней таблице мог ждать завершения другой транзакции, если бы изменение родительской таблицы вызвало связанные изменения в дочерней таблице через ON UPDATE или ON DELETE, используя параметры CASCADE или SET NULL.

  • Таким же образом, если таблица родительская в отношениях внешнего ключа, даже при том, что это не содержит никакого FOREIGN KEY, это могло ждать конца ALTER TABLE, если INSERT, UPDATE или DELETE вызвал ON UPDATE или ON DELETE в дочерней таблице.

Замечания по ALGORITHM=COPY

Любая ALTER TABLE, выполненная с ALGORITHM=COPY, предотвращает параллельные операции DML. Параллельные запросы все еще позволены. Таким образом, копирующая таблицу работа всегда включает, по крайней мере, ограничения параллелизма LOCK=SHARED (позволяет запросы, но не DML). Вы можете далее ограничить параллелизм для таких операций, определяя LOCK=EXCLUSIVE, что предотвращает DML и запросы.

Параллельный DML, но табличная копия все еще необходима

Некоторый другой вызов ALTER TABLE позволяет параллельный DML, но все еще требует табличной копии.

  • Добавление, удаление или переупорядочивание столбцов.

  • Добавление или удаление primary key.
  • Изменение ROW_FORMAT или KEY_BLOCK_SIZE.
  • Изменение статуса nullable для столбца.
  • OPTIMIZE TABLE.
  • Пересоздание с опцией FORCE.
  • Пересоздание, используя null ALTER TABLE ... ENGINE=INNODB.

Поддержание CREATE TABLE

Поскольку Ваша схема базы данных развивается с новыми столбцами, типами данных, ограничениями, индексами и так далее, держите Ваш CREATE TABLE современным с последними табличными определениями. Даже с исполнительными усовершенствованиями DDL онлайн, более эффективно создать устойчивые структуры базы данных вначале, вместо того, чтобы создать часть схемы и затем использовать ALTER TABLE позже.

Основное исключение: вторичные индексы на таблицах с большими количествами строк. Является, как правило, самым эффективным составить таблицу со всеми деталями, кроме вторичного индекса, загрузите данные, затем создать вторичный индекс. Вы можете использовать тот же самый метод с внешними ключами, если Вы знаете, что исходные данные чисты и не нуждаются в проверках непротиворечивости во время процесса загрузки.

Безотносительно последовательности CREATE TABLE, CREATE INDEX , ALTER TABLE и подобных запросов, Вы можете получить SQL, который должен восстановить текущую форму таблицы, делая запрос SHOW CREATE TABLE table\G (верхний регистр \G нужен для опрятного форматирования). Этот вывод показывает такие пункты, как числовая точность, NOT NULL и CHARACTER SET, это иногда добавляется негласно, которые Вы можете не учесть, клонируя таблицу на новой системе или настраивая столбцы внешнего ключа с идентичным типом.

16.12.2. Работа и соображения параллелизма для Online DDL

Online DDL улучшает несколько аспектов работы MySQL, таких как работа, параллелизм, доступность и масштабируемость:

  • Поскольку запросы и операции DML на таблице могут продолжиться, в то время как DDL происходит, приложения, которые получают доступ к таблице, более отзывчивы. Уменьшенная блокировка и ожидание других ресурсов всюду по серверу MySQL приводят к большей масштабируемости, даже для операций, не вовлекающих измененную таблицу.

  • Для оперативных операций, избегая дискового ввода/вывода и циклов центрального процессора, чтобы пересоздать таблицу, Вы минимизируете полную загрузку базы данных и поддерживаете хорошую работу и высокую пропускную способность во время работы DDL.
  • Для оперативных операций, потому что меньше данных считано в буферный пул, чем если бы все данные были скопированы, Вы избегаете чистки данных, к которым часто получают доступ, что прежде могло вызвать временное исполнительное падение после работы DDL.

Если работа онлайн требует временных файлов, InnoDB создает их во временном каталоге по умолчанию, а не в каталоге, содержащем оригинальную таблицу. Если этот каталог не является достаточно большим, чтобы содержать такие файлы, Вы, возможно, должны установить tmpdir к иному каталогу. Альтернативно, Вы можете определить отдельный временный каталог для операций InnoDB online ALTER TABLE, применяя опцию innodb_tmpdir. Эта опция была введена, чтобы помочь избежать временных переполнений каталога, которые могли произойти в результате больших временных файлов, создаваемых во время онлайн ALTER TABLE . Подробности в разделе B.5.3.5.

Опции блокировки для Online DDL

В то время, как таблица InnoDB изменяется работой DDL, таблица может или не может быть блокирована, в зависимости от внутренних работ и параметра LOCK ALTER TABLE. По умолчанию MySQL использует такую небольшую блокировку, насколько возможно, во время работы DDL, Вы определяете параметр, чтобы сделать блокировку более сильной, чем обычно (таким образом ограничиваете параллельный DML или DML и запросов), или гарантировать, что некоторая ожидаемая степень блокировки позволена для работы. Если LOCK определяет уровень блокировки, которая не доступна для того определенного вида работы DDL, например, LOCK=SHARED или LOCK=NONE создавая или удаляя первичный ключ, пункт работает как утверждение, заставляя запрос потерпеть неудачу с ошибкой. Следующий список показывает различные возможности для LOCK, от самой разрешающей до самой строгой:

  • Для DDL с LOCK=NONE запросы и параллельный DML позволены. Этот пункт делает ALTER TABLE неудачым, если вид работы DDL не может быть выполнен с требуемым типом блокировки, так что определите LOCK=NONE, если хранение полностью доступной таблицы жизненно важно, и нормально отменять DDL, если это невозможно. Например, Вы могли бы использовать этот пункт в DDL для таблиц, вовлекающих потребительские регистрации или покупки, чтобы избежать делать те таблицы недоступными, по ошибке создав сложный ALTER TABLE.

  • Для DDL с LOCK=SHARED любые записи в таблицу (то есть, операции DML) заблокированы, но данные в таблице могут быть считаны. Этот пункт делает ALTER TABLE неудачным, если вид работы DDL не может быть выполнен с требуемым типом блокировки, так что определите LOCK=SHARED, если хранение таблицы, доступной для запросов, жизненно важно, и нормально отменять DDL, если это невозможно. Например, Вы могли бы использовать этот пункт в DDL для таблиц в хранилище данных, где нормально задерживать операции загрузки данных, пока DDL не закончен, но запросы не могут быть отсрочены в течение длительных периодов.
  • Для DDL с LOCK=DEFAULT или без LOCK MySQL использует самый низкий уровень блокировки, которая доступна для такой работы, позволяя параллельные запросы и DML везде, где возможно. Это установка, чтобы использовать, производя предварительно запланированные и проверенные изменения, которые Вы знаете, не будет вызывать проблем доступности, основанных на рабочей нагрузке для этой таблицы.
  • Для DDL с LOCK=EXCLUSIVE блокировано все. Этот пункт делает ALTER TABLE неудачным, если вид работы DDL не может быть выполнен с требуемым типом блокировки, так что определите LOCK=EXCLUSIVE, если первоочередная задача заканчивает DDL в самое короткое возможное время, и нормально, что заявки ждут, когда они пытаются получить доступ к таблице. Вы могли бы также использовать LOCK=EXCLUSIVE, если сервер, как предполагается, неактивен, чтобы избегать неожиданных доступов к таблице.

В зависимости от внутренних работ online DDL и LOCK в ALTER TABLE, online DDL может ждать того, чтобы в настоящее время выполняемые транзакции, которые получают доступ к таблице, завершились прежде, чем завершиться, потому что эксклюзивный доступ к таблице требуется в течение краткого времени во время начальных и заключительных фаз работы DDL. Эти online DDL также ждут завершения получающих доступ к таблице транзакций, запущенных в то время, как DDL происходит. Следовательно, в случае долгого рабочего операционного выполнения вставки, обновления, удаления или SELECT ... FOR UPDATE на таблице, онлайн ALTER TABLE может исчерпать время, поскольку это ждет эксклюзивного доступа к таблице. Операции DML, которые выполнены на таблице в то время, как онлайн ALTER TABLE ждет исключительной табличной блокировки, могут также быть заблокированы.

Поскольку есть некоторая работа обработки, связанная с записью изменений, произведенных параллельными операциями DML, затем применяя те изменения в конце, работа DDL онлайн могла занять больше времени, чем механизм в старинном стиле, который блокирует табличный доступ от других сеансов. Сокращение сырой работы сбалансировано относительно лучшего отклика для приложений, которые используют таблицу. Оценивая идеальные методы для структуры изменения таблицы, рассмотрите восприятие конечного пользователя работы, основанной на факторах, таких как времена загрузки для веб-страниц.

Недавно создаваемый вторичный индекс \содержит только преданные данные в таблице в то время, как CREATE INDEX или ALTER TABLE заканчивает выполняться. Это не содержит нейтральных значений, старых версий значений или отмеченных для удаления значений.

Исполнение оперативных операций DDL против копирующих таблицу

Сырое исполнение работы DDL онлайн в значительной степени определено тем, выполнена ли работа оперативно или требует копирования и восстановления всей таблицы. См. таблицу 16.9 , чтобы видеть, какие виды операций могут быть выполнены оперативно, и любые требования для того, чтобы избежать операций табличной копии.

Исполнительное ускорение от оперативного DDL относится к операциям на вторичном индексе, не к первичному ключу. Строки таблицы InnoDB сохранены в кластеризируемом индексе организованном, основываясь на primary key, формируя то, что некоторые системы базы данных называют index-organized table. Поскольку структура таблицы близко связана с первичным ключом, пересмотр первичного ключа все еще требует копирования данных.

Когда работа с первичным ключом использует ALGORITHM=INPLACE, даже при том, что данные все еще скопированы, это более эффективно, чем использование ALGORITHM=COPY:

  • Никакое журналирование отмены не требуется для ALGORITHM=INPLACE. Эти операции добавляют издержки к запросам DDL, которые используют ALGORITHM=COPY.

  • Вторичные индексные записи, предварительно сортированы и могут быть загружены в нужном порядке.
  • Буфер изменения не используется, потому что нет никаких произвольных вставок во вторичный индекс.

Чтобы судить относительное исполнение операций DDL онлайн, Вы можете выполнить такие операции на большой таблице InnoDB, используя текущие и более ранние версии MySQL. Вы можете также выполнить все тесты производительности под последней версией MySQL, моделируя предыдущее поведение DDL для предыдущих результатов, устанавливая old_alter_table. Скомандуйте set old_alter_table=1 в сеансе и примените DDL, чтобы сделать запись предварительных чисел. Затем верните set old_alter_table=0, чтобы повторно включить более новое, более быстрое поведение и выполните операции DDL снова, чтобы сделать запись чисел после .

Для основной идеи о том, делает ли работа DDL свои оперативные изменения или выполняет табличную копию, см. значение rows affected , выведенное на экран после того, как команда заканчивается. Например, вот строки, которые Вы могли бы видеть после выполнения различных типов операций DDL:

  • Изменяя значение по умолчанию столбца (сверхбыстро, не затрагивает табличные данные вообще):

    Query OK, 0 rows affected (0.07 sec)
    
  • Добавление индексирования (занимает время, но 0 rows affected говорит, что таблица не скопирована):
    Query OK, 0 rows affected (21.42 sec)
    
  • Изменение типа данных столбца (занимает время и действительно требует пересоздания всех строк таблицы):
    Query OK, 1671168 rows affected (1 min 35.54 sec)
    

    Изменение типа данных столбца требует восстановления всех строк таблицы за исключением изменения размера VARCHAR , который может быть выполнен, используя онлайн ALTER TABLE.

Например, прежде, чем выполнить работу DDL на большой таблице, Вы могли бы проверить, будет ли работа быстра или замедлится следующим образом:

  1. Клонируйте структуру таблицы.

  2. Заполните клонированную таблицу крошечным объемом данных.
  3. Выполните работу DDL на клонированной таблице.
  4. Проверьте, является ли rows affected нолем или нет. Ненулевое значение означает, что работа потребует восстановления всей таблицы, которая могла бы потребовать специального планирования. Например, Вы могли бы сделать работу DDL во время периода запланированного времени простоя, или на каждом ведомом сервере репликации по одному.

Для более глубокого понимания сокращения обработки MySQL, исследуйте таблицы performance_schema и INFORMATION_SCHEMA, связанные с InnoDB, до и после DDL, чтобы видеть число физических чтений, записей, распределения памяти и так далее.

16.12.3. Синтаксис SQL для онлайн DDL

Как правило, Вы не должны сделать ничего специального, чтобы включить online DDL, используя ALTER TABLE. См. таблицу 16.9 для видов операций DDL, которые могут быть выполнены оперативно, позволяя параллельный DML. Некоторые изменения требуют особых комбинаций настроек конфигурации или параметров ALTER TABLE .

Вы можете управлять различными аспектами особой работы DDL онлайн при использовании LOCK и ALGORITHM в ALTER TABLE. Эти пункты стоят в конце запроса, отделенные от таблицы и технических требований столбца запятыми. LOCK полезен для точной настройки степени параллельного доступа к таблице. ALGORITHM прежде всего предназначен для исполнительных сравнений и как отступление к более старому копирующему таблицу поведению в случае, если Вы сталкиваетесь с любыми проблемами с существующим кодом DDL. Например:

  • Чтобы избежать случайно сделать таблицу недоступной, определите в ALTER TABLE параметр LOCK=NONE (разрешает чтения и записи) LOCK=SHARED (только чтения). Работа немедленно останавливается, если требуемый уровень параллелизма недоступен.

  • Чтобы сравнить работу, выполните запрос с ALGORITHM=INPLACE и другой с ALGORITHM=COPY, как альтернатива установке опции old_alter_table.
  • Избегайте связывать сервер операцией ALTER TABLE, которая копирует таблицу, включая ALGORITHM=INPLACE. Запрос немедленно останавливается, если не может использовать оперативный механизм. См. таблицу 16.9 для списка операций DDL, которые могут или не могут быть выполнены оперативно.

См. раздел 16.12.2 для большего количества деталей о LOCK. Для полных примеров использования онлайн DDL см. раздел 16.12.5.

16.12.4. Объединение или отделение запросов DDL

Перед введением online DDL было обычной практикой объединить много операций DDL в один запрос ALTER TABLE. Поскольку каждый ALTER TABLE вовлекал копирование и восстановление таблицы, было более эффективно произвести несколько изменений в той же самой таблице сразу, так как те изменения могли все быть сделаны сразу. Проблема была в том, что код SQL, вовлекающий операции DDL, было трудно поддержать и снова использовать в различных скриптах. Определенные изменения отличались каждый раз, когда Вам, возможно, придется создать новый ALTER TABLE для каждого немного отличающегося скрипта.

Для DDL, которые могут быть сделаны оперативно, как показано в таблице 16.9, теперь Вы можете разделить их на отдельные ALTER TABLE для более легких сценариев и обслуживания, не жертвуя эффективностью. Например, Вы могли бы взять сложный запрос, такой как:

ALTER TABLE t1 ADD INDEX i1(c1), ADD UNIQUE INDEX i2(c2),
      CHANGE c4_old_name c4_new_name INTEGER UNSIGNED;

и поделить это на более простые части, которые могут быть проверены и выполнены независимо:

ALTER TABLE t1 ADD INDEX i1(c1);
ALTER TABLE t1 ADD UNIQUE INDEX i2(c2);
ALTER TABLE t1 CHANGE c4_old_name c4_new_name INTEGER UNSIGNED NOT NULL;

Вы могли бы все еще использовать многослойный ALTER TABLE для:

  • Операции, которые должны быть выполнены в определенной последовательности, такие как создание индексирования, сопровождаемого ограничением внешнего ключа.

  • Операции, которые не могут быть выполнены оперативно, то есть, все еще копируют таблицу.
  • Операции, для которых Вы определяете ALGORITHM=COPY или old_alter_table=1 , чтобы вызвать копирующее таблицу поведение если нужно для точной прежней совместимости в специализированных ситуациях.

16.12.5. Примеры Online DDL

Вот примеры кода, показывающих некоторые операции, работа которых, параллелизм и масштабируемость улучшены последними улучшениями online DDL.

  • Пример 16.1 настраивает таблицы BIG_TABLE и SMALL_TABLE, используемые в последующих примерах.

  • Пример 16.2 иллюстрирует исполнительные аспекты создания и удаления индексов.
  • Пример 16.3 показывает запросы DML, работающие во время DROP INDEX.
  • Пример 16.4 демонстрирует усовершенствование скорости для того, чтобы переименовать столбец, и показывает, что важно сохранить тип данных точно тем же самым, делая переименование.
  • Пример 16.5 демонстрирует, как внешние ключи работают с DDL онлайн. Поскольку две таблицы вовлечены в операции внешнего ключа, есть дополнительные соображения блокировки. Таким образом, у таблиц с внешними ключами иногда есть ограничения для операций DDL онлайн.
  • Пример 16.6 демонстрирует, как столбцы auto-increment работают с DDL онлайн. У таблиц со столбцами auto-increment иногда есть ограничения для операций DDL онлайн.
  • Пример 16.7 демонстрирует опции, чтобы разрешить или ограничить параллельные запросы и операции DML, в то время как работа DDL онлайн происходит. Это показывает ситуации, когда запрос DDL или параллельная транзакция могли бы ждать, или параллельная транзакция могла бы отменить запрос DML из-за ошибки тупика.
  • Пример 16.8 демонстрирует создание и удаление нескольких индексов в в единственном запросе, которое может быть более эффективным, чем использование отдельного запроса для каждого индекса.
  • Пример 16.9 демонстрирует, как более эффективно определить primary key, составляя таблицу, и относительно дорого добавить еще один позже.

Пример 16.1. Установки схемы для экспериментов DDL онлайн

Вот код, который настраивает начальные таблицы, используемые в этих демонстрациях:

/*
Setup code for the online DDL demonstration:
- Set up some config variables.
- Create 2 tables that are clones of one of the INFORMATION_SCHEMA tables
  that always has some data. The "small" table has a couple of thousand rows.
  For the "big" table, keep doubling the data until it reaches over a million rows.
- Set up a primary key for the sample tables, since we are demonstrating InnoDB aspects.
*/

set autocommit = 0;
set foreign_key_checks = 1;
set global innodb_file_per_table = 1;
set old_alter_table=0;
prompt mysql:

use test;

\! echo "Setting up 'small' table:"
drop table if exists small_table;
create table small_table as select * from information_schema.columns;
alter table small_table add id int unsigned not null primary key auto_increment;
select count(id) from small_table;

\! echo "Setting up 'big' table:"
drop table if exists big_table;
create table big_table as select * from information_schema.columns;
show create table big_table\G

insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
insert into big_table select * from big_table;
commit;

alter table big_table add id int unsigned not null primary key auto_increment;
select count(id) from big_table;

Running this code gives this output, condensed for brevity and with the most important points bolded:

Setting up 'small' table:
Query OK, 0 rows affected (0.01 sec)

Query OK, 1678 rows affected (0.13 sec)
Records: 1678  Duplicates: 0  Warnings: 0

Query OK, 1678 rows affected (0.07 sec)
Records: 1678  Duplicates: 0  Warnings: 0
+-----------+
| count(id) |
+-----------+
|  1678 |
+-----------+
1 row in set (0.00 sec)

Setting up 'big' table:
Query OK, 0 rows affected (0.16 sec)

Query OK, 1678 rows affected (0.17 sec)
Records: 1678  Duplicates: 0  Warnings: 0

*************************** 1. row ***************************
   Table: big_table
Create Table: CREATE TABLE `big_table` (
  `TABLE_CATALOG` varchar(512) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_SCHEMA` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `ORDINAL_POSITION` bigint(21) unsigned NOT NULL DEFAULT '0',
  `COLUMN_DEFAULT` longtext CHARACTER SET utf8,
  `IS_NULLABLE` varchar(3) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `DATA_TYPE` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `CHARACTER_MAXIMUM_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_OCTET_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_SCALE` bigint(21) unsigned DEFAULT NULL,
  `DATETIME_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_SET_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLLATION_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLUMN_TYPE` longtext CHARACTER SET utf8 NOT NULL,
  `COLUMN_KEY` varchar(3) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `EXTRA` varchar(30) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `PRIVILEGES` varchar(80) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_COMMENT` varchar(1024) CHARACTER SET utf8 NOT NULL DEFAULT ''
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

Query OK, 1678 rows affected (0.09 sec)
Records: 1678  Duplicates: 0  Warnings: 0

Query OK, 3356 rows affected (0.07 sec)
Records: 3356  Duplicates: 0  Warnings: 0

Query OK, 6712 rows affected (0.17 sec)
Records: 6712  Duplicates: 0  Warnings: 0

Query OK, 13424 rows affected (0.44 sec)
Records: 13424  Duplicates: 0  Warnings: 0

Query OK, 26848 rows affected (0.63 sec)
Records: 26848  Duplicates: 0  Warnings: 0

Query OK, 53696 rows affected (1.72 sec)
Records: 53696  Duplicates: 0  Warnings: 0

Query OK, 107392 rows affected (3.02 sec)
Records: 107392  Duplicates: 0  Warnings: 0

Query OK, 214784 rows affected (6.28 sec)
Records: 214784  Duplicates: 0  Warnings: 0

Query OK, 429568 rows affected (13.25 sec)
Records: 429568  Duplicates: 0  Warnings: 0

Query OK, 859136 rows affected (28.16 sec)
Records: 859136  Duplicates: 0  Warnings: 0

Query OK, 0 rows affected (0.03 sec)
Query OK, 1718272 rows affected (1 min 9.22 sec)
Records: 1718272  Duplicates: 0  Warnings: 0
+-----------+
| count(id) |
+-----------+
|   1718272 |
+-----------+
1 row in set (1.75 sec)

Пример 16.2. Скорость и эффективность CREATE INDEX и DROP INDEX

Вот последовательность запросов, демонстрирующих относительную скорость CREATE INDEX и DROP INDEX. Для маленькой таблицы прошедшее время меньше, чем секунда, используем ли мы быстрый или медленный метод, таким образом, мы смотрим на rows affected, чтобы проверить, какие операции могут избежать пересоздания таблицы. Для большой таблицы различие в эффективности очевидно, потому что пропуск пересоздания таблицы экономит существенное время.

\! clear

\! echo "=== Create and drop index (small table, new/fast technique) ==="
\! echo
\! echo "Data size (kilobytes) before index created: "
\! du -k data/test/small_table.ibd
create index i_dtyp_small on small_table (data_type), algorithm=inplace;
\! echo "Data size after index created: "
\! du -k data/test/small_table.ibd
drop index i_dtyp_small on small_table, algorithm=inplace;

-- Compare against the older slower DDL.

\! echo "=== Create and drop index (small table, old/slow technique) ==="
\! echo
\! echo "Data size (kilobytes) before index created: "
\! du -k data/test/small_table.ibd
create index i_dtyp_small on small_table (data_type), algorithm=copy;
\! echo "Data size after index created: "
\! du -k data/test/small_table.ibd
drop index i_dtyp_small on small_table, algorithm=copy;

-- In the above example, we examined the "rows affected" number,
-- ideally looking for a zero figure. Let's try again with a larger
-- sample size, where we'll see that the actual time taken can
-- vary significantly.

\! echo "=== Create and drop index (big table, new/fast technique) ==="
\! echo
\! echo "Data size (kilobytes) before index created: "
\! du -k data/test/big_table.ibd
create index i_dtyp_big on big_table (data_type), algorithm=inplace;
\! echo "Data size after index created: "
\! du -k data/test/big_table.ibd
drop index i_dtyp_big on big_table, algorithm=inplace;

\! echo "=== Create and drop index (big table, old/slow technique) ==="
\! echo
\! echo "Data size (kilobytes) before index created: "
\! du -k data/test/big_table.ibd
create index i_dtyp_big on big_table (data_type), algorithm=copy;
\! echo "Data size after index created: "
\! du -k data/test/big_table.ibd
drop index i_dtyp_big on big_table, algorithm=copy;

Выполнение этого кода дает этот вывод, сжатый для краткости и с выделенными наиболее важными моментами:

Query OK, 0 rows affected (0.00 sec)

=== Create and drop index (small table, new/fast technique) ===

Data size (kilobytes) before index created:
384  data/test/small_table.ibd
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

Data size after index created:
432  data/test/small_table.ibd
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

Query OK, 0 rows affected (0.00 sec)

=== Create and drop index (small table, old/slow technique) ===

Data size (kilobytes) before index created:
432  data/test/small_table.ibd
Query OK, 1678 rows affected (0.12 sec)
Records: 1678  Duplicates: 0  Warnings: 0

Data size after index created:
448  data/test/small_table.ibd
Query OK, 1678 rows affected (0.10 sec)
Records: 1678  Duplicates: 0  Warnings: 0

Query OK, 0 rows affected (0.00 sec)

=== Create and drop index (big table, new/fast technique) ===

Data size (kilobytes) before index created:
315392  data/test/big_table.ibd
Query OK, 0 rows affected (33.32 sec)
Records: 0  Duplicates: 0  Warnings: 0

Data size after index created:
335872  data/test/big_table.ibd
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

Query OK, 0 rows affected (0.00 sec)

=== Create and drop index (big table, old/slow technique) ===

Data size (kilobytes) before index created:
335872  data/test/big_table.ibd
Query OK, 1718272 rows affected (1 min 5.01 sec)
Records: 1718272  Duplicates: 0  Warnings: 0

Data size after index created:
348160  data/test/big_table.ibd
Query OK, 1718272 rows affected (46.59 sec)
Records: 1718272  Duplicates: 0  Warnings: 0

Пример 16.3. Параллельные DML во время DML CREATE INDEX и DROP INDEX

Вот некоторые отрывки кода, которые выполнены в отдельных сессиях mysql, соединенных с той же самой базой данных, чтобы иллюстрировать запрос DML (вставка, обновление или удаление), работающий в то же самое время, как CREATE INDEX и DROP INDEX.

/*
CREATE INDEX statement to run against a table while
insert/update/delete statements are modifying the
column being indexed.
*/

-- Run this script in one session, while simultaneously creating and dropping
-- an index on test/big_table.table_name in another session.

use test;
create index i_concurrent on big_table(table_name);

/*
DROP INDEX statement to run against a table while
insert/update/delete statements are modifying the
column being indexed.
*/

-- Run this script in one session, while simultaneously creating and dropping
-- an index on test/big_table.table_name in another session.

use test;
drop index i_concurrent on big_table;

/*
Some queries and insert/update/delete statements to run against a table
while an index is being created or dropped. Previously, these operations
would have stalled during the index create/drop period and possibly
timed out or deadlocked.
*/

-- Run this script in one session, while simultaneously creating and dropping
-- an index on test/big_table.table_name in another session.

-- In the test instance, that column has about 1.7M rows, with 136 different values.
-- Sample values: COLUMNS (20480), ENGINES (6144), EVENTS (24576), FILES (38912),
-- TABLES (21504), VIEWS (10240).

set autocommit = 0;
use test;

select distinct character_set_name from big_table where table_name = 'FILES';
delete from big_table where table_name = 'FILES';
select distinct character_set_name from big_table where table_name = 'FILES';

-- I'll issue the final rollback interactively, not via script,
-- the better to control the timing.
-- rollback;

Выполнение этого кода дает этот вывод, сжатый для краткости и с выделенными наиболее важными моментами:

mysql: source concurrent_ddl_create.sql
Database changed
Query OK, 0 rows affected (1 min 25.15 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql: source concurrent_ddl_drop.sql
Database changed
Query OK, 0 rows affected (24.98 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql: source concurrent_dml.sql
Query OK, 0 rows affected (0.00 sec)

Database changed
+--------------------+
| character_set_name |
+--------------------+
| NULL               |
| utf8               |
+--------------------+
2 rows in set (0.32 sec)

Query OK, 38912 rows affected (1.84 sec)
Empty set (0.01 sec)

mysql: rollback;
Query OK, 0 rows affected (1.05 sec)

Пример 16.4. Переименование столбца

Вот демонстрация использования ALTER TABLE, чтобы переименовать столбец. Мы используем новый быстрый механизм DDL, чтобы изменить название, потом старый механизм DDL (с old_alter_table=1), чтобы восстановить оригинальное имя столбца.

Замечания:

  • Поскольку синтаксис для того, чтобы переименовать столбец также вовлекает переопределение типа данных, надо определить точно тот же самый тип данных, чтобы избежать пересоздания таблицы. В этом случае смотрим вывод show create table table\G и важные параметры CHARACTER SET и NOT NULL берем из оригинального определения столбца.

  • Переименование столбца для маленькой таблицы достаточно быстро, так что мы должны исследовать rows affected, чтобы проверить, что новый механизм DDL более эффективен, чем старый. С большой таблицей различие в прошедшем времени делает усовершенствование очевидным.

/*
Run through a sequence of 'rename column' statements.
Because this operation involves only metadata, not table data,
it is fast for big and small tables, with new or old DDL mechanisms.
*/

\! clear
\! echo "Rename column (fast technique, small table):"
alter table small_table change `IS_NULLABLE` `NULLABLE` varchar(3) character
  set utf8 not null, algorithm=inplace;
\! echo "Rename back to original name (slow technique):"
alter table small_table change `NULLABLE` `IS_NULLABLE` varchar(3) character
  set utf8 not null, algorithm=copy;


\! echo "Rename column (fast technique, big table):"
alter table big_table change `IS_NULLABLE` `NULLABLE` varchar(3) character
  set utf8 not null, algorithm=inplace;
\! echo "Rename back to original name (slow technique):"
alter table big_table change `NULLABLE` `IS_NULLABLE` varchar(3) character
  set utf8 not null, algorithm=copy;

Выполнение этого кода дает этот вывод, сжатый для краткости и с выделенными наиболее важными моментами:

Rename column (fast technique, small table):
Query OK, 0 rows affected (0.05 sec)

Query OK, 0 rows affected (0.13 sec)
Records: 0  Duplicates: 0  Warnings: 0

Rename back to original name (slow technique):
Query OK, 0 rows affected (0.00 sec)

Query OK, 1678 rows affected (0.35 sec)
Records: 1678  Duplicates: 0  Warnings: 0

Rename column (fast technique, big table):
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.11 sec)
Records: 0  Duplicates: 0  Warnings: 0

Rename back to original name (slow technique):
Query OK, 0 rows affected (0.00 sec)

Query OK, 1718272 rows affected (1 min 0.00 sec)
Records: 1718272  Duplicates: 0  Warnings: 0

Query OK, 0 rows affected (0.00 sec)

Пример 16.5. Удаление Foreign Keys

Вот демонстрация внешних ключей, включая усовершенствование скорости удаления ограничения внешнего ключа.

/*
Demonstrate aspects of foreign keys that are or aren't affected by the DDL improvements.
- Create a new table with only a few values to serve as the parent table.
- Set up the 'small' and 'big' tables as child tables using a foreign key.
- Verify that the ON DELETE CASCADE clause makes changes ripple from parent to child tables.
- Drop the foreign key constraints, and optionally associated indexes. (This is the operation that is sped up.)
*/

\! clear

-- Make sure foreign keys are being enforced, and allow
-- rollback after doing some DELETEs that affect both
-- parent and child tables.
set foreign_key_checks = 1;
set autocommit = 0;

-- Create a parent table, containing values that we know are already present
-- in the child tables.
drop table if exists schema_names;
create table schema_names (id int unsigned not null primary key
       auto_increment, schema_name varchar(64) character set utf8 not null,
       index i_schema (schema_name)) as select distinct
       table_schema schema_name from small_table;

show create table schema_names\G
show create table small_table\G
show create table big_table\G

-- Creating the foreign key constraint still involves a table rebuild when foreign_key_checks=1,
-- as illustrated by the "rows affected" figure.
alter table small_table add constraint small_fk foreign key i_table_schema (table_schema)
  references schema_names(schema_name) on delete cascade;
alter table big_table add constraint big_fk foreign key i_table_schema (table_schema)
  references schema_names(schema_name) on delete cascade;

show create table small_table\G
show create table big_table\G

select schema_name from schema_names order by schema_name;
select count(table_schema) howmany, table_schema from small_table
       group by table_schema;
select count(table_schema) howmany, table_schema from big_table
       group by table_schema;

-- big_table is the parent table.
-- schema_names is the parent table.
-- big_table is the child table.
-- (One row in the parent table can have many "children" in the child table.)
-- Changes to the parent table can ripple through to the child table.
-- For example, removing the value 'test' from schema_names.schema_name will
-- result in the removal of 20K or so rows from big_table.

delete from schema_names where schema_name = 'test';
select schema_name from schema_names order by schema_name;
select count(table_schema) howmany, table_schema from small_table
       group by table_schema;
select count(table_schema) howmany, table_schema from big_table
       group by table_schema;

-- Because we've turned off autocommit, we can still get back those deleted rows
-- if the DELETE was issued by mistake.
rollback;

select schema_name from schema_names order by schema_name;
select count(table_schema) howmany, table_schema from small_table
       group by table_schema;
select count(table_schema) howmany, table_schema from big_table
       group by table_schema;

-- All of the cross-checking between parent and child tables would be
-- deadly slow if there wasn't the requirement for the corresponding
-- columns to be indexed!

-- But we can get rid of the foreign key using a fast operation
-- that doesn't rebuild the table.
-- If we didn't specify a constraint name when setting up the foreign key, we would
-- have to find the auto-generated name such as 'big_table_ibfk_1' in the
-- output from 'show create table'.

-- For the small table, drop the foreign key and the associated index.
-- Having an index on a small table is less critical.

\! echo "DROP FOREIGN KEY and INDEX from small_table:"
alter table small_table drop foreign key small_fk, drop index small_fk;

-- For the big table, drop the foreign key and leave the associated index.
-- If we are still doing queries that reference the indexed column, the index is
-- very important to avoid a full table scan of the big table.
\! echo "DROP FOREIGN KEY from big_table:"
alter table big_table drop foreign key big_fk;
show create table small_table\G
show create table big_table\G

Выполнение этого кода дает этот вывод, сжатый для краткости и с выделенными наиболее важными моментами:

Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 4 rows affected (0.03 sec)
Records: 4  Duplicates: 0  Warnings: 0

*************************** 1. row ***************************
   Table: schema_names
Create Table: CREATE TABLE `schema_names` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `schema_name` varchar(64) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`id`), KEY `i_schema` (`schema_name`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

*************************** 1. row ***************************
   Table: small_table
Create Table: CREATE TABLE `small_table` (
  `TABLE_CATALOG` varchar(512) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_SCHEMA` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `ORDINAL_POSITION` bigint(21) unsigned NOT NULL DEFAULT '0',
  `COLUMN_DEFAULT` longtext CHARACTER SET utf8,
  `IS_NULLABLE` varchar(3) CHARACTER SET utf8 NOT NULL,
  `DATA_TYPE` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `CHARACTER_MAXIMUM_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_OCTET_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_SCALE` bigint(21) unsigned DEFAULT NULL,
  `DATETIME_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_SET_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLLATION_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLUMN_TYPE` longtext CHARACTER SET utf8 NOT NULL,
  `COLUMN_KEY` varchar(3) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `EXTRA` varchar(30) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `PRIVILEGES` varchar(80) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_COMMENT` varchar(1024) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1679
  DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

*************************** 1. row ***************************
   Table: big_table
Create Table: CREATE TABLE `big_table` (
  `TABLE_CATALOG` varchar(512) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_SCHEMA` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `ORDINAL_POSITION` bigint(21) unsigned NOT NULL DEFAULT '0',
  `COLUMN_DEFAULT` longtext CHARACTER SET utf8,
  `IS_NULLABLE` varchar(3) CHARACTER SET utf8 NOT NULL,
  `DATA_TYPE` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `CHARACTER_MAXIMUM_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_OCTET_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_SCALE` bigint(21) unsigned DEFAULT NULL,
  `DATETIME_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_SET_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLLATION_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLUMN_TYPE` longtext CHARACTER SET utf8 NOT NULL,
  `COLUMN_KEY` varchar(3) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `EXTRA` varchar(30) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `PRIVILEGES` varchar(80) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_COMMENT` varchar(1024) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`),
  KEY `big_fk` (`TABLE_SCHEMA`)
) ENGINE=InnoDB AUTO_INCREMENT=1718273 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

Query OK, 1678 rows affected (0.10 sec)
Records: 1678  Duplicates: 0  Warnings: 0

Query OK, 1718272 rows affected (1 min 14.54 sec)
Records: 1718272  Duplicates: 0  Warnings: 0

*************************** 1. row ***************************
   Table: small_table
Create Table: CREATE TABLE `small_table` (
  `TABLE_CATALOG` varchar(512) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_SCHEMA` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `ORDINAL_POSITION` bigint(21) unsigned NOT NULL DEFAULT '0',
  `COLUMN_DEFAULT` longtext CHARACTER SET utf8,
  `IS_NULLABLE` varchar(3) CHARACTER SET utf8 NOT NULL,
  `DATA_TYPE` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `CHARACTER_MAXIMUM_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_OCTET_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_SCALE` bigint(21) unsigned DEFAULT NULL,
  `DATETIME_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_SET_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLLATION_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLUMN_TYPE` longtext CHARACTER SET utf8 NOT NULL,
  `COLUMN_KEY` varchar(3) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `EXTRA` varchar(30) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `PRIVILEGES` varchar(80) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_COMMENT` varchar(1024) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`),
  KEY `small_fk` (`TABLE_SCHEMA`),
  CONSTRAINT `small_fk` FOREIGN KEY (`TABLE_SCHEMA`)
REFERENCES `schema_names` (`schema_name`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1679 DEFAULT CHARSET=latin1
1 row in set (0.12 sec)

*************************** 1. row ***************************
   Table: big_table
Create Table: CREATE TABLE `big_table` (
  `TABLE_CATALOG` varchar(512) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_SCHEMA` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `ORDINAL_POSITION` bigint(21) unsigned NOT NULL DEFAULT '0',
  `COLUMN_DEFAULT` longtext CHARACTER SET utf8,
  `IS_NULLABLE` varchar(3) CHARACTER SET utf8 NOT NULL,
  `DATA_TYPE` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `CHARACTER_MAXIMUM_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_OCTET_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_SCALE` bigint(21) unsigned DEFAULT NULL,
  `DATETIME_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_SET_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLLATION_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLUMN_TYPE` longtext CHARACTER SET utf8 NOT NULL,
  `COLUMN_KEY` varchar(3) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `EXTRA` varchar(30) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `PRIVILEGES` varchar(80) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_COMMENT` varchar(1024) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT, PRIMARY KEY (`id`),
  KEY `big_fk` (`TABLE_SCHEMA`),
  CONSTRAINT `big_fk` FOREIGN KEY (`TABLE_SCHEMA`)
  REFERENCES `schema_names` (`schema_name`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1718273 DEFAULT CHARSET=latin1
1 row in set (0.01 sec)

+--------------------+
| schema_name        |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.00 sec)

+---------+--------------------+
| howmany | table_schema       |
+---------+--------------------+
| 563     | information_schema |
| 286     | mysql              |
| 786     | performance_schema |
|  43     | test               |
+---------+--------------------+
4 rows in set (0.01 sec)

+---------+--------------------+
| howmany | table_schema       |
+---------+--------------------+
|  576512 | information_schema |
|  292864 | mysql              |
|  804864 | performance_schema |
|   44032 | test               |
+---------+--------------------+
4 rows in set (2.10 sec)
Query OK, 1 row affected (1.52 sec)

+--------------------+
| schema_name        |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
+--------------------+
3 rows in set (0.00 sec)

+---------+--------------------+
| howmany | table_schema       |
+---------+--------------------+
| 563     | information_schema |
| 286     | mysql              |
| 786     | performance_schema |
+---------+--------------------+
3 rows in set (0.00 sec)

+---------+--------------------+
| howmany | table_schema       |
+---------+--------------------+
|  576512 | information_schema |
|  292864 | mysql              |
|  804864 | performance_schema |
+---------+--------------------+
3 rows in set (1.74 sec)
Query OK, 0 rows affected (0.60 sec)

+--------------------+
| schema_name        |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| test               |
+--------------------+
4 rows in set (0.00 sec)

+---------+--------------------+
| howmany | table_schema       |
+---------+--------------------+
| 563     | information_schema |
| 286     | mysql              |
| 786     | performance_schema |
|  43     | test               |
+---------+--------------------+
4 rows in set (0.01 sec)

+---------+--------------------+
| howmany | table_schema       |
+---------+--------------------+
|  576512 | information_schema |
|  292864 | mysql              |
|  804864 | performance_schema |
|   44032 | test               |
+---------+--------------------+
4 rows in set (1.59 sec)

DROP FOREIGN KEY and INDEX from small_table:
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

DROP FOREIGN KEY from big_table:
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

*************************** 1. row ***************************
   Table: small_table
Create Table: CREATE TABLE `small_table` (
  `TABLE_CATALOG` varchar(512) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_SCHEMA` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `ORDINAL_POSITION` bigint(21) unsigned NOT NULL DEFAULT '0',
  `COLUMN_DEFAULT` longtext CHARACTER SET utf8,
  `IS_NULLABLE` varchar(3) CHARACTER SET utf8 NOT NULL,
  `DATA_TYPE` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `CHARACTER_MAXIMUM_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_OCTET_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_SCALE` bigint(21) unsigned DEFAULT NULL,
  `DATETIME_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_SET_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLLATION_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLUMN_TYPE` longtext CHARACTER SET utf8 NOT NULL,
  `COLUMN_KEY` varchar(3) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `EXTRA` varchar(30) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `PRIVILEGES` varchar(80) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_COMMENT` varchar(1024) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1679
  DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

*************************** 1. row ***************************
   Table: big_table
Create Table: CREATE TABLE `big_table` (
  `TABLE_CATALOG` varchar(512) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_SCHEMA` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `TABLE_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_NAME` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `ORDINAL_POSITION` bigint(21) unsigned NOT NULL DEFAULT '0',
  `COLUMN_DEFAULT` longtext CHARACTER SET utf8,
  `IS_NULLABLE` varchar(3) CHARACTER SET utf8 NOT NULL,
  `DATA_TYPE` varchar(64) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `CHARACTER_MAXIMUM_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_OCTET_LENGTH` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `NUMERIC_SCALE` bigint(21) unsigned DEFAULT NULL,
  `DATETIME_PRECISION` bigint(21) unsigned DEFAULT NULL,
  `CHARACTER_SET_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLLATION_NAME` varchar(32) CHARACTER SET utf8 DEFAULT NULL,
  `COLUMN_TYPE` longtext CHARACTER SET utf8 NOT NULL,
  `COLUMN_KEY` varchar(3) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `EXTRA` varchar(30) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `PRIVILEGES` varchar(80) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `COLUMN_COMMENT` varchar(1024) CHARACTER SET utf8 NOT NULL DEFAULT '',
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`), KEY `big_fk` (`TABLE_SCHEMA`)
) ENGINE=InnoDB AUTO_INCREMENT=1718273 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

Пример 16.6. Изменение значений Auto-Increment

Вот иллюстрация увеличения нижнего предела auto-increment для столбца таблицы, демонстрируя, как эта работа теперь обходит пересоздание таблицы плюс другие факты о столбцах InnoDB auto-increment.

/*
If this script is run after foreign_key.sql, the schema_names table is
already set up. But to allow this script to run multiple times without
running into duplicate ID errors, we set up the schema_names table
all over again.
*/

\! clear
\! echo "=== Adjusting the Auto-Increment Limit for a Table ==="
\! echo

drop table if exists schema_names;
create table schema_names (id int unsigned not null primary key auto_increment,
  schema_name varchar(64) character set utf8 not null, index i_schema (schema_name))
  as select distinct table_schema schema_name from small_table;

\! echo "Initial state of schema_names table."
\! echo "AUTO_INCREMENT is included in SHOW CREATE TABLE output."
\! echo "Note how MySQL reserved a block of IDs."
\! echo "Only 4 IDs are needed in this transaction. The next inserted values get IDs 8 and 9."
show create table schema_names\G
select * from schema_names order by id;

\! echo "Inserting even a tiny amount of data can produce gaps in the ID sequence."
insert into schema_names (schema_name) values ('eight'), ('nine');

\! echo "Bumping auto-increment lower limit to 20 (fast mechanism):"
alter table schema_names auto_increment=20, algorithm=inplace;

\! echo "Inserting 2 rows that should get IDs 20 and 21:"
insert into schema_names (schema_name) values ('foo'), ('bar');
commit;

\! echo "Bumping auto-increment lower limit to 30 (slow mechanism):"
alter table schema_names auto_increment=30, algorithm=copy;

\! echo "Inserting 2 rows that should get IDs 30 and 31:"
insert into schema_names (schema_name) values ('bletch'),('baz');
commit;

select * from schema_names order by id;

\! echo "Final state of schema_names table."
\! echo "AUTO_INCREMENT value shows the next inserted row would get ID=32."
show create table schema_names\G

Выполнение этого кода дает этот вывод, сжатый для краткости и с выделенными наиболее важными моментами:

=== Adjusting the Auto-Increment Limit for a Table ===

Query OK, 0 rows affected (0.01 sec)
Query OK, 4 rows affected (0.02 sec)
Records: 4  Duplicates: 0  Warnings: 0

Initial state of schema_names table.
AUTO_INCREMENT is included in SHOW CREATE TABLE output.
Note how MySQL reserved a block of IDs.
Only 4 IDs are needed in this transaction.
The next inserted values get IDs 8 and 9.
*************************** 1. row ***************************
   Table: schema_names
Create Table: CREATE TABLE `schema_names` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `schema_name` varchar(64) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`id`), KEY `i_schema` (`schema_name`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

+----+--------------------+
| id | schema_name        |
+----+--------------------+
|  1 | information_schema |
|  2 | mysql              |
|  3 | performance_schema |
|  4 | test               |
+----+--------------------+
4 rows in set (0.00 sec)

Inserting even a tiny amount of data can produce gaps in the ID sequence.
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

Query OK, 0 rows affected (0.00 sec)
Bumping auto-increment lower limit to 20 (fast mechanism):
Query OK, 0 rows affected (0.01 sec)
Records: 0  Duplicates: 0  Warnings: 0

Inserting 2 rows that should get IDs 20 and 21:
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)

Bumping auto-increment lower limit to 30 (slow mechanism):
Query OK, 8 rows affected (0.02 sec)
Records: 8  Duplicates: 0  Warnings: 0

Inserting 2 rows that should get IDs 30 and 31:
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

Query OK, 0 rows affected (0.01 sec)

+----+--------------------+
| id | schema_name        |
+----+--------------------+
|  1 | information_schema |
|  2 | mysql              |
|  3 | performance_schema |
|  4 | test               |
|  8 | eight              |
|  9 | nine               |
| 20 | foo                |
| 21 | bar                |
| 30 | bletch             |
| 31 | baz                |
+----+--------------------+
10 rows in set (0.00 sec)
Query OK, 0 rows affected (0.00 sec)

Final state of schema_names table.
AUTO_INCREMENT value shows the next inserted row would get ID=32.
*************************** 1. row ***************************
   Table: schema_names
Create Table: CREATE TABLE `schema_names` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `schema_name` varchar(64) CHARACTER SET utf8 NOT NULL,
  PRIMARY KEY (`id`), KEY `i_schema` (`schema_name`)
) ENGINE=InnoDB AUTO_INCREMENT=32
  DEFAULT CHARSET=latin1
1 row in set (0.00 sec)

Пример 16.7. Параллелизм управления с LOCK

Этот пример показывает, как использовать LOCK в ALTER TABLE, чтобы позволить или лишить параллельного доступа к таблице, в то время как происходит работа DDL онлайн. Есть настройки, которые позволяют запросы DML (LOCK=NONE), только запросы (LOCK=SHARED) или никакой параллельный доступ вообще (LOCK=EXCLUSIVE).

В одном сеансе мы выполняем последовательность ALTER TABLE, чтобы создать и удалить индекс, используя различные значения для LOCK, чтобы видеть, что происходит с ожиданием или заведением в тупик в любом сеансе. Мы используем ту же самую таблицу BIG_TABLE, как в предыдущих примерах, запускающихся приблизительно с 1.7 миллионов строк. В целях иллюстрации мы индексируем и запросим столбец IS_NULLABLE. Хотя в действительности было бы глупо сделать индексирование для крошечного столбца только с 2 отличными значениями.

mysql: desc big_table;
+------------------+---------------------+------+-----+---------+-------+
| Field            | Type                | Null | Key | Default | Extra |
+------------------+---------------------+------+-----+---------+-------+
| TABLE_CATALOG    | varchar(512)        | NO   |     |         |       |
| TABLE_SCHEMA     | varchar(64)         | NO   |     |         |       |
| TABLE_NAME       | varchar(64)         | NO   |     |         |       |
| COLUMN_NAME      | varchar(64)         | NO   |     |         |       |
| ORDINAL_POSITION | bigint(21) unsigned | NO   |     | 0       |       |
| COLUMN_DEFAULT   | longtext            | YES  |     | NULL    |       |

| IS_NULLABLE      | varchar(3)          | NO   |     |         |       |
...
+------------------+---------------------+------+-----+---------+-------+
21 rows in set (0.14 sec)

mysql: alter table big_table add index i1(is_nullable);
Query OK, 0 rows affected (20.71 sec)

mysql: alter table big_table drop index i1;
Query OK, 0 rows affected (0.02 sec)

mysql: alter table big_table add index i1(is_nullable), lock=exclusive;
Query OK, 0 rows affected (19.44 sec)

mysql: alter table big_table drop index i1;
Query OK, 0 rows affected (0.03 sec)

mysql: alter table big_table add index i1(is_nullable), lock=shared;
Query OK, 0 rows affected (16.71 sec)

mysql: alter table big_table drop index i1;
Query OK, 0 rows affected (0.05 sec)

mysql: alter table big_table add index i1(is_nullable), lock=none;
Query OK, 0 rows affected (12.26 sec)

mysql: alter table big_table drop index i1;
Query OK, 0 rows affected (0.01 sec)

... repeat statements like the above while running queries ...
... and DML statements at the same time in another session ...

Ничто драматическое не происходит в сеансе, выполняющем запросы DDL. Иногда ALTER TABLE работает необычно долго, потому что это ждет завершения другой транзакции, так как та транзакция изменила таблицу во время DDL или запросила таблицу перед DDL:

mysql: alter table big_table add index i1(is_nullable), lock=none;
Query OK, 0 rows affected (59.27 sec)

mysql: -- The previous ALTER took so long because it was waiting for all the concurrent
mysql: -- transactions to commit or roll back.

mysql: alter table big_table drop index i1;
Query OK, 0 rows affected (41.05 sec)

mysql: -- Even doing a SELECT on the table in the other session first causes
mysql: -- the ALTER TABLE above to stall until the transaction
mysql: -- surrounding the SELECT is committed or rolled back.

Вот журнал от другого сеанса, работающего одновременно, где мы выпускаем запросы данных и запросы DML для таблицы прежде, во время и после операций DDL, показанных в предыдущих примерах. Первый листинг показывает только запросы. Мы ожидаем, что запросы будут позволены во время использования операций DDL через LOCK=NONE или LOCK=SHARED, и запроса будет ждать, пока DDL не закончен, если ALTER TABLE включает LOCK=EXCLUSIVE.

mysql: show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.01 sec)

mysql: -- A trial query before any ADD INDEX in the other session:
mysql: -- Note: because autocommit is enabled, each
mysql: -- transaction finishes immediately after the query.
mysql: select distinct is_nullable from big_table;
+-------------+
| is_nullable |
+-------------+
| NO          |
| YES         |
+-------------+
2 rows in set (4.49 sec)

mysql: -- Index is being created with LOCK=EXCLUSIVE on the ALTER statement.
mysql: -- The query waits until the DDL is finished before proceeding.
mysql: select distinct is_nullable from big_table;
+-------------+
| is_nullable |
+-------------+
| NO          |
| YES         |
+-------------+
2 rows in set (17.26 sec)

mysql: -- Index is being created with LOCK=SHARED on the ALTER statement.
mysql: -- The query returns its results while the DDL is in progress.
mysql: -- The same thing happens with LOCK=NONE on the ALTER statement.
mysql: select distinct is_nullable from big_table;
+-------------+
| is_nullable |
+-------------+
| NO          |
| YES         |
+-------------+
2 rows in set (3.11 sec)

mysql: -- Once the index is created, and with no DDL in progress,
mysql: -- queries referencing the indexed column are very fast:
mysql: select count(*) from big_table where is_nullable = 'YES';
+----------+
| count(*) |
+----------+
|   411648 |
+----------+
1 row in set (0.20 sec)

mysql: select distinct is_nullable from big_table;
+-------------+
| is_nullable |
+-------------+
| NO          |
| YES         |
+-------------+
2 rows in set (0.00 sec)

Теперь в этом параллельном сеансе, мы выполняем некоторые транзакции, включая запрос DML или комбинацию запросов DML и запросов данных. Применим DELETE, чтобы иллюстрировать предсказуемые изменения таблицы. Поскольку транзакции в этой части могут охватить много запросов, мы выполняем эти тесты с выключенным autocommit.

mysql: set global autocommit = off;
Query OK, 0 rows affected (0.00 sec)

mysql: -- Count the rows that will be involved in our DELETE statements:
mysql: select count(*) from big_table where is_nullable = 'YES';
+----------+
| count(*) |
+----------+
|   411648 |
+----------+
1 row in set (0.95 sec)

mysql: -- After this point, any DDL statements back in the other session
mysql: -- stall until we commit or roll back.

mysql: delete from big_table where is_nullable = 'YES' limit 11648;
Query OK, 11648 rows affected (0.14 sec)

mysql: select count(*) from big_table where is_nullable = 'YES';
+----------+
| count(*) |
+----------+
|   400000 |
+----------+
1 row in set (1.04 sec)

mysql: rollback;
Query OK, 0 rows affected (0.09 sec)

mysql: select count(*) from big_table where is_nullable = 'YES';
+----------+
| count(*) |
+----------+
|   411648 |
+----------+
1 row in set (0.93 sec)

mysql: -- OK, now we're going to try that during index creation with LOCK=NONE.
mysql: delete from big_table where is_nullable = 'YES' limit 11648;
Query OK, 11648 rows affected (0.21 sec)

mysql: -- We expect that now there will be 400000 'YES' rows left:
mysql: select count(*) from big_table where is_nullable = 'YES';
+----------+
| count(*) |
+----------+
|   400000 |
+----------+
1 row in set (1.25 sec)

mysql: -- In the other session, the ALTER TABLE is waiting before finishing,
mysql: -- because _this_ transaction hasn't committed or rolled back yet.
mysql: rollback;
Query OK, 0 rows affected (0.11 sec)

mysql: select count(*) from big_table where is_nullable = 'YES';
+----------+
| count(*) |
+----------+
|   411648 |
+----------+
1 row in set (0.19 sec)

mysql: -- The ROLLBACK left the table in the same state we originally found it.
mysql: -- Now let's make a permanent change while the index is being created,
mysql: -- again with ALTER TABLE ... , LOCK=NONE.
mysql: -- First, commit so the DROP INDEX in the other shell can finish;
mysql: -- the previous SELECT started a transaction that accessed the table.
mysql: commit;
Query OK, 0 rows affected (0.00 sec)

mysql: -- Now we add the index back in the other shell, then issue DML in this one
mysql: -- while the DDL is running.
mysql: delete from big_table where is_nullable = 'YES' limit 11648;
Query OK, 11648 rows affected (0.23 sec)

mysql: commit;
Query OK, 0 rows affected (0.01 sec)

mysql: -- In the other shell, the ADD INDEX has finished.
mysql: select count(*) from big_table where is_nullable = 'YES';
+----------+
| count(*) |
+----------+
|   400000 |
+----------+
1 row in set (0.19 sec)

mysql: -- At the point the new index is finished being created, it contains entries
mysql: -- only for the 400000 'YES' rows left when all concurrent transactions are finished.
mysql:
mysql: -- Now we will run a similar test, while ALTER TABLE ... , LOCK=SHARED is running.
mysql: -- We expect a query to complete during the ALTER TABLE, but for the DELETE
mysql: -- to run into some kind of issue.
mysql: commit;
Query OK, 0 rows affected (0.00 sec)

mysql: -- As expected, the query returns results while the LOCK=SHARED DDL is running:
mysql: select count(*) from big_table where is_nullable = 'YES';
+----------+
| count(*) |
+----------+
|   400000 |
+----------+
1 row in set (2.07 sec)

mysql: -- The DDL in the other session is not going to finish until this transaction
mysql: -- is committed or rolled back. If we tried a DELETE now and it waited because
mysql: -- of LOCK=SHARED on the DDL, both transactions would wait forever (deadlock).
mysql: -- MySQL detects this condition and cancels the attempted DML statement.
mysql: delete from big_table where is_nullable = 'YES' limit 100000;
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
mysql: -- The transaction here is still going, so in the other shell, the ADD INDEX operation
mysql: -- is waiting for this transaction to commit or roll back.
mysql: rollback;
Query OK, 0 rows affected (0.00 sec)

mysql: -- Now let's try issuing a query and some DML, on one line, while running
mysql: -- ALTER TABLE ... , LOCK=EXCLUSIVE in the other shell.
mysql: -- Notice how even the query is held up until the DDL is finished.
mysql: -- By the time the DELETE is issued, there is no conflicting access
mysql: -- to the table and we avoid the deadlock error.
mysql: select count(*) from big_table where is_nullable = 'YES'; delete from big_table
  where is_nullable = 'YES' limit 100000;
+----------+
| count(*) |
+----------+
|   400000 |
+----------+

1 row in set (15.98 sec)

Query OK, 100000 rows affected (2.81 sec)

mysql: select count(*) from big_table where is_nullable = 'YES';
+----------+
| count(*) |
+----------+
|   300000 |
+----------+
1 row in set (0.17 sec)

mysql: rollback;
Query OK, 0 rows affected (1.36 sec)

mysql: select count(*) from big_table where is_nullable = 'YES';
+----------+
| count(*) |
+----------+
|   400000 |
+----------+
1 row in set (0.19 sec)

mysql: commit;
Query OK, 0 rows affected (0.00 sec)

mysql: -- Next, we try ALTER TABLE ... , LOCK=EXCLUSIVE in the other session
mysql: -- and only issue DML, not any query, in the concurrent transaction here.
mysql: delete from big_table where is_nullable = 'YES' limit 100000;
Query OK, 100000 rows affected (16.37 sec)

mysql: -- That was OK because the ALTER TABLE did not have to wait for the transaction
mysql: -- here to complete. The DELETE in this session waited until the index was ready.
mysql: select count(*) from big_table where is_nullable = 'YES';
+----------+
| count(*) |
+----------+
|   300000 |
+----------+
1 row in set (0.16 sec)

mysql: commit;
Query OK, 0 rows affected (0.00 sec)

В предыдущих примерах мы узнали что:

  • LOCK для ALTER TABLE отделен от остальной части запроса запятой.

  • Online DDL могут ждать перед запуском, пока любые предшествующие транзакции, которые получают доступ к таблице, не завершены.
  • Online DDL могут ждать перед завершением, пока любые параллельные транзакции, которые получают доступ к таблице, не завершены.
  • В то время как online DDL работает, параллельные запросы являются относительно прямыми, пока ALTER TABLE использует LOCK=NONE или LOCK=SHARED.
  • Обратите внимание на отключение autocommit. Если он выключен, сделайте все возможное, чтобы закончить транзакции в других сеансах (даже только запросы) прежде, чем выполнить операции DDL на таблице.
  • С LOCK=SHARED параллельные транзакции, которые смешивают запросы и DML, могли столкнуться с ошибками тупика и быть перезапущенными после того, как DDL закончен.
  • С LOCK=NONE параллельные транзакции могут свободно смешать запросы и DML. Работа DDL ждет, пока параллельные транзакции не завершены.
  • С LOCK=EXCLUSIVE параллельные транзакции могут свободно смешать запросы и DML, но те транзакции ждут, пока работа DDL не закончена прежде, чем они смогут получить доступ к таблице.

Пример 16.8. Установки схемы для экспериментов DDL онлайн

Вы можете создать много индексов на таблице одним вызовом ALTER TABLE. Это относительно эффективно, потому что кластеризируемый индекс таблицы должен быть просмотрен только однажды (хотя данные отсортированы отдельно для каждого нового индекса). Например:

CREATE TABLE T1(A INT PRIMARY KEY, B INT, C CHAR(1)) ENGINE=InnoDB;
INSERT INTO T1 VALUES (1,2,'a'), (2,3,'b'), (3,2,'c'), (4,3,'d'), (5,2,'e');
COMMIT;
ALTER TABLE T1 ADD INDEX (B), ADD UNIQUE INDEX (C);

Вышеупомянутые запросы составляют таблицу T1 с первичным ключом на столбце A, вставляют несколько строк, затем создают два новых индекса на столбцах B и C. Если было много строк, вставленных в T1 до ALTER TABLE, этот подход намного более эффективен, чем создание всех вторичных индексов прежде, чем загрузить данные.

Поскольку удаление вторичного индекса, также не требует никакого копирования табличных данных, одинаково эффективно удалить много индексов одним вызовом ALTER TABLE или несколькими DROP INDEX:

ALTER TABLE T1 DROP INDEX B, DROP INDEX C;

Или:

DROP INDEX B ON T1;
DROP INDEX C ON T1;

Пример 16.9. Создание и удаление первичного ключа

Реструктурирование кластеризируемого индекса всегда требует копирования табличных данных. Таким образом, лучше определять primary key, когда Вы составляете таблицу, вместо ALTER TABLE ... ADD PRIMARY KEY позже, чтобы избежать пересоздания таблицы.

Определение PRIMARY KEY позже требует копирования данных, как в следующем примере:

CREATE TABLE T2 (A INT, B INT);
INSERT INTO T2 VALUES (NULL, 1);
ALTER TABLE T2 ADD PRIMARY KEY (B);

Когда Вы создаете индекс UNIQUE или PRIMARY KEY, MySQL должен сделать некоторую дополнительную работу. Для UNIQUE MySQL проверяет, что таблица не содержит двойных значений для ключа. Для PRIMARY KEY MySQL также проверяет что ни один из столбцов PRIMARY KEY не содержит NULL.

Когда Вы добавляете первичный ключ, используя ALGORITHM=COPY, MySQL фактически преобразовывает NULL в связанных столбцах к значениям по умолчанию: 0 для чисел, пустая строка для символьно-ориентированных столбцов и BLOB, 0000-00-00 00:00:00 для DATETIME. Это нестандартное поведение, Oracle не рекомендует на него полагаться. Добавление использования первичного ключа ALGORITHM=INPLACE позволено только когда SQL_MODE включает the strict_trans_tables или strict_all_tables, когда SQL_MODE строгий, ADD PRIMARY KEY ... , ALGORITHM=INPLACE позволен, но запрос может все еще потерпеть неудачу, если требуемые столбцы первичного ключа содержат NULL. Поведение ALGORITHM=INPLACE более стандартно-послушно.

Следующие примеры показывают различные возможности для ADD PRIMARY KEY. С ALGORITHM=COPY работа преуспевает несмотря на присутствие NULL в столбцах первичного ключа, данные тихо изменены, что может вызвать проблемы.

mysql> CREATE TABLE add_pk_via_copy (c1 INT, c2 VARCHAR(10), c3 DATETIME);
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO add_pk_via_copy VALUES (1,'a','2014-11-03 11:01:37'),
                 (NULL,NULL,NULL);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE add_pk_via_copy ADD PRIMARY KEY (c1,c2,c3),
                ALGORITHM=COPY;
Query OK, 2 rows affected, 3 warnings (0.07 sec)
Records: 2  Duplicates: 0  Warnings: 3

mysql> SHOW WARNINGS;
+---------+------+-----------------------------------------+
| Level   | Code | Message                                 |
+---------+------+-----------------------------------------+
| Warning | 1265 | Data truncated for column 'c1' at row 2 |
| Warning | 1265 | Data truncated for column 'c2' at row 2 |
| Warning | 1265 | Data truncated for column 'c3' at row 2 |
+---------+------+-----------------------------------------+
3 rows in set (0.00 sec)

mysql> SELECT * FROM add_pk_via_copy;
+----+----+---------------------+
| c1 | c2 | c3                  |
+----+----+---------------------+
|  0 |    | 0000-00-00 00:00:00 |
|  1 | a  | 2014-11-03 11:01:37 |
+----+----+---------------------+
2 rows in set (0.00 sec)

С ALGORITHM=INPLACE работа могла потерпеть неудачу по различным причинам, потому что эта установка считает целостность данных высоким приоритетом: запрос дает ошибку, если SQL_MODE недостаточно строг, или если столбцы первичного ключа содержат NULL. Как только мы обращаемся к обоим требованиям, ALTER TABLE успешна.

mysql> CREATE TABLE add_pk_via_inplace (c1 INT, c2 VARCHAR(10),
                 c3 DATETIME);
Query OK, 0 rows affected (0.02 sec)

mysql> INSERT INTO add_pk_via_inplace VALUES (1, 'a',
                 '2014-11-03 11:01:37'),(NULL,NULL,NULL);
Query OK, 2 rows affected (0.00 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> SELECT * FROM add_pk_via_inplace;
+------+------+---------------------+
| c1   | c2   | c3                  |
+------+------+---------------------+
| 1    | a    | 2014-11-03 11:01:37 |
| NULL | NULL | NULL                |
+------+------+---------------------+
2 rows in set (0.00 sec)

mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE add_pk_via_inplace ADD PRIMARY KEY (c1,c2,c3),
                ALGORITHM=INPLACE;
ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported. Reason: cannot silently convert NULL
values, as required in this SQL_MODE. Try ALGORITHM=COPY.

mysql> SET sql_mode ='strict_trans_tables';
Query OK, 0 rows affected (0.00 sec)

mysql> ALTER TABLE add_pk_via_inplace ADD PRIMARY KEY (c1,c2,c3),
                ALGORITHM=INPLACE;
ERROR 1138 (22004): Invalid use of NULL value
mysql> DELETE FROM add_pk_via_inplace WHERE c1 IS NULL OR c2 IS NULL OR
                 c3 IS NULL;
Query OK, 1 row affected (0.01 sec)

mysql> SELECT * FROM add_pk_via_inplace;
+----+----+---------------------+
| c1 | c2 | c3                  |
+----+----+---------------------+
| 1  | a  | 2014-11-03 11:01:37 |
+----+----+---------------------+
1 row in set (0.00 sec)

mysql> ALTER TABLE add_pk_via_inplace ADD PRIMARY KEY (c1,c2,c3),
                ALGORITHM=INPLACE;
Query OK, 0 rows affected (0.09 sec)
Records: 0  Duplicates: 0  Warnings: 0

Если Вы составляете таблицу без первичного ключа, InnoDB выбирает один для Вас, которые могут быть первым UNIQUE ключом, определенный на столбце NOT NULL или произведенный системой ключ. Чтобы избежать любой неуверенности и потенциального требования пространства для дополнительного скрытого столбца, определите PRIMARY KEY в CREATE TABLE.

16.12.6. Детали выполнения DDL онлайн

Каждой операцией ALTER TABLE для InnoDB управляют несколько аспектов:

  • Есть ли какое-либо изменение физического представления таблицы или это просто изменение метаданных, которые могут быть сделаны, не касаясь таблицы непосредственно.

  • Остается ли объем данных в таблице тем же самым, увеличивается или уменьшается.
  • Вовлекает ли изменение в табличных данных кластеризируемый индекс, вторичный индекс или оба.
  • Есть ли какие-либо отношения foreign key между измененной таблицей и некоторой другой таблицей. Механика отличается в зависимости от параметра конфигурации foreign_key_checks .
  • Разделена ли таблица. Разделы в ALTER TABLE превращены в низкоуровневые операции, вовлекающие одну или более таблиц, и те операции следуют регулярным правилам для DDL онлайн.
  • Должны ли табличные данные быть скопированы, может ли таблица быть реорганизована на месте.
  • Содержит ли таблица какие-либо столбцы auto-increment.
  • Какая степень блокировки требуется: природой основных операций базы данных или указанием LOCK в ALTER TABLE .

Этот раздел объясняет, как эти факторы затрагивают различные виды ALTER TABLE.

Состояния ошибки для DDL онлайн

Вот основные причины, почему работа DDL онлайн могла потерпеть неудачу:

  • Если LOCK определяет низкую степень блокировки (SHARED или NONE), это не совместимо с особым типом работы DDL.

  • Если тайм-аут происходит при ожидании, чтобы получить исключительную блокировку на таблице, которая может быть необходима кратко во время начальных и заключительных фаз работы DDL.
  • Если tmpdir или innodb_tmpdir исчерпывает дисковое пространство, в то время как MySQL пишет временные файлы на диске во время создания индекса. Для получения дополнительной информации см. раздел B.5.3.5.
  • Если ALTER TABLE занимает много времени, и параллельный DML изменяет таблицу так, что размер временного журнала превышает значение параметра innodb_online_alter_log_max_size. Это условие вызывает ошибку DB_ONLINE_LOG_TOO_BIG.
  • Если параллельный DML производит изменения в таблице, которые позволены с оригинальным табличным определением, но не с новым. Работа только неудачу терпит в самом конце, когда MySQL пытается применить все изменения из параллельных запросов DML. Например, Вы могли бы вставить двойные значения в столбец, в то время как уникальный индекс создается, или Вы могли бы вставить NULL в столбец, создавая индекс primary key на том столбце. Изменения, произведенные параллельным DML, имеют приоритет, и ALTER TABLE откатывается.

Хотя параметр конфигурации innodb_file_per_table имеет сильное воздействие на представление таблицы, все операции online DDL работают одинаково хорошо, включена ли та опция или отключена, и расположена ли таблица физически в ее собственном файле .ibd или в системном табличном пространстве.

У InnoDB есть два типа индексов: кластеризируемые, представляющие все данные в таблице, и дополнительные вторичные, чтобы ускорить запросы. Так как кластеризируемый индекс содержит значения данных в его узлах B-дерева, добавление или удаление кластеризируемого индекса действительно вовлекает копирование данных и создание новой копии таблицы. Вторичный индекс, однако, содержит только ключ индекса и значение первичного ключа. Этот тип индекса может быть создан или удален, не копируя данные в кластеризируемом индексе. Поскольку каждый вторичный индекс содержит копии значений первичного ключа (получает доступ к кластеризируемому индексу при необходимости), когда Вы изменяете определение первичного ключа, все вторичные индексы обновлены также.

Удаление вторичного индекса просто. Только внутренние системные таблицы InnoDB и таблицы словаря данных MySQL обновлены, чтобы отразить факт, что индекс больше не существует. InnoDB возвращает место для индекса табличному пространству, чтобы новый индекс или дополнительные строки таблицы могут использовать пространство.

Чтобы добавить вторичный индекс к существующей таблице, InnoDB просматривает таблицу и сортирует строки, используя буферы памяти и временные файлы, в порядке значений ключевых столбцов вторичного индекса. B-дерево тогда создано в порядке значений ключа, что более эффективно, чем вставка строк в индекс в случайном порядке. Поскольку узлы B-дерева разделены, когда они заполняются, создание индекса таким образом приводит к более высокому коэффициенту заполнения для индекса, делая это более эффективным для последующего доступа.

16.12.7. Восстановление катастрофического отказа с DDL онлайн

Хотя никакие данные не потеряны, если сервер отказывает в то время, как выполняется ALTER TABLE, процесс восстановления катастрофического отказа отличается для кластеризируемого и вторичного индексов.

Если сервер отказывает в то время, как идет создание вторичного индекса, после восстановления MySQL удаляет любой частично созданный индекс. Вы должны запустить повторно ALTER TABLE или CREATE INDEX.

Когда катастрофический отказ происходит во время создания кластеризируемого индекса, восстановление является более сложным, потому что данные в таблице должны быть скопированы к полностью новому кластеризируемому индексу. Помните, что все таблицы InnoDB сохранены как кластеризуемый индекс.

MySQL создает новый кластеризируемый индекс, копируя существующие данные от оригинальной таблицы InnoDB во временную таблицу, у которой есть желаемая структура индекса. Как только данные полностью скопированы к этой временной таблице, оригинальная таблица переименована. Временная таблица, включающая кластеризируемый индекс, переименована с названием оригинальной таблицы, а оригинальная таблица исключена из базы данных.

Если системный катастрофический отказ происходит в то время, как идет создание кластеризируемого индекса, никакие данные не потеряны, но Вы должны завершить процесс восстановления, используя временные таблицы, которые существуют во время процесса. Так как кластеризируемый индекса редко обновляется или пересматривают первичные ключи на больших таблицах, столкнуться с системным катастрофическим отказом во время этой работы шансов мало, поэтому это руководство не предоставляет информацию о восстановлении от этого сбоя.

16.12.8. Online DDL для разделенных таблиц InnoDB

За исключением параметров разделения в ALTER TABLE, online DDL следует тем же самым правилам, которые относятся к обычным таблицам. Правила DDL обрисованы в общих чертах в таблице 16.9.

Параметры разделения ALTER TABLE не проходят тот же самый внутренний DDL онлайн API, как обычные таблицы и позволены только в соединении с ALGORITHM=DEFAULT и LOCK=DEFAULT.

Если Вы используете параметры разделения в ALTER TABLE, разделенная таблица будет переразделена с использованием ALTER TABLE COPY. Другими словами, новая разделенная таблица составлена с новой схемой разделения. Недавно составленная таблица будет включать любые изменения, примененные ALTER TABLE, табличные данные будут скопированы в новую структуру таблицы.

Если Вы не изменяете разделения таблицы или выполняете любое другое управление разделением в Вашем ALTER TABLE, ALTER TABLE будет использовать INPLACE на каждом табличном разделе. Знайте, однако, что когда INPLACE ALTER TABLE выполнен на каждом разделе, будут увеличены требования к системным ресурсам из-за операций, выполняемых на многих разделах.

Даже при том, что разделы в ALTER TABLE не проходят тот же самый внутренний DDL онлайн API, как обычные таблицы, MySQL все еще пытается минимизировать копирование данных и блокировку где только возможно:

  • ADD PARTITION и DROP PARTITION для таблиц, разделенных RANGE или LIST не копируют существующие данные.

  • TRUNCATE PARTITION не копирует существующих данных для всех типов разделенных таблиц.
  • Во время параллельных запросов позволяются ADD PARTITION и COALESCE PARTITION для таблиц, разделенных HASH или LIST. MySQL копирует данные, держа совместно используемую блокировку.
  • Для REORGANIZE PARTITION, REBUILD PARTITION, ADD PARTITION или COALESCE PARTITION для таблицы, разделенной by LINEAR HASH или LIST, параллельные запросы позволены. Данные затронутого раздела скопированы, держа совместно используемую блокировку (чтение) метаданных на табличном уровне.

Полнотекстовый поиск (FTS) и внешние ключи не поддержаны разделенными таблицами InnoDB. Подробности в разделах 13.9.5 и 20.6.2.

16.12.9. Ограничения Online DDL

Примите следующие ограничения во внимание, выполняя операции online DDL:

  • Работа DDL онлайн, которая копирует таблицу, может вызвать ошибку, если работа использует все доступное дисковое пространство на файловой системе, где каталог данных находится ( datadir). Чтобы избежать этой проблемы, гарантируйте, что есть достаточно дискового пространства, чтобы выполнить операции online ALTER TABLE, которые копируют таблицу. Во время этих операций MySQL пишет временные файлы во временный каталог ($TMPDIR в Unix, %TEMP% в Windows или каталог, определенный переменной --tmpdir). Каждый временный файл является достаточно большим, чтобы держать один столбец в новой таблице или индексе, и удален, как только это слито в заключительную таблицу. Такие операции могут потребовать временное пространство, равное сумме данных в таблице плюс индексы.

    Вы можете использовать опцию innodb_tmpdir, чтобы определить отдельный временный каталог для операций DDL онлайн. Опция innodb_tmpdir была введена, чтобы помочь избежать временных переполнений каталога, которые могли произойти в результате больших временных файлов вида, создаваемых во время операций онлайн ALTER TABLE, которые пересоздают таблицу.

  • Таблица скопирована, вместо того, чтобы использовать быстрое создание индекса, когда Вы создаете индекс на TEMPORARY TABLE. Об этом сообщили как MySQL Bug #39833.
  • InnoDB обрабатывает ошибочные случаи, когда пользователи пытаются удалить индекс, необходимый для внешних ключей. См. раздел B.3.
  • LOCK=NONE в ALTER TABLE не позволен, если есть ограничения ON...CASCADE или ON...SET NULL на таблицу.
  • В зависимости от внутренних работ, online DDL и LOCK в ALTER TABLE может потребовать эксклюзивного доступа к таблице в течение краткого времени во время начальных и заключительных фаз работы DDL. Таким образом, работа DDL онлайн могла бы ждать прежде, чем закончиться, если есть продолжительное выполнение вставки, обновления, удаления или SELECT ... FOR UPDATE на таблице, работа DDL онлайн могла бы ждать прежде, чем закончиться, если подобная продолжительная транзакция запущена в то время, как выполняется ALTER TABLE.
  • Выполняя работу DDL онлайн, поток, который выполняет ALTER TABLE, применит online-журнал операций DML, которые были выполнены одновременно на той же самой таблице от других потоков соединения. Когда операции DML применены, возможно столкнуться с ошибкой дубликата ключа (ERROR 1062 (23000): Duplicate entry), даже если бы двойная запись является только временной и исправилась бы более поздней запись в online-журнале. Это подобно идее ограничения внешнего ключа, в котором ограничения должны держаться во время транзакции.
  • OPTIMIZE TABLE для InnoDB отображена на ALTER TABLE, чтобы восстановить таблицу, обновить индексную статистику и свободное неиспользуемое место в кластеризируемом индексе. Вторичный индекс не создаются так эффективно, потому что ключи вставлены в порядке, в котором они появились в первичном ключе. OPTIMIZE TABLE также поддерживает online DDL для пересоздания таблиц InnoDB. Для дополнительной информации см. раздел 16.12.1.

    До MySQL 5.6.17/5.7.4 не было поддержки online DDL для этого.

  • Таблицы InnoDB, составленные перед MySQL 5.6, не поддерживают ALTER TABLE ... ALGORITHM=INPLACE для таблиц, которые включают временные столбцы (DATE, DATETIME или TIMESTAMP) и не были пересозданы через ALTER TABLE ... ALGORITHM=COPY. В этом случае ALTER TABLE ... ALGORITHM=INPLACE возвращает следующую ошибку:

    ERROR 1846 (0A000): ALGORITHM=INPLACE is not supported.
    Reason: Cannot change column type INPLACE. Try ALGORITHM=COPY.
    
  • Эти ограничения вообще применимы к операциям DDL онлайн на больших таблицах, где копирование таблицы вовлечено:

    • Нет никакого механизма, чтобы сделать паузу в online DDL или ограничить ввод/вывод или использование центрального процессора для работы DDL.

    • Откат online DDL может быть дорогим.
    • Долгое выполнение онлайн операции DDL может вызвать задержку репликации. Работа DDL онлайн должна закончить работать на ведущем устройстве прежде, чем она будет выполнена на ведомом устройстве. Кроме того, DML, который был обработан одновременно на ведущем устройстве, обработан на ведомом устройстве только после того, как работа DDL на ведомом устройстве завершена (Bug #73196).

    Для дополнительной информации, связанной с выполнением онлайн операции DDL на больших таблицах, см. раздел 16.12.2.

16.13. Опции запуска InnoDB и системные переменные

  • Системные переменные, которые являются истиной или ложью, могут быть включены при запуске сервера или отключены при использовании префикса --skip-. Например, чтобы включить или отключить адаптивный хэш индекс, Вы можете использовать --innodb_adaptive_hash_index или --skip-innodb_adaptive_hash_index в командной строке или innodb_adaptive_hash_index или skip-innodb_adaptive_hash_index в файле опций.

  • Системные переменные, которые берут числовое значение, могут быть определены как --var_name=value в командной строке или как var_name=value в файле опций.
  • Много системных переменных могут быть изменены во время выполнения (см. раздел 6.1.6.2).
  • Для информации о модификаторах контекста GLOBAL и SESSION обратитесь к описанию команды SET.
  • Определенные опции управляют местоположением и расположением файлов с данными InnoDB. Раздел 16.6 объясняет, как использовать эти опции.
  • Некоторые опции, которые Вы не могли бы использовать первоначально, помогают настроить технические характеристики InnoDB, основанные на машинной конфигурации и Вашей рабочей нагрузке базы данных.
  • Для получения дополнительной информации об определении опций и системных переменных см. раздел 5.2.3.

Таблица 16.10. Опции и переменные InnoDB

ИмяCmd-LineФайл опций СистемнаяСтатуснаяОбласть видимости Динамическая
daemon_memcached_enable_binlogДаДаДа ГлобальнаяНет
daemon_memcached_engine_lib_nameДаДаДа ГлобальнаяНет
daemon_memcached_engine_lib_pathДаДаДа ГлобальнаяНет
daemon_memcached_optionДаДаДа ГлобальнаяНет
daemon_memcached_r_batch_sizeДаДаДа ГлобальнаяНет
daemon_memcached_w_batch_sizeДаДаДа ГлобальнаяНет
foreign_key_checks Да ОбеДа
ignore-builtin-innodbДаДа ГлобальнаяНет
- Переменные: ignore_builtin_innodb Да ГлобальнаяНет
innodbДа Да
innodb_adaptive_flushingДаДаДа ГлобальнаяДа
innodb_adaptive_flushing_lwmДаДаДа ГлобальнаяДа
innodb_adaptive_hash_indexДаДаДа ГлобальнаяДа
innodb_adaptive_hash_index_partsДаДаДа ГлобальнаяНет
innodb_adaptive_max_sleep_delayДаДаДа ГлобальнаяДа
innodb_api_bk_commit_intervalДаДаДа ГлобальнаяДа
innodb_api_disable_rowlockДаДаДа ГлобальнаяНет
innodb_api_enable_binlogДаДаДа ГлобальнаяНет
innodb_api_enable_mdlДаДаДа ГлобальнаяНет
innodb_api_trx_levelДаДаДа ГлобальнаяДа
innodb_autoextend_incrementДаДаДа ГлобальнаяДа
innodb_autoinc_lock_modeДаДаДа ГлобальнаяНет
Innodb_available_undo_logs Да ГлобальнаяНет
innodb_background_drop_list_emptyДаДаДа ГлобальнаяДа
Innodb_buffer_pool_bytes_data ДаГлобальнаяНет
Innodb_buffer_pool_bytes_dirty ДаГлобальнаяНет
innodb_buffer_pool_chunk_sizeДаДаДа ГлобальнаяНет
innodb_buffer_pool_debugДаДаДа ГлобальнаяНет
innodb_buffer_pool_dump_at_shutdownДаДаДа ГлобальнаяДа
innodb_buffer_pool_dump_nowДаДаДа ГлобальнаяДа
innodb_buffer_pool_dump_pctДаДаДа ГлобальнаяДа
Innodb_buffer_pool_dump_status ДаГлобальнаяНет
innodb_buffer_pool_filenameДаДаДа ГлобальнаяДа
innodb_buffer_pool_instancesДаДаДа ГлобальнаяНет
innodb_buffer_pool_load_abortДаДаДа ГлобальнаяДа
innodb_buffer_pool_load_at_startupДаДаДа ГлобальнаяНет
innodb_buffer_pool_load_nowДаДаДа ГлобальнаяДа
Innodb_buffer_pool_load_status ДаГлобальнаяНет
Innodb_buffer_pool_pages_data ДаГлобальнаяНет
Innodb_buffer_pool_pages_dirty ДаГлобальнаяНет
Innodb_buffer_pool_pages_flushed ДаГлобальнаяНет
Innodb_buffer_pool_pages_free ДаГлобальнаяНет
Innodb_buffer_pool_pages_latched ДаГлобальнаяНет
Innodb_buffer_pool_pages_misc ДаГлобальнаяНет
Innodb_buffer_pool_pages_total ДаГлобальнаяНет
Innodb_buffer_pool_read_ahead ДаГлобальнаяНет
Innodb_buffer_pool_read_ahead_evicted ДаГлобальнаяНет
Innodb_buffer_pool_read_ahead_rnd ДаГлобальнаяНет
Innodb_buffer_pool_read_requests ДаГлобальнаяНет
Innodb_buffer_pool_reads Да ГлобальнаяНет
Innodb_buffer_pool_resize_status ДаГлобальнаяНет
innodb_buffer_pool_sizeДаДаДа ГлобальнаяДа
Innodb_buffer_pool_wait_free ДаГлобальнаяНет
Innodb_buffer_pool_write_requests ДаГлобальнаяНет
innodb_change_buffer_max_sizeДаДаДа ГлобальнаяДа
innodb_change_bufferingДаДаДа ГлобальнаяДа
innodb_change_buffering_debugДаДаДа ГлобальнаяДа
innodb_checksum_algorithmДаДаДа ГлобальнаяДа
innodb_cmp_per_index_enabledДаДаДа ГлобальнаяДа
innodb_commit_concurrencyДаДаДа ГлобальнаяДа
innodb_compress_debugДаДаДа ГлобальнаяДа
innodb_compression_failure_threshold_pctДаДа Да ГлобальнаяДа
innodb_compression_levelДаДаДа ГлобальнаяДа
innodb_compression_pad_pct_maxДаДаДа ГлобальнаяДа
innodb_concurrency_ticketsДаДаДа ГлобальнаяДа
innodb_data_file_pathДаДаДа ГлобальнаяНет
Innodb_data_fsyncs Да ГлобальнаяНет
innodb_data_home_dirДаДаДа ГлобальнаяНет
Innodb_data_pending_fsyncs Да ГлобальнаяНет
Innodb_data_pending_reads Да ГлобальнаяНет
Innodb_data_pending_writes Да ГлобальнаяНет
Innodb_data_read ДаГлобальная Нет
Innodb_data_reads ДаГлобальная Нет
Innodb_data_writes ДаГлобальная Нет
Innodb_data_written ДаГлобальнаяНет
Innodb_dblwr_pages_written ДаГлобальнаяНет
Innodb_dblwr_writes ДаГлобальнаяНет
innodb_default_row_formatДаДаДа ГлобальнаяДа
innodb_disable_sort_file_cacheДаДаДа ГлобальнаяДа
innodb_doublewrite ДаДаДа ГлобальнаяНет
innodb_fast_shutdown ДаДаДа ГлобальнаяДа
innodb_fil_make_page_dirty_debugДаДаДа ГлобальнаяДа
innodb_file_per_tableДаДаДа ГлобальнаяДа
innodb_fill_factor ДаДаДа ГлобальнаяДа
innodb_flush_log_at_timeout Да ГлобальнаяДа
innodb_flush_log_at_trx_commitДаДаДа ГлобальнаяДа
innodb_flush_methodДаДаДа ГлобальнаяНет
innodb_flush_neighborsДаДаДа ГлобальнаяДа
innodb_flush_sync ДаДаДа ГлобальнаяДа
innodb_flushing_avg_loopsДаДаДа ГлобальнаяДа
innodb_force_load_corruptedДаДаДа ГлобальнаяНет
innodb_force_recoveryДаДаДа ГлобальнаяНет
innodb_ft_aux_tableДаДаДа ГлобальнаяДа
innodb_ft_cache_sizeДаДаДа ГлобальнаяНет
innodb_ft_enable_diag_printДаДаДа ГлобальнаяДа
innodb_ft_enable_stopwordДаДаДа ГлобальнаяДа
innodb_ft_max_token_sizeДаДаДа ГлобальнаяНет
innodb_ft_min_token_sizeДаДаДа ГлобальнаяНет
innodb_ft_num_word_optimizeДаДаДа ГлобальнаяДа
innodb_ft_result_cache_limitДаДаДа ГлобальнаяДа
innodb_ft_server_stopword_tableДаДаДа ГлобальнаяДа
innodb_ft_sort_pll_degreeДаДаДа ГлобальнаяНет
innodb_ft_total_cache_sizeДаДаДа ГлобальнаяНет
innodb_ft_user_stopword_tableДаДаДа ОбеДа
Innodb_have_atomic_builtins ДаГлобальнаяНет
innodb_io_capacity ДаДаДа Глобальная Да
innodb_io_capacity_maxДаДаДа ГлобальнаяДа
innodb_limit_optimistic_insert_debugДаДаДа ГлобальнаяДа
innodb_lock_wait_timeoutДаДаДа ОбеДа
innodb_log_buffer_sizeДаДаДа ГлобальнаяНет
innodb_log_checksums ДаДаДа Глобальная Да
innodb_log_compressed_pagesДаДаДа ГлобальнаяДа
innodb_log_file_size ДаДаДа Глобальная Нет
innodb_log_files_in_groupДаДаДа ГлобальнаяНет
innodb_log_group_home_dirДаДаДа ГлобальнаяНет
Innodb_log_waits ДаГлобальная Нет
innodb_log_write_ahead_sizeДаДаДа ГлобальнаяДа
Innodb_log_write_requests Да ГлобальнаяНет
Innodb_log_writes ДаГлобальная Нет
innodb_lru_scan_depthДаДаДа ГлобальнаяДа
innodb_max_dirty_pages_pctДаДаДа ГлобальнаяДа
innodb_max_dirty_pages_pct_lwmДаДаДа ГлобальнаяДа
innodb_max_purge_lag ДаДаДа Глобальная Да
innodb_max_purge_lag_delayДаДаДа ГлобальнаяДа
innodb_max_undo_log_sizeДаДаДа ГлобальнаяДа
innodb_merge_threshold_set_all_debugДаДа Да ГлобальнаяДа
innodb_monitor_disableДаДаДа ГлобальнаяДа
innodb_monitor_enableДаДаДа ГлобальнаяДа
innodb_monitor_resetДаДаДа ГлобальнаяДа
innodb_monitor_reset_allДаДаДа ГлобальнаяДа
Innodb_num_open_files Да ГлобальнаяНет
innodb_numa_interleaveДаДаДа ГлобальнаяНет
innodb_old_blocks_pctДаДаДа ГлобальнаяДа
innodb_old_blocks_timeДаДаДа ГлобальнаяДа
innodb_online_alter_log_max_sizeДаДаДа ГлобальнаяДа
innodb_open_files ДаДаДа Глобальная Нет
innodb_optimize_fulltext_onlyДаДаДа ГлобальнаяДа
Innodb_os_log_fsyncs Да ГлобальнаяНет
Innodb_os_log_pending_fsyncs ДаГлобальнаяНет
Innodb_os_log_pending_writes ДаГлобальнаяНет
Innodb_os_log_written Да ГлобальнаяНет
innodb_page_cleanersДаДаДа ГлобальнаяНет
Innodb_page_size ДаГлобальная Нет
innodb_page_size ДаДаДа Глобальная Нет
Innodb_pages_created Да ГлобальнаяНет
Innodb_pages_read ДаГлобальная Нет
Innodb_pages_written Да ГлобальнаяНет
innodb_print_all_deadlocksДаДаДа ГлобальнаяДа
innodb_purge_batch_sizeДаДаДа ГлобальнаяДа
innodb_purge_rseg_truncate_frequencyДаДа Да ГлобальнаяДа
innodb_purge_threads ДаДаДа Глобальная Нет
innodb_random_read_aheadДаДаДа ГлобальнаяДа
innodb_read_ahead_thresholdДаДаДа ГлобальнаяДа
innodb_read_io_threadsДаДаДа ГлобальнаяНет
innodb_read_onlyДаДаДа ГлобальнаяНет
innodb_replication_delayДаДаДа ГлобальнаяДа
innodb_rollback_on_timeoutДаДаДа ГлобальнаяНет
innodb_rollback_segmentsДаДаДа ГлобальнаяДа
Innodb_row_lock_current_waits ДаГлобальнаяНет
Innodb_row_lock_time ДаГлобальнаяНет
Innodb_row_lock_time_avg Да ГлобальнаяНет
Innodb_row_lock_time_max Да ГлобальнаяНет
Innodb_row_lock_waits Да ГлобальнаяНет
Innodb_rows_deleted ДаГлобальная Нет
Innodb_rows_inserted Да ГлобальнаяНет
Innodb_rows_read ДаГлобальная Нет
Innodb_rows_updated Да ГлобальнаяНет
innodb_saved_page_number_debugДаДаДа ГлобальнаяДа
innodb_sort_buffer_sizeДаДаДа ГлобальнаяНет
innodb_spin_wait_delayДаДаДа ГлобальнаяДа
innodb_stats_auto_recalcДаДаДа ГлобальнаяДа
innodb_stats_include_delete_markedДаДа Да ГлобальнаяДа
innodb_stats_methodДаДаДа ГлобальнаяДа
innodb_stats_on_metadataДаДаДа ГлобальнаяДа
innodb_stats_persistentДаДаДа ГлобальнаяДа
innodb_stats_persistent_sample_pagesДаДа Да ГлобальнаяДа
innodb_stats_transient_sample_pagesДаДаДа ГлобальнаяДа
innodb-status-fileДаДа
innodb_status_outputДаДаДа ГлобальнаяДа
innodb_status_output_locksДаДаДа ГлобальнаяДа
innodb_strict_modeДаДаДа ОбеДа
innodb_sync_array_sizeДаДаДа ГлобальнаяНет
innodb_sync_debugДаДаДа ГлобальнаяНет
innodb_sync_spin_loopsДаДаДа ГлобальнаяДа
innodb_table_locksДаДаДа ОбеДа
innodb_temp_data_file_pathДаДаДа ГлобальнаяНет
innodb_thread_concurrencyДаДаДа ГлобальнаяДа
innodb_thread_sleep_delayДаДаДа ГлобальнаяДа
innodb_tmpdir ДаДаДа ОбеДа
Innodb_truncated_status_writes ДаГлобальнаяНет
innodb_trx_purge_view_update_only_debugДаДа Да ГлобальнаяДа
innodb_trx_rseg_n_slots_debugДаДаДа ГлобальнаяДа
innodb_undo_directoryДаДаДа ГлобальнаяНет
innodb_undo_log_truncateДаДаДа ГлобальнаяДа
innodb_undo_logs ДаДаДа Глобальная Да
innodb_undo_tablespacesДаДаДа ГлобальнаяНет
innodb_use_native_aioДаДаДа ГлобальнаяНет
innodb_version Да ГлобальнаяНет
innodb_write_io_threadsДаДаДа ГлобальнаяНет
mecab_rc_file ДаДаДа Глобальная Нет
ngram_token_size ДаДаДа Глобальная Нет
unique_checks Да ОбеДа

Опции команд InnoDB

  • --ignore-builtin-innodb

    Устаревшая 5.5.22
    Формат командной строки --ignore-builtin-innodb
    Системная переменная Имя ignore_builtin_innodb
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Типboolean

    В MySQL 5.1 эта опция заставила сервер вести себя как будто встроенный InnoDB не присутствовал, что заставляет InnoDB Plugin использовать вместо этого. В MySQL 8.0 InnoDB механизм хранения по умолчанию и InnoDB Plugin не используется, таким образом, эта опция проигнорирована.

  • --innodb[=value]

    Устаревшая 5.7.5
    Формат командной строки --innodb[=value]
    Допустимые значения Тип enumeration
    Значение по умолчанию ON
    Допустимые значения OFF
    ON
    FORCE
    Допустимые значения Тип boolean

    Загрузка средств управления InnoDB, если сервер был собран с поддержкой InnoDB. У этой опции есть формат tristate, с возможными значениями OFF, ON или FORCE. См. раздел 6.6.2.

    Чтобы отключить InnoDB, используйте --innodb=OFF или --skip-innodb. В этом случае, потому что InnoDB механизм хранения по умолчанию, сервер не будет запускаться, если Вы также не будете использовать --default-storage-engine и --default-tmp-storage-engine, чтобы установить значением по умолчанию некоторый другой механизм для постоянных и для TEMPORARY таблиц.

    Механизм хранения InnoDB больше не может быть отключен, и --innodb=OFF и --skip-innodb устарели и не имеют никакого эффекта. Их использование приводит к предупреждению. Эти опции будут удалены в будущем выпуске MySQL.

  • --innodb-status-file

    Формат командной строки --innodb-status-file
    Допустимые значения Тип boolean
    Значение по умолчанию OFF

    Управляет, создает ли InnoDB файл innodb_status.pid в каталоге данных MySQL. Если включено, InnoDB периодически пишет вывод SHOW ENGINE INNODB STATUS в этот файл.

    По умолчанию файл не создается. Чтобы создать его, запустите mysqld с опцией --innodb-status-file=1. Файл удален во время нормального завершения работы.

  • --skip-innodb

    Отключает InnoDB. См. описание --innodb.

Системные переменные InnoDB

  • daemon_memcached_enable_binlog

    Формат командной строки --daemon_memcached_enable_binlog=#
    Системная переменная Имя daemon_memcached_enable_binlog
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип boolean
    Значение по умолчанию false

    См. раздел 16.19 для подробностей об этой опции.

  • daemon_memcached_engine_lib_name

    Формат командной строки --daemon_memcached_engine_lib_name=library
    Системная переменная Имя daemon_memcached_engine_lib_name
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип file name
    Значение по умолчанию innodb_engine.so

    Определяет совместно используемую библиотеку, которая осуществляет плагин InnoDB memcached.

    См. раздел 16.19.

  • daemon_memcached_engine_lib_path

    Формат командной строки --daemon_memcached_engine_lib_path=directory
    Системная переменная Имя daemon_memcached_engine_lib_path
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип directory name
    Значение по умолчанию NULL

    Путь к каталогу, содержащесу совместно используемую библиотеку, которая осуществляет плагин InnoDB memcached . Значение по умолчанию NULL, представляя каталог плагинов MySQL. Вы не должны менять этот параметр, не определяя иной механизм хранения, плагин для которого расположен за пределами каталога плагинов MySQL.

    См. раздел 16.19.

  • daemon_memcached_option

    Формат командной строки --daemon_memcached_option=options
    Системная переменная Имя daemon_memcached_option
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип string
    Значение по умолчанию

    Используется, чтобы передать разделенные пробелом опции memcached опции к основному демону кэширования объекта памяти при запуске. Например, Вы могли бы изменить порт, на котором слушает memcached, уменьшить максимальное количество одновременных соединений, изменить максимальный размер памяти для пары ключ/значение или позволить отладочные сообщения для журнала ошибок.

    См. раздел 16.19.

  • daemon_memcached_r_batch_size

    Формат командной строки --daemon_memcached_r_batch_size=#
    Системная переменная Имя daemon_memcached_r_batch_size
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип integer
    Значение по умолчанию 1

    Определяет, сколько операций чтения memcached (get) выполнить прежде, чем сделать COMMIT, чтобы запустить новую транзакцию. Копия daemon_memcached_w_batch_size.

    Это значение установлено в 1 по умолчанию, чтобы любые изменения, произведенные в таблице через запросы SQL, были немедленно видимы в memcached. Вы могли бы увеличить это, чтобы уменьшить издержки от частых передач в системе, где к основной таблице получают доступ только через интерфейс memcached . Если Вы устанавливаете слишком большое значение, размер данных в undo или redo добавит издержек по системе хранения, как с любой продолжительной транзакцией.

    См. раздел 16.19.

  • daemon_memcached_w_batch_size

    Формат командной строки --daemon_memcached_w_batch_size=#
    Системная переменная Имя daemon_memcached_w_batch_size
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип integer
    Значение по умолчанию 1

    Определяет, скольким операциям записи memcached таким, как add, set или incr, выполниться прежде, чем сделать COMMIT. Копия daemon_memcached_r_batch_size.

    Это значение установлено в 1 по умолчанию, при условии, что любые хранимые данные важны, чтобы сохранить в случае отключения электричества и должны немедленно быть переданы. Храня некритические данные, Вы могли бы увеличить это значение, чтобы уменьшить издержки, но тогда последние N-1 операций записи могут быть потеряны в случае катастрофического отказа. См. раздел 16.19.

  • ignore_builtin_innodb

    Устаревшая 5.5.22
    Формат командной строки --ignore-builtin-innodb
    Системная переменная Имя ignore_builtin_innodb
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип boolean

    См. описание на --ignore-builtin-innodb.

  • innodb_adaptive_flushing

    Формат командной строки --innodb_adaptive_flushing=#
    Системная переменная Имя innodb_adaptive_flushing
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию ON

    Определяет, скорректировать ли динамически уровень сброса грязных страниц в буферном пуле, основываясь на рабочей нагрузке. Корректировка уровня потока динамически предназначена, чтобы избежать взрывов деятельности ввода/вывода. Эта установка включена по умолчанию. См. раздел 16.6.3.6. Для общих советов по настройке ввода/вывода см. раздел 9.5.8.

  • innodb_adaptive_flushing_lwm

    Формат командной строки --innodb_adaptive_flushing_lwm=#
    Системная переменная Имя innodb_adaptive_flushing_lwm
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 10
    Минимум 0
    Максимум 70

    Нижний предел процента размера журнала redo, на котором включен адаптивный сброс.

  • innodb_adaptive_hash_index

    Формат командной строки --innodb_adaptive_hash_index=#
    Системная переменная Имя innodb_adaptive_hash_index
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию ON

    Включен или отключен адаптивный хеш индекс. Может быть желательно, в зависимости от Вашей рабочей нагрузки, динамически включить или отключить адаптивный хеш индекс, чтобы улучшить работу запроса. Поскольку адаптивный хеш индекс, возможно, не полезен для всех рабочих нагрузок, надо смотреть результаты работы с ним, используя реалистические рабочие нагрузки. См. раздел 16.4.3.

    Эта переменная включена по умолчанию. Вы можете изменить этот параметр, используя SET GLOBAL, не перезапуская сервер. Изменение настроек требует привилегии SUPER. Вы можете также использовать --skip-innodb_adaptive_hash_index при запуске сервера, чтобы отключить это.

    Отключение адаптивного хеш-индекса опустошает хэш-таблицу немедленно. Нормальное функционирование может продолжиться, в то время как хэш-таблица освобождена, и выполняются запросы, которые использовали хэш-таблицу, получают доступ к индексным B-деревьям непосредственно вместо этого. Когда адаптивный хеш-индекс повторно включен, хэш-таблица заполнена снова во время нормального функционирования.

  • innodb_adaptive_hash_index_parts

    Формат командной строки --innodb_adaptive_hash_index_parts=#
    Системная переменная Имя innodb_adaptive_hash_index_parts
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип numeric
    Значение по умолчанию 8
    Минимум 1
    Максимум 512

    Разделы системы поиска адаптивного хеш-индекса. Каждый индекс связан с определенным разделом, каждый раздел защищен отдельно.

    Адаптивный хеш индекс разделен на 8 частей по умолчанию. Максимальная установка 512.

    См. раздел 16.4.3.

  • innodb_adaptive_max_sleep_delay

    Формат командной строки --innodb_adaptive_max_sleep_delay=#
    Системная переменная Имя innodb_adaptive_max_sleep_delay
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 150000
    Минимум 0
    Максимум 1000000

    Позволяет автоматически скорректировать значение innodb_thread_sleep_delay, согласно текущей рабочей нагрузке. Любое ненулевое значение включает автоматизированную динамическую корректировку innodb_thread_sleep_delay до максимального значения, определенного в innodb_adaptive_max_sleep_delay. Значение представляет число микросекунд. Эта опция может быть полезной в занятых системах, более чем с 16 потоками InnoDB. Практически это является самым ценным для систем MySQL с сотнями или тысячами одновременных соединений.

    См. раздел 16.6.5.

  • innodb_api_bk_commit_interval

    Формат командной строки --innodb_api_bk_commit_interval=#
    Системная переменная Имя innodb_api_bk_commit_interval
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 5
    Минимум 1
    Максимум 1073741824

    Как часто передать неактивные соединения, которые используют InnoDB memcached, в секундах. См. раздел 16.19.

  • innodb_api_disable_rowlock

    Формат командной строки --innodb_api_disable_rowlock=#
    Системная переменная Имя innodb_api_disable_rowlock
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип boolean
    Значение по умолчанию OFF

    Используйте эту переменную, чтобы отключить блокировки строки, когда InnoDB memcached выполняет DML. По умолчанию innodb_api_disable_rowlock OFF, что означает, что memcached просит блокировки строки для операций получения и установки. Когда innodb_api_disable_rowlock ON, memcached просит табличную блокировку вместо блокировок строки.

    innodb_api_disable_rowlock не является динамичной. Это должно быть определено в командной строке mysqld или введено в конфигурационный файл MySQL. Конфигурация вступает в силу, когда плагин установлен, что делается каждый раз, когда сервер MySQL запущен.

  • innodb_api_enable_binlog

    Формат командной строки --innodb_api_enable_binlog=#
    Системная переменная Имя innodb_api_enable_binlog
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип boolean
    Значение по умолчанию OFF

    Позволяет Вам использовать плагин memcached с MySQL двоичным журналом. См. раздел 16.19.

  • innodb_api_enable_mdl

    Формат командной строки --innodb_api_enable_mdl=#
    Системная переменная Имя innodb_api_enable_mdl
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип boolean
    Значение по умолчанию OFF

    Блокирует таблицу, используемую memcached, чтобы это не могло быть удалено или изменено DDL через интерфейс SQL. См. раздел 16.19.

  • innodb_api_trx_level

    Формат командной строки --innodb_api_trx_level=#
    Системная переменная Имя innodb_api_trx_level
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 0

    Позволяет Вам управлять операционным уровнем изоляции на запросах, обработанных интерфейсом memcached . См. раздел 16.19. Константы, соответствующие именам:

  • innodb_autoextend_increment

    Формат командной строки --innodb_autoextend_increment=#
    Системная переменная Имя innodb_autoextend_increment
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 64
    Минимум 1
    Максимум 1000

    Размер увеличения (в MB) для того, чтобы расширить размер файла системного табличного пространства, когда это становится полным. Значение по умолчанию 64. Эта переменная не затрагивает файлы file-per-table (.ibd), которые создаются, если Вы используете innodb_file_per_table=1, или общее табличное пространство. Те файлы автомасштабируются независимо от значения innodb_autoextend_increment. Начальные расширения идут небольшими порциями, после которых расширения происходят блоками по 4MB.

  • innodb_autoinc_lock_mode

    Формат командной строки --innodb_autoinc_lock_mode=#
    Системная переменная Имя innodb_autoinc_lock_mode
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип integer
    Значение по умолчанию 1
    Допустимые значения 0
    1
    2

    Режим блокировки, чтобы произвести значения auto-increment. Допустимые значения 0, 1 или 2 для режимов traditional, consecutive или interleaved. раздел 16.8.5 описывает характеристики этих режимов.

    У этой переменной есть значение по умолчанию 1 (consecutive).

  • innodb_background_drop_list_empty

    Формат командной строки --innodb_background_drop_list_empty=#
    Системная переменная Имя innodb_background_drop_list_empty
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию OFF

    Включение опции отладки innodb_background_drop_list_empty помогает избежать отказов, задерживая табличное создание, пока фоновый список удаления не пуст. Например, если случай теста A поместил таблицу t1 в фоновый список, случай теста B пока фоновый список не пуст прежде, чем составить таблицу t1.

  • innodb_buffer_pool_chunk_size

    Формат командной строки --innodb_buffer_pool_chunk_size
    Системная переменная Имя innodb_buffer_pool_chunk_size
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип integer
    Значение по умолчанию 134217728
    Минимум 1048576
    Максимум innodb_buffer_pool_size/innodb_buffer_pool_instances

    innodb_buffer_pool_chunk_size определяет размер куска для изменения размера буферного пула.

    innodb_buffer_pool_size является динамичным, который позволяет Вам изменять размеры буферного пула, не перезапуская сервер. Чтобы избежать копировать все буферные страницы пула во время изменения размеров операций, работа выполнена кусками. Размер куска определен innodb_buffer_pool_chunk_size. По умолчанию innodb_buffer_pool_chunk_size 128 MB (134217728 байт). Число страниц, содержавшихся в куске, зависит от значения innodb_page_size. innodb_buffer_pool_chunk_size может быть увеличен или уменьшен с шагом 1MB (1048576 байт).

    Следующие условия применяются, изменяя innodb_buffer_pool_chunk_size:

    Меняя innodb_buffer_pool_chunk_size будьте осторожны, так как изменяя это значение можно автоматически увеличить размер буферного пула. Прежде, чем Вы измените innodb_buffer_pool_chunk_size, вычислите эффект, который это будет иметь innodb_buffer_pool_size, чтобы гарантировать, что получающийся буферный размер пула является приемлемым.

    Чтобы избегать потенциальных исполнительных проблем, число кусков ( innodb_buffer_pool_size/ innodb_buffer_pool_chunk_size) не должно превысить 1000.

    См. раздел 16.6.3.2.

  • innodb_buffer_pool_debug

    Формат командной строки --innodb_buffer_pool_debug=#
    Системная переменная Имя innodb_buffer_pool_debug
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип boolean
    Значение по умолчанию OFF

    Включение этой опции разрешает многократные буферные экземпляры, когда буферный пул меньше 1GB, игнорируя ограничение минимума размера пула в 1GB, наложенное на innodb_buffer_pool_instances. Опция innodb_buffer_pool_debug доступна, если поддержка отладка собрана с использованием опции WITH_DEBUG в CMake.

  • innodb_buffer_pool_dump_at_shutdown

    Формат командной строки --innodb_buffer_pool_dump_at_shutdown=#
    Системная переменная Имя innodb_buffer_pool_dump_at_shutdown
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию ON

    Определяет, сделать ли запись страниц, кэшируемых в буферном пуле, когда сервер MySQL закрыт, чтобы сократить процесс разминки в следующем перезапуске. Как правило используется в комбинации с innodb_buffer_pool_load_at_startup. Опция innodb_buffer_pool_dump_pct определяет процент последний раз используемых буферных страниц пула для дампа.

    innodb_buffer_pool_dump_at_shutdown и innodb_buffer_pool_load_at_startup включены по умолчанию.

    См. раздел 16.6.3.8.

  • innodb_buffer_pool_dump_now

    Формат командной строки --innodb_buffer_pool_dump_now=#
    Системная переменная Имя innodb_buffer_pool_dump_now
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию OFF

    Немедленно делает запись страниц, кэшируемых в буферном пуле. Как правило используется в комбинации с innodb_buffer_pool_load_now.

    См. раздел 16.6.3.8.

  • innodb_buffer_pool_dump_pct

    Формат командной строки --innodb_buffer_pool_dump_pct=#
    Системная переменная Имя innodb_buffer_pool_dump_pct
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 25
    Минимум 1
    Максимум 100

    Определяет процент последний раз используемых страниц для каждого буферного пула, чтобы читать и сбросить в дамп. Диапазон 1-100. Значение по умолчанию 25. Например, если есть 4 буферных пула с 100 страницами каждый, и innodb_buffer_pool_dump_pct 25, то 25 последний раз используемых страниц из каждого буферного пула выведены в дамп.

  • innodb_buffer_pool_filename

    Формат командной строки --innodb_buffer_pool_filename=file
    Системная переменная Имя innodb_buffer_pool_filename
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип file name
    Значение по умолчанию ib_buffer_pool

    Определяет название файла, который хранит список ID табличного пространства и страниц, произведенный innodb_buffer_pool_dump_at_shutdown или innodb_buffer_pool_dump_now. ID сохраняют следующий формат: space, page_id. По умолчанию, файл называют ib_buffer_pool и расположен он в каталоге данных. Местоположение не по умолчанию должно быть определено относительно каталога данных.

    Имя файла может быть определено во время выполнения, используя SET:

    SET GLOBAL innodb_buffer_pool_filename='file_name';
    

    Вы можете также определить определяемое пользователем имя файла при запуске в строке запуска или конфигурационном файле MySQL. Определяя имя файла при запуске, файл должен уже существовать или InnoDB возвратит ошибку запуска, указывающую, что нет такого файла или каталога.

    См. раздел 16.6.3.8.

  • innodb_buffer_pool_instances

    Формат командной строки --innodb_buffer_pool_instances=#
    Системная переменная Имя innodb_buffer_pool_instances
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения (Windows, 32-bit platforms)Тип integer
    Значение по умолчанию (autosized)
    Минимум 1
    Максимум 64
    Допустимые значения (Другие)Тип integer
    Значение по умолчанию 8 (или 1, если innodb_buffer_pool_size < 1GB
    Минимум 1
    Максимум 64

    Число областей, на которые буферный пул разделен. Для систем с буферными пулами в диапазоне нескольких гигабай деление буферного пула на отдельные экземпляры может улучшить параллелизм, уменьшая издержки на различное чтение потоков и запись кэшируемых страниц. Каждая страница, которая сохранена или считана из буферного пула, назначена на один из буферных экземпляров пула беспорядочно, используя хеширующую функцию. Каждый буферный пул управляет своими собственными свободными списками, списками потока, LRU и всеми другими структурами данных, соединенными с буферным пулом, и защищен его собственным mutex.

    Эта опция вступает в силу, только когда Вы устанавливаете innodb_buffer_pool_size в 1GB или больше. Полный буферный размер пула разделен среди всех буферных пулов. Для лучшей эффективности определите комбинацию innodb_buffer_pool_instances и innodb_buffer_pool_size так, чтобы каждый буферный экземпляр был минимум в 1GB.

    Значение по умолчанию в 32-bit Windows зависит от значения innodb_buffer_pool_size:

    • Если innodb_buffer_pool_size больше 1.3GB, значение по умолчанию для innodb_buffer_pool_instances= innodb_buffer_pool_size/128MB, с отдельным распределением памяти для каждого куска. 1.3GB был выбран в качестве границы, в которой есть существенный риск для 32-битной Windows не быть способной выделить непрерывное адресное пространство, необходимое для единственного буферного пула.

    • Иначе значение по умолчанию 1.

    На всех других платформах значение по умолчанию 8, когда innodb_buffer_pool_size больше или равен 1GB. Иначе 1.

    См. раздел 16.6.3.2.

  • innodb_buffer_pool_load_abort

    Формат командной строки --innodb_buffer_pool_load_abort=#
    Системная переменная Имя innodb_buffer_pool_load_abort
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию OFF

    Прерывает процесс восстановления содержания буферного пула, вызванный innodb_buffer_pool_load_at_startup или innodb_buffer_pool_load_now.

    См. раздел 16.6.3.8.

  • innodb_buffer_pool_load_at_startup

    Формат командной строки --innodb_buffer_pool_load_at_startup=#
    Системная переменная Имя innodb_buffer_pool_load_at_startup
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип boolean
    Значение по умолчанию ON

    Определяет, что на запуске сервера MySQL буферный пул автоматически подогревается, загружая те же самые страницы, которые это содержало в более раннее время. Как правило, используется в комбинации с innodb_buffer_pool_dump_at_shutdown.

    innodb_buffer_pool_dump_at_shutdown и innodb_buffer_pool_load_at_startup включены по умолчанию.

    См. раздел 16.6.3.8.

  • innodb_buffer_pool_load_now

    Формат командной строки --innodb_buffer_pool_load_now=#
    Системная переменная Имя innodb_buffer_pool_load_now
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию OFF

    Немедленно нагревает буферный пул, загружая ряд страниц данных, не ожидая перезапуска сервера. Может быть полезным, чтобы возвратить кэш-память к известному состоянию во время сопоставительного анализа, или к готовому сервер MySQL, чтобы возобновить его нормальную рабочую нагрузку после выполнения запросов для отчетов или обслуживания. См. раздел 16.6.3.8.

  • innodb_buffer_pool_size

    Формат командной строки --innodb_buffer_pool_size=#
    Системная переменная Имя innodb_buffer_pool_size
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 8388608
    Минимум 1048576
    Допустимые значения (32-bit platforms)Тип integer
    Значение по умолчанию 134217728
    Минимум 5242880
    Максимум 2**32-1
    Допустимые значения (64-bit platforms)Тип integer
    Значение по умолчанию 134217728
    Минимум 5242880
    Максимум 2**64-1

    Размер в байтах буферного пула , области памяти, где InnoDB хранит таблицу кэшей и индексные данные. Значение по умолчанию составляет 128 МБ. Максимальное значение зависит от архитектуры центрального процессора: максимум 4294967295 (232-1) в 32-bit системах и 18446744073709551615 (264-1) в 64-bit системах. В 32-bit системах архитектура центрального процессора и операционная система могут наложить более низкий практический максимальный размер, чем установленный максимум. Когда размер буферного пула больше 1GB, установка innodb_buffer_pool_instances к значению больше 1 может улучшить масштабируемость относительно занятого сервера.

    Буферный пул большего размера требует, чтобы меньше дискового ввода/вывода получило доступ к тем же самым табличным данным. На специализированном сервере базы данных Вы могли бы установить буферный размер пула в 80% размера физической памяти машины. Знайте о следующих потенциальных проблемах, когда конфигурируете размер буфера, и будьте подготовлены вычислить размер буферного пула в случае необходимости.

    • Соревнование за физическую память может вызвать своп в операционной системе.

    • InnoDB резервирует дополнительную память для буферов и структур управления, чтобы полное выделенное место было приблизительно на 10% больше, чем указанный размер пула.
    • Адресное пространство для буферного пула должно быть непрерывным, что может быть проблемой на системах Windows с DLL, которые загружаются в определенных адресах.
    • Время, чтобы инициализировать буферный пул, примерно пропорционально его размеру. На больших установках время инициализации могло бы быть существенным. Например, на современном сервере Linux x86_64 инициализация буферного пула в 10 GB занимает приблизительно 6 секунд. См. раздел 16.6.3.1.

    Когда Вы увеличиваете или уменьшаете размер пула, работа выполнена в кусках. Размер куска определен innodb_buffer_pool_chunk_size, у которой есть значение по умолчанию 128 MB.

    Буферный размер должен всегда быть равным или кратным innodb_buffer_pool_chunk_size * innodb_buffer_pool_instances. Если Вы изменяете буферный размер к значению, которое не равно или кратно innodb_buffer_pool_chunk_size* innodb_buffer_pool_instances, буферный размер автоматически скорректирован к значению, которое равно или кратно innodb_buffer_pool_chunk_size* innodb_buffer_pool_instances, но не меньше, чем указанный буферный размер.

    innodb_buffer_pool_size может быть установлен динамически, что позволяет Вам изменять размеры буферного пула, не перезапуская сервер. Innodb_buffer_pool_resize_status сообщает о состоянии изменения размера буферного пула. См. раздел 16.6.3.2.

  • innodb_change_buffer_max_size

    Формат командной строки --innodb_change_buffer_max_size=#
    Системная переменная Имя innodb_change_buffer_max_size
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 25
    Минимум 0
    Максимум 50

    Максимальный размер для буфера изменений, как процент от полного размера буферного пула. Вы могли бы увеличить это значение для сервера MySQL с тяжелой вставкой, обновлением и удалением или уменьшить это для сервера MySQL с неизменными данными. Для общих советов по настройке ввода/вывода см. раздел 9.5.8.

  • innodb_change_buffering

    Формат командной строки --innodb_change_buffering=#
    Системная переменная Имя innodb_change_buffering
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип enumeration
    Значение по умолчанию all
    Допустимые значения none
    inserts
    deletes
    changes
    purges
    all

    Выполняет ли InnoDB буферизацию изменений, оптимизируя задержки операции записи вторичного индекса так, чтобы операции ввода/вывода могли быть выполнены последовательно. Разрешенные значения описаны в следующей таблице. Значения могут также быть определены в цифровой форме. Для получения дополнительной информации см. раздел 16.6.4. Для общих советов по настройке ввода/вывода см. раздел 9.5.8.

    Таблица 16.11. Разрешенные значения для innodb_change_buffering

    ValueЧисловое значение Описание
    none0 Не буферизовать операции.
    inserts1 Буферизовать операции вставки.
    deletes2 Буферизовать операции маркировки удаления, строго говоря, отметка записей индекса для более позднего удаления во время работы чистки.
    changes3 Буферизовать операции маркировки удаления и вставки.
    purges4 Буферизовать операции удаления, которые происходят в фоне.
    all5 По умолчанию. Буферизовать операции маркировки удаления, вставки и чистки.
  • innodb_change_buffering_debug

    Формат командной строки --innodb_change_buffering_debug=#
    Системная переменная Имя innodb_change_buffering_debug
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 0
    Максимум 2

    Устанавливает флаг отладки для буферизации изменений. Значение 1 пишет все изменения буфера изменения. Значение 2 пишет катастрофический отказ при слиянии. Значение по умолчанию 0 указывает, что флаг отладки, не установлен. Эта опция только доступна, когда отладка поддержки собрана с использованием WITH_DEBUG в CMake.

  • innodb_checksum_algorithm

    Формат командной строки --innodb_checksum_algorithm=#
    Системная переменная Имя innodb_checksum_algorithm
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип enumeration
    Значение по умолчанию crc32
    Допустимые значения innodb
    crc32
    none
    strict_innodb
    strict_crc32
    strict_none

    Определяет, как произвести и проверить контрольную сумму, сохраненную в каждом дисковом блоке каждого табличного пространства. Значение по умолчанию для innodb_checksum_algorithm crc32.

    MySQL Enterprise Backup до версии 3.8.0 не поддерживают табличные пространства с использованием контрольных сумм CRC32. MySQL Enterprise Backup добавляет поддержку контрольной суммы CRC32 в 3.8.1 с некоторыми ограничениями.

    Значение innodb обратно совместимо со всеми версиями MySQL. Значение crc32 использует алгоритм, который быстрее, чтобы вычислить контрольную сумму для каждого измененного блока и проверить контрольные суммы при каждом дисковом чтении. Это просматривает блоки по 32 бита за один раз, что является быстрее алгоритма контрольной суммы innodb, который просматривает блоки по 8 бит за раз. Значение none пишет постоянную величину в области контрольной суммы вместо того, чтобы вычислить значение, основанное на данных о блоке. Блоки в табличном пространстве могут использовать соединение старых, новых и никаких значений контрольной суммы, будучи обновлены постепенно, по мере того, как данные изменены. Как только любые блоки в табличном пространстве изменены, чтобы использовать crc32, связанные таблицы не могут быть считаны более ранними версиями MySQL.

    Форма strict_* работает как innodb, crc32 и none, за исключением того, что InnoDB сообщает об ошибке, если сталкивается с допустимым, но несоответствующим значением контрольной суммы. В этом случае страница все еще принята как допустимая. Рекомендуется, чтобы Вы использовали strict_* только в новом экземпляре, чтобы настроить все табличные пространства впервые. Настройки strict_* несколько быстрее, потому что они не должны вычислить все значения контрольной суммы во время дисковых чтений.

    Следующая таблица иллюстрирует различие между значениями опции и их версиями strict_. none, innodb и crc32 пишут указанный тип значения контрольной суммы в каждый блок данных, но для совместимости принимают любое из других значений контрольной суммы, проверяя блок во время работы чтения. Форма strict_ каждого параметра также принимает любое допустимое значение контрольной суммы, но печатает сообщение об ошибке, когда сталкивается с несоответствием допустимого значения контрольной суммы. Используя strict_* можно сделать проверку быстрее, если все файлы с данными создаются с идентичным значением innodb_checksum_algorithm.

    Таблица 16.12. Настройки innodb_checksum_algorithm

    ЗначениеПроизведенная контрольная сумма (при записи) Разрешенные контрольные суммы (при чтении)
    noneЧисло. Любая из контрольных сумм, произведенных none, innodb или crc32.
    innodbКонтрольная сумма, вычисленная в программном обеспечении, используя оригинальный алгоритм InnoDB. Любая из контрольных сумм, произведенных none, innodb или crc32.
    crc32Контрольная сумма, вычисленная с использованием алгоритма crc32, возможно сделанного аппаратными средствами. Любая из контрольных сумм, произведенных none, innodb или crc32.
    strict_noneЧисло.Любая из контрольных сумм, произведенных none, innodb или crc32. InnoDB печатает сообщение об ошибке, если сталкивается с допустимой, но несоответствующей контрольной суммой.
    strict_innodbКонтрольная сумма, вычисленная в программном обеспечении, используя оригинальный алгоритм InnoDB. Любая из контрольных сумм, произведенных none, innodb или crc32. InnoDB печатает сообщение об ошибке, если сталкивается с допустимой, но несоответствующей контрольной суммой.
    strict_crc32Контрольная сумма, вычисленная с использованием алгоритма crc32, возможно сделанного аппаратными средствами. Любая из контрольных сумм, произведенных none, innodb или crc32. InnoDB печатает сообщение об ошибке, если сталкивается с допустимой, но несоответствующей контрольной суммой.
  • innodb_cmp_per_index_enabled

    Формат командной строки --innodb_cmp_per_index_enabled=#
    Системная переменная Имя innodb_cmp_per_index_enabled
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию OFF
    Допустимые значения OFF
    ON

    Включает индексную связанную со сжатием статистику в INFORMATION_SCHEMA.INNODB_CMP_PER_INDEX. Поскольку эти статистические данные могут быть дорогими в сборе, включите эту опцию только на тесте или ведомых экземплярах во время исполнительной настройки, связанной с сжатыми таблицами InnoDB.

  • innodb_commit_concurrency

    Формат командной строки --innodb_commit_concurrency=#
    Системная переменная Имя innodb_commit_concurrency
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 0
    Минимум 0
    Максимум 1000

    Число потоков, которые могут завершать транзакции в то же самое время. Значение 0 (значение по умолчанию) разрешает любое число транзакций одновременно.

    Значение innodb_commit_concurrency не может быть изменено во время выполнения от ноля до отличного от нуля или наоборот. Значение может быть изменено от одного ненулевого значения до другого.

  • innodb_compress_debug

    Формат командной строки --innodb_compress_debug=#
    Системная переменная Имя innodb_compress_debug
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип enumeration
    Значение по умолчанию none
    Допустимые значения none
    zlib
    lz4
    lz4hc

    Сжимает все таблицы, используя указанный алгоритм сжатия, не имея необходимости определять атрибут COMPRESSION для каждой таблицы. Эта опция доступна только, если поддержка отладки собрана с использованием WITH_DEBUG в CMake.

  • innodb_compression_failure_threshold_pct

    Формат командной строки --innodb_compression_failure_threshold_pct=#
    Системная переменная Имя innodb_compression_failure_threshold_pct
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 5
    Минимум 0
    Максимум 100

    Устанавливает предел, в котором MySQL начинает добавлять место в пределах сжатых страниц, чтобы избежать дорогих отказов сжатия. Значение 0 отключает механизм, который контролирует эффективность сжатия и динамически корректирует количество места. См. раздел 16.9.1.6.

  • innodb_compression_level

    Формат командной строки --innodb_compression_level=#
    Системная переменная Имя innodb_compression_level
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 6
    Минимум 0
    Максимум 9

    Определяет уровень zlib сжатия, чтобы использовать для сжатых таблицы и индекса. См. раздел 16.9.1.6 .

  • innodb_compression_pad_pct_max

    Формат командной строки --innodb_compression_pad_pct_max=#
    Системная переменная Имя innodb_compression_pad_pct_max
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 50
    Минимум 0
    Максимум 75

    Определяет максимальный процент, который может быть сохранен как свободное пространство в пределах каждой сжатой страницы, позволяя реорганизовать данные и журнал модификации в пределах страницы, когда a сжатая таблица или индекс обновлены, и данные могли бы быть повторно сжаты. Применяется только когда innodb_compression_failure_threshold_pct установлен в ненулевое значение, и уровень отказов сжатия передает предел. См. раздел 16.9.1.6.

  • innodb_concurrency_tickets

    Формат командной строки --innodb_concurrency_tickets=#
    Системная переменная Имя innodb_concurrency_tickets
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 5000
    Минимум 1
    Максимум 4294967295

    Определяет число потоков, которые могут работать одновременно. Поток помещен в очередь, когда он пытается обратиться к InnoDB, если число потоков уже достигло предела параллелизма. Когда потоку разрешают работать, ему дают несколько свободных тикетов, заданное значением innodb_concurrency_tickets, поток работает, пока не израсходует свои тикеты. После этого поток снова подвергается проверке параллелизма (и возможна организация очереди) в следующий раз, когда пытается обратиться к InnoDB. Значение по умолчанию 5000.

    С маленьким значением innodb_concurrency_tickets маленькие транзакции, которые должны обработать только несколько строк, конкурирует справедливо с большими транзакциями, которые обрабатывают много строк. Недостаток маленького innodb_concurrency_tickets: большие транзакции должны образовать петли через очередь много раз прежде, чем они смогут завершиться, что расширяет отрезок времени, требуемый, чтобы завершить их задачу.

    С большим значением innodb_concurrency_tickets большие транзакции проводят меньше времени, ожидая позиции в конце очереди (управляемой innodb_thread_concurrency) и получение строки требует большего количества времени. Большие транзакции также требуют меньше проходов через очередь. Недостаток большого innodb_concurrency_tickets: слишком много больших транзакций, работающих в то же самое время, могут держать меньшие транзакции, заставляя их ждать более длительное время перед выполнением.

    С отличным от нуля значением innodb_thread_concurrency Вы, возможно, должны корректировать innodb_concurrency_tickets, чтобы найти оптимальный баланс между большими и меньшими транзакциями. SHOW ENGINE INNODB STATUS показывает число билетов, остающихся для транзакции выполнения в ее потоке, при текущем проходе через очередь. Эти данные могут также быть получены из столбца TRX_CONCURRENCY_TICKETS таблицы INFORMATION_SCHEMA.INNODB_TRX .

    См. раздел 16.6.5.

  • innodb_data_file_path

    Формат командной строки --innodb_data_file_path=name
    Системная переменная Имя innodb_data_file_path
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип string
    Значение по умолчанию ibdata1:12M:autoextend

    Пути к файлам с данными и их размеры. Полный путь к каталогу к каждому файлу с данными сформирован, добавляя innodb_data_home_dir к каждому пути, определенному здесь. Размеры файл определен в KB, MB или GB (1024 MB), добавляя K, M или G к значению размера. Определяя размер файла с данными в килобайтах (КБ), умножьте его на 1024. Иначе значения КБ округлены к самому близкому мегабайту (MB). Сумма размеров файлов должна быть, по крайней мере, немного больше 10 МБ. Если Вы не определяете innodb_data_file_path, поведение по умолчанию должно создать единственный автомасштабируемый файл с данными, немного больше 12 МБ, названный ibdata1. Предел размера отдельных файлов определен Вашей операционной системой. Вы можете установить размер файла больше 4 ГБ на тех операционных системах, которые поддерживают большие файлы. Вы можете также использовать сырой дисковый раздел в качестве файлов с данными. См. раздел 16.6.

    Следующие минимальные размеры файла проведены в жизнь для первого системного файла с данными табличного пространства (ibdata1), чтобы гарантировать, что есть достаточно пространства для буферных блоков doublewrite (Bug #20972309):

    • Для innodb_page_size 16 KB или меньше минимальный размер файла с данными составляет 3 МБ.

    • Для innodb_page_size 32 KB минимальный размер файла с данными составляет 6 MB.
    • Для innodb_page_size 64 KB минимальный размер файла с данными составляет 12 MB.

  • innodb_data_home_dir

    Формат командной строки --innodb_data_home_dir=dir_name
    Системная переменная Имя innodb_data_home_dir
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип Имя каталога

    Общая часть пути к каталогу для всех файлов с данными в системном табличном пространстве. Эта установка не затрагивает местоположение табличных пространств file-per-table, когда включена опция innodb_file_per_table. Значение по умолчанию каталог MySQL data. Если Вы определяете значение как пустую строку, Вы можете использовать абсолютные пути к файлам в innodb_data_file_path .

  • innodb_deadlock_detect

    Формат командной строки --innodb_deadlock_detect
    Системная переменная Имя innodb_deadlock_detect
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию ON

    Эта опция используется, чтобы отключить обнаружение тупика. На системах с высоким параллелизмом обнаружение тупика может вызвать замедление, когда многочисленные потоки ждут той же самой блокировки. Время от времени может быть более эффективно отключить обнаружение тупика и положиться на innodb_lock_wait_timeout для операционной отмены, когда тупик происходит.

  • innodb_default_row_format

    Формат командной строки --innodb_default_row_format=#
    Системная переменная Имя innodb_default_row_format
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип enumeration
    Значение по умолчанию DYNAMIC
    Допустимые значения DYNAMIC
    COMPACT
    REDUNDANT

    Определяет формат строки по умолчанию для таблицы (включая создаваемые пользователем временные таблицы). Настройка по умолчанию DYNAMIC. Другие разрешенные значения COMPACT и REDUNDANT. COMPRESSED не поддержан для использования в системном табличном пространстве и не может быть определен как значение по умолчанию.

    Недавно составленные таблицы используют формат строки, определенный innodb_default_row_format, когда опция ROW_FORMAT не определена явно или когда используется ROW_FORMAT=DEFAULT.

    Когда ROW_FORMAT не определена явно или определена как ROW_FORMAT=DEFAULT, любая работа, которая пересоздает таблицу, также тихо изменяет формат строки таблицы к формату, определенному innodb_default_row_format. См. раздел 16.10.2.

    Внутренние временные таблицы, составленные сервером, чтобы обработать запросы, используют формат DYNAMIC, независимо от innodb_default_row_format.

  • innodb_disable_sort_file_cache

    Формат командной строки --innodb_disable_sort_file_cache=#
    Системная переменная Имя innodb_disable_sort_file_cache
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию OFF

    Если включено, эта переменная отключает кэш файловой системы операционной системы для сортировки и слияния временных файлов. Эффект состоит в том, чтобы открыть такие файлы с эквивалентом O_DIRECT.

  • innodb_doublewrite

    Формат командной строки --innodb-doublewrite
    Системная переменная Имя innodb_doublewrite
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип boolean
    Значение по умолчанию ON

    Если эта переменная включена (значение по умолчанию), InnoDB хранит все данные дважды, сначала в буфере doublewrite, затем в фактические файлы с данными . Эта переменная может быть выключена --skip-innodb_doublewrite для точек отсчета или случаев, когда главная работа необходима, а не беспокойство о целостности данных или возможных отказах.

    Если системные файлы табличного пространства (ibdata ) расположены на устройствах Fusion-io, которые поддерживают атомную запись, буфер doublewrite автоматически отключен, и атомная запись Fusion-io используются для всех файлов с данными. Поскольку буферная установка doublewrite глобальна, буферизация также отключена для файлов с данными, находящихся на не-Fusion-io. Эта функция поддерживается только на аппаратных средствах Fusion-io и включена только для Fusion-io NVMFS в Linux. Чтобы в полной мере воспользоваться этой особенностью, установите innodb_flush_method в O_DIRECT.

  • innodb_fast_shutdown

    Формат командной строки --innodb_fast_shutdown[=#]
    Системная переменная Имя innodb_fast_shutdown
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 1
    Допустимые значения 0
    1
    2

    Режим InnoDB shutdown . Если значение 0, InnoDB делает медленное завершение работы, полную чистку и слияние буфера изменений перед закрытием. Если значение 1 (значение по умолчанию), InnoDB пропускает эти операции при завершении работы, процесс, известный как быстрое завершение работы. Если значение 2, InnoDB сбрасывает журналы и закрывается, как будто MySQL отказал, никакие переданные транзакции не потеряны, но работа восстановления катастрофического отказа заставляет следующий запуск занять больше времени.

    Медленное завершение работы может занять минуты или даже часы в крайних случаях, где значительное количество данных все еще буферизовано. Используйте медленный метод завершения работы прежде, чем обновить MySQL между главными выпусквси, чтобы все файлы с данными были полностью подготовлены в случае, если процесс обновления обновляет формат файла.

    innodb_fast_shutdown=2 применяется в чрезвычайной ситуации или ситуациях с поиском неисправностей, чтобы получить абсолютное самое быстрое завершение работы, если данные подвергаются риску повреждения.

  • innodb_fil_make_page_dirty_debug

    Формат командной строки --innodb_fil_make_page_dirty_debug=#
    Системная переменная Имя innodb_fil_make_page_dirty_debug
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 0
    Максимум 2**32-1

    По умолчанию установка innodb_fil_make_page_dirty_debug в ID табличного пространства немедленно помечает грязной первую страницу табличного пространства. Если innodb_saved_page_number_debug установлен в значение не по умолчанию, установка innodb_fil_make_page_dirty_debug помечает грязной указанную страницу. innodb_fil_make_page_dirty_debug доступна только если поддержка отладки собрана с использованием WITH_DEBUG в CMake.

  • innodb_file_per_table

    Формат командной строки --innodb_file_per_table
    Системная переменная Имя innodb_file_per_table
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию ON

    Когда innodb_file_per_table включен (значение по умолчанию), InnoDB хранит данные и индекс для каждой недавно составленной таблицы в отдельном файле .ibd, а не в системном табличном пространстве. Место для этих таблиц освобождено, когда таблицы удалены или усеченные. Эта установка позволяет несколько других особенностй, например, сжатие. См. раздел 16.7.4.

    Знайте, что включение innodb_file_per_table также значит, что ALTER TABLE переместит таблицу из системного табличного пространства в отдельный файл .ibd в случаях, где ALTER TABLE обновляет таблицу (ALGORITHM=COPY). Исключение: таблицы, которые были помещены в системное табличное пространство, используя опцию TABLESPACE=innodb_system в CREATE TABLE или ALTER TABLE. Эти таблицы не затронуты innodb_file_per_table и могут быть перемещены только в табличные пространства file-per-table, применяя ALTER TABLE ... TABLESPACE=innodb_file_per_table.

    Если innodb_file_per_table выключен, InnoDB хранит данные для всех таблиц и индексов в файлах ibdata, которые составляют системное табличное пространство. Эта установка уменьшает издержки операций файловой системы для таких операций, как DROP TABLE или TRUNCATE TABLE. Для окружающей среды сервера является самым уместным, что все устройства хранения данных посвящены данным MySQL. Поскольку системное табличное пространство никогда не сжимается и совместно использовано всеми базами данных, избегайте загружать огромное количество временных данных, если innodb_file_per_table=OFF. Настройте отдельный экземпляр в таких случаях, чтобы Вы могли удалить весь экземпляр, чтобы восстановить место.

    innodb_file_per_table включен по умолчанию. Рассмотрите отключение этого, если обратная совместимость с MySQL 5.5 или ранее является важной. Это не даст ALTER TABLE переместить таблицы из системного табличного пространства.

    innodb_file_per_table является динамичным и может быть установлен в ON или OFF через SET GLOBAL. Вы можете также установить эти параметры в конфигурационном файле MySQL (my.cnf или my.ini), но это требует закрытия и перезапуска сервера.

    Динамическое изменение значения этого параметра требует привилегии SUPER и немедленно затрагивает работу всех соединений.

    innodb_file_per-table не затрагивает создание временных таблиц. Все временные таблицы составлены в совместно используемом временном табличном пространстве.

  • innodb_fill_factor

    Формат командной строки --innodb_fill_factor=#
    Системная переменная Имя innodb_fill_factor
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 100
    Минимум 10
    Максимум 100

    InnoDB выполняет оптовую загрузку, когда создает или восстанавливает индекс. Этот метод известен как создание сортированного индекса.

    innodb_fill_factor определяет процент пространства на каждой странице B-дерева, которая заполнена во время создания сортированного индекса, с остающимся пространством, сохраненным для будущего роста индекса. Например, установка innodb_fill_factor в 80 резервирует 20% пространства на каждой странице B-дерева для будущего роста индекса. Фактические проценты могут измениться. innodb_fill_factor интерпретируется как подсказка, а не жесткий предел.

    innodb_fill_factor определяет 100 листьев 1/16 пространства в кластеризируемых индексных страницах, свободных для будущего роста индекса.

    innodb_fill_factor относится к страницам листа и нелиста B-дерева. Это не относится к внешним страницам, используемым для TEXT или BLOB.

    См. раздел 16.8.11.

  • innodb_flush_log_at_timeout

    Системная переменная Имя innodb_flush_log_at_timeout
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 1
    Минимум 1
    Максимум 2700

    Записать и сбросить журналы каждые N секунд. innodb_flush_log_at_timeout позволяет периоду тайм-аута между потоками быть увеличенным, чтобы уменьшить сброс и избежать падения производительности групповых записей в двоичный журнал. Настройка по умолчанию для innodb_flush_log_at_timeout однажды в секунду.

  • innodb_flush_log_at_trx_commit

    Формат командной строки --innodb_flush_log_at_trx_commit[=#]
    Системная переменная Имя innodb_flush_log_at_trx_commit
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип enumeration
    Значение по умолчанию 1
    Допустимые значения 0
    1
    2

    Управляет балансом между строгой совместимостью с ACID для commit и и более высокой производительностью, которая возможна, когда передача связанных операций ввода/вывода перестроена и сделана в пакетах. Вы можете достигнуть лучшей производительности, изменяя значение по умолчанию, но тогда Вы можете потерять до секунды транзакций в катастрофическом отказе.

    • Значение по умолчанию 1 требуется для полного соответствия ACID. С этим значением содержимое буфера журнала записано в файл системного журнала в каждой передаче транзакции, и файл системного журнала сброшен на диск.

    • Со значением 0 содержание буфера журнала записано в файл приблизительно однажды в секунду, и файл системного журнала сбрасывается на диск. Ежесекундный сброс не составляет 100% гарантию, что сброс будет происходить каждую секунду, есть проблемы планирования. Поскольку сброс на диск происходит приблизительно однажды в секунду, Вы можете потерять до секунды транзакций с любым катастрофическим отказом процесса mysqld .
    • Со значением 2 содержание буфера журнала записано в файл после того, как каждая транзакция передается, и файл системного журнала сбрасывается на диск приблизительно однажды в секунду. Ежесекундный сброс не составляет 100% гарантию, что сброс будет происходить каждую секунду, есть проблемы планирования. Поскольку сброс на диск происходит приблизительно однажды в секунду, Вы можете потерять до секунды транзакций при катастрофическом отказе операционной системы.
    • Частотой сброса журнала управляет innodb_flush_log_at_timeout, который позволяет Вам устанавливать частоту сброса журнала в N секунд (где N 1 ... 2700, по умолчанию 1). Однако, любой катастрофический отказ процесса mysqld может стереть до N секунд транзакций.
    • DDL и другие внутренние изменения InnoDB вызывают сброс журнала, независимый от innodb_flush_log_at_trx_commit.
    • Восстановление независимо от innodb_flush_log_at_trx_commit. Транзакции или применены полностью или стерты полностью.

    Для длительности и последовательности в установке репликации, которая использует InnoDB с транзакциями:

    • Если двоичное журналирование включено, установите sync_binlog=1.

    • Всегда установите innodb_flush_log_at_trx_commit=1.

    Много операционных систем и некоторые дисковые аппаратные средства дурачат работу потока. Они могут сказать mysqld, что сброс имел место, даже при том, что это не так. Тогда длительность транзакций не гарантируется даже с установкой 1, и в худшем случае отключение электричества может даже повредить данные InnoDB. Использование поддержанного батареей дискового кэша в дисковом контроллере SCSI или в самом диске делает работу более безопасной. Вы можете также попытаться использовать команду Unix hdparm, чтобы отключить кэширование диска или используйте некоторую другую команду, определенную для аппаратных средств.

  • innodb_flush_method

    Формат командной строки --innodb_flush_method=name
    Системная переменная Имя innodb_flush_method
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения (Unix) Тип string
    Значение по умолчанию fsync
    Допустимые значения fsync
    O_DSYNC
    littlesync
    nosync
    O_DIRECT
    O_DIRECT_NO_FSYNC
    Допустимые значения (Windows)Тип string
    Значение по умолчанию unbuffered
    Допустимые значения unbuffered
    normal

    Определяет метод, используемый, чтобы сбросить данные к файлам с данными и файлам системного журнала, которые могут затронуть пропускную способность ввода/вывода.

    В Unix-системах значение по умолчанию fsync. В Windows unbuffered.

    В MySQL 8.0 опции innodb_flush_method могут быть определены в цифровой форме.

    innodb_flush_method в Unix:

    • fsync или 0: InnoDB использует fsync(), чтобы сбросить данные и файлы системного журнала. fsync настройка по умолчанию.

    • O_DSYNC или 1: InnoDB использует O_SYNC, чтобы открыть и сбросить файлы системного журнала, и fsync(), чтобы сбросить файлы данных. InnoDB не использует O_DSYNC непосредственно, потому что были проблемы с этим на многих вариантах Unix.
    • littlesync или 2: Эта опция используется для тестирования собственной производительности и в настоящее время не поддерживается. Используйте на ваш собственный риск.
    • nosync или 3: Эта опция используется для тестирования собственной производительности и в настоящее время не поддерживается. Используйте на ваш собственный риск.
    • O_DIRECT или 4: InnoDB использует O_DIRECT (или directio() в Solaris), чтобы открыть файлы данных, и fsync(), чтобы сбросить данные и файлы системного журнала. Эта опция доступна на некоторых версиях GNU/Linux, FreeBSD и Solaris.
    • O_DIRECT_NO_FSYNC или 5: InnoDB использует O_DIRECT во время ввода/вывода, но пропускает fsync() позже. Эта установка является подходящей для некоторых типов файловых систем, но не других. Например, это не является подходящим для XFS. Если Вы не уверены, требует ли файловая система, которую Вы используете, fsync(), например, чтобы сохранить все метаданные о файле, надо использовать O_DIRECT.

    innodb_flush_method в Windows:

    • unbuffered или 0: InnoDB использует моделируемый асинхронный ввод/вывод и небуферизованный ввод/вывод.

    • normal или 1: InnoDB моделируемый асинхронный ввод/вывод и буферизованный ввод/вывод.

    То, как каждая настройка затрагивают работу, зависит от конфигурации аппаратных средств и рабочей нагрузки. Определите эффективность своей особой конфигурации, чтобы решить, которую установку использовать или сохранить настройку по умолчанию. Исследуйте Innodb_data_fsyncs , чтобы видеть общее количество fsync() для каждой установки. Соединение чтения и записи в Вашей рабочей нагрузке может затронуть, как установка работает. Например, на системе с контроллером RAID и поддержанным батареей кэшем O_DIRECT может помочь избежать двойной буферизации между буферным пулом InnoDB и кэшем файловой системы операционной системы. На некоторых системах, где данные и файлы системного журнала расположены на SAN, значении по умолчанию или O_DSYNC могло бы быть быстрее для нагруженной чтением рабочей нагрузки с главным образом запросами SELECT. Всегда проверяйте этот параметр с аппаратными средствами и рабочей нагрузкой, которые отражают Вашу производственную среду. Для общих советов о настройке ввода/вывода см. раздел 9.5.8.

  • innodb_flush_neighbors

    Формат командной строки --innodb_flush_neighbors
    Системная переменная Имя innodb_flush_neighbors
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип enumeration
    Значение по умолчанию 1
    Допустимые значения 0
    1
    2

    Определяет сброс страниц из буферного пула и другие грязные страницы в том же самом экстенте.

    • Значение по умолчанию 1 сбрасывает грязные страницы в том же самом экстенте из буферного пула.

    • Установка 0 выключает innodb_flush_neighbors и никакие другие грязные страницы из буферного пула не сбрасываются.
    • Установка 2 сбрасывает грязные страницы в том же самом экстенте из буферного пула.

    Когда табличные данные хранятся на традиционном устройстве хранения данных HDD, сброс such соседних страниц в одной работе уменьшает ввод/вывод (прежде всего для операций поиска) по сравнению со сбросом отдельных страниц в разное время. Для табличных данных, хранимых на SSD, время поиска не значимый фактор, и Вы можете выключить эту установку. Для общих советов о настройке ввода/вывода см. раздел 9.5.8.

  • innodb_flush_sync

    Формат командной строки --innodb_flush_sync=#
    Системная переменная Имя innodb_flush_sync
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию ON

    innodb_flush_sync включен по умолчанию, вызывает установку innodb_io_capacity , которая будет проигнорирована для взрывов деятельности ввода/вывода, которые происходят в контрольных точках. Чтобы придерживаться предела на фоновую деятельность ввода/вывода, определенного innodb_io_capacity , выключите innodb_flush_sync.

  • innodb_flushing_avg_loops

    Формат командной строки --innodb_flushing_avg_loops=#
    Системная переменная Имя innodb_flushing_avg_loops
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 30
    Минимум 1
    Максимум 1000

    Число итераций, для которых InnoDB сохраняет ранее расчетный образ состояния сброса, управляя, как быстро quickly адаптивный сброс отвечает на изменяющуюся нагрузку. Увеличение значения заставляет уровень операций сброса измениться гладко и постепенно, как рабочая нагрузка изменяется. Уменьшение значения заставляет адаптивный сброс корректироваться быстро к изменениям рабочей нагрузки, что может вызвать пики сброса, если увеличения и уменьшения рабочей нагрузки внезапны.

  • innodb_force_load_corrupted

    Формат командной строки --innodb_force_load_corrupted
    Системная переменная Имя innodb_force_load_corrupted
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип boolean
    Значение по умолчанию OFF

    Позволяет InnoDB загружать таблицы при запуске, которые отмечены как поврежденные. Используйте только во время поиска неисправностей, чтобы возвратить данные, которые иначе недоступны. Когда поиск неисправностей выполнен, выключите это и перезапустите сервер.

  • innodb_force_recovery

    Формат командной строки --innodb_force_recovery=#
    Системная переменная Имя innodb_force_recovery
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип integer
    Значение по умолчанию 0
    Минимум 0
    Максимум 6

    Режим восстановления катастрофического отказа, измененный в серьезных ситуациях с поиском неисправностей. Возможные значения от 0 до 6. Для смысла этих значений и важной информации о innodb_force_recovery см. раздел 16.20.2.

    Установите эту переменную в значение больше 0 в чрезвычайной ситуации, чтобы Вы могли запустить InnoDB и выведите свои таблицы в дамп. Как мера по безопасности, InnoDB запрещает INSERT, UPDATE или DELETE, когда innodb_force_recovery больше 0. Установка innodb_force_recovery в 4 или больше переводит InnoDB в режим только для чтения.

    Эти ограничения могут заставить такие команды управления репликацией, как --relay-log-info-repository=TABLE и --master-info-repository=TABLE терпеть неудачу с ошибкой сохранения информации в таблицах InnoDB.

  • innodb_ft_aux_table

    Формат командной строки --innodb_ft_aux_table=#
    Системная переменная Имя innodb_ft_aux_table
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип string

    Определяет полностью определенное имя таблицы, содержащей индекс FULLTEXT. Эта переменная предназначена в диагностических целях.

    После того, как Вы устанавливаете эту переменную в имя в формате db_name/table_name, таблицы INFORMATION_SCHEMA INNODB_FT_INDEX_TABLE , INNODB_FT_INDEX_CACHE, INNODB_FT_CONFIG , INNODB_FT_DELETED и INNODB_FT_BEING_DELETED покажет информацию о поисковом индексе для указанной таблицы.

  • innodb_ft_cache_size

    Формат командной строки --innodb_ft_cache_size=#
    Системная переменная Имя innodb_ft_cache_size
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип integer
    Значение по умолчанию 8000000
    Минимум 1600000
    Максимум 80000000

    Выделенная память в байтах для кэша FULLTEXT, который держит разобранный документ в памяти, создавая индекс FULLTEXT. Вставки и обновления сохранены на диск, когда предел размера innodb_ft_cache_size исчерпан. innodb_ft_cache_size определяет размер кэша на таблицу. Чтобы установить глобальный предел для всех таблиц см. innodb_ft_total_cache_size.

  • innodb_ft_enable_diag_print

    Формат командной строки --innodb_ft_enable_diag_print=#
    Системная переменная Имя innodb_ft_enable_diag_print
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию OFF

    Включить ли дополнительный диагностический вывод полнотекстового поиска. Эта опция прежде всего предназначена для усовершенствованной отладки FTS и не будет представлять интерес для большинства пользователей. Вывод напечатан в журнал ошибок и включает такую информацию, как:

    • Ход синхронизации индекса FTS (когда предел кэша FTS достигнут). Например:

      FTS SYNC for table test, deleted count: 100 size: 10000 bytes
      SYNC words: 100
      
    • Ход оптимизации FTS:
      FTS start optimize test
      FTS_OPTIMIZE: optimize "mysql"
      FTS_OPTIMIZE: processed "mysql"
      
    • Ход создания индекса FTS:
      Number of doc processed: 1000
      
    • Для запросов FTS дерево парсинга запроса, вес слова, время обработки запроса и использование памяти напечатано. Например:
      FTS Search Processing time: 1 secs: 100 millisec: row(s) 10000
      Full Search Memory: 245678 (bytes),  Row: 10000
      
  • innodb_ft_enable_stopword

    Формат командной строки --innodb_ft_enable_stopword=#
    Системная переменная Имя innodb_ft_enable_stopword
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию ON

    Определяет ряд стоп-слов, связанный с индексом InnoDB FULLTEXT, когда индекс создается. Если innodb_ft_user_stopword_table установлена, стоп-слова взяты от той таблицы. Иначе если innodb_ft_server_stopword_table установлена, стоп-слова взяты от той таблицы. Иначе используется встроенный набор стоп-слов по умолчанию.

  • innodb_ft_max_token_size

    Формат командной строки --innodb_ft_max_token_size=#
    Системная переменная Имя innodb_ft_max_token_size
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип integer
    Значение по умолчанию 84
    Минимум 10
    Максимум 84
    Допустимые значения Тип integer
    Значение по умолчанию 84
    Минимум 10
    Максимум 84

    Максимальная символьная длина слов, которые сохранены в индексе InnoDB FULLTEXT. Установка предела для этого значения уменьшает размер индекса, таким образом ускоряя запросы, опуская долгие ключевые слова или произвольные наборы символов, которые не являются реальными словами и вряд ли будут критериями поиска.

  • innodb_ft_min_token_size

    Формат командной строки --innodb_ft_min_token_size=#
    Системная переменная Имя innodb_ft_min_token_size
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип integer
    Значение по умолчанию 3
    Минимум 0
    Максимум 16

    Минимальная длина слов, которые сохранены в индексе InnoDB FULLTEXT. Увеличение этого значения уменьшает размер индекса, таким образом ускоряя запросы, опуская общее слово, которые вряд ли будут существенными в контексте поиска, такие как английские слова a и to. Для контента, использующего набор символов CJK (Chinese, Japanese, Korean), определяют значение 1.

  • innodb_ft_num_word_optimize

    Формат командной строки --innodb_ft_num_word_optimize=#
    Системная переменная Имя innodb_ft_num_word_optimize
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 2000

    Число слов, чтобы обработать во время каждого вызова OPTIMIZE TABLE для индекса InnoDB FULLTEXT. Поскольку большая вставка или обновление таблицы, содержащей полнотекстовый индекс может потребовать существенное обслуживание индекса, чтобы включить все изменения, Вы могли бы сделать серию OPTIMIZE TABLE , продолжающих работу друг друга.

  • innodb_ft_result_cache_limit

    Формат командной строки --innodb_ft_result_cache_limit=#
    Системная переменная Имя innodb_ft_result_cache_limit
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 2000000000
    Минимум 1000000
    Максимум 2**32-1

    InnoDB FULLTEXT search (FTS) запрашивает предел кэша результата (определенный в байтах) на запрос FTS или поток. Результаты запроса FTS обработаны в памяти. Используйте innodb_ft_result_cache_limit, чтобы устанавливать границу размера кэша результатов FTS, чтобы избежать чрезмерного потребления памяти в случае очень большого результата запроса FTS (миллионы или сотни миллионов строк, например). Память выделена как требуется, когда запрос FTS обработан. Если предел размера кэша результата достигнут, ошибка возвращена, указывая, что запрос превышает максимальную позволенную память.

    Максимальное значение innodb_ft_result_cache_limit для всех платформ 2**32-1. Bug #71554.

  • innodb_ft_server_stopword_table

    Формат командной строки --innodb_ft_server_stopword_table=db_name/table_name
    Системная переменная Имя innodb_ft_server_stopword_table
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип string
    Значение по умолчанию NULL

    Эта опция используется, чтобы определить Ваш собственный список стоп-слов FULLTEXT для всех таблицы. Сконфигурировать Ваш собственный список для определенной таблицы можно через innodb_ft_user_stopword_table.

    Установите innodb_ft_server_stopword_table в название таблицы, содержащей список стоп-слов, в формате db_name/table_name.

    Таблица должна существовать прежде, чем Вы сконфигурируете innodb_ft_server_stopword_table. innodb_ft_enable_stopword должен быть включен и innodb_ft_server_stopword_table должна быть сконфигурирована прежде, чем Вы создадите FULLTEXT.

    Таблица должна быть таблицей InnoDB с одним столбцом VARCHAR с именем value.

    Подробности в разделе 13.9.4.

  • innodb_ft_sort_pll_degree

    Формат командной строки --innodb_ft_sort_pll_degree=#
    Системная переменная Имя innodb_ft_sort_pll_degree
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип integer
    Значение по умолчанию 2
    Минимум 1
    Максимум 32

    Число потоков, чтобы параллельно индексировать и размечать текст в индексе FULLTEXT, при создании поискового индекса. См. innodb_sort_buffer_size.

  • innodb_ft_total_cache_size

    Формат командной строки --innodb_ft_total_cache_size=#
    Системная переменная Имя innodb_ft_total_cache_size
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип integer
    Значение по умолчанию 640000000
    Минимум 32000000
    Максимум 1600000000

    Полная выделенная память в байтах для кэша поискового индекса FULLTEXT для всех таблиц. Составление многочисленных таблиц, каждая с полнотекстовым поисковым индексом, может потреблять существенную часть доступной памяти. innodb_ft_total_cache_size определяет глобальный предел памяти для всего полнотекстового поиска, чтобы помочь избежать чрезмерного потребления памяти. Если глобальный предел достигнут вызвана принудительная синхронизация.

  • innodb_ft_user_stopword_table

    Формат командной строки --innodb_ft_user_stopword_table=db_name/table_name
    Системная переменная Имя innodb_ft_user_stopword_table
    Область действия Global, Session
    Динамическая Да
    Допустимые значения Тип string
    Значение по умолчанию NULL

    Эта опция используется, чтобы определить Ваш список стоп-слов FULLTEXT на определенной таблице. Сконфигурировать Ваш собственный список для всех таблиц можно с помощью innodb_ft_server_stopword_table.

    Установите innodb_ft_user_stopword_table в название таблицы, содержащей список стоп-слов, в формате db_name/table_name.

    Таблица должна существовать прежде, чем Вы сконфигурируете innodb_ft_user_stopword_table. innodb_ft_enable_stopword должен быть включен и innodb_ft_user_stopword_table должен быть сконфигурирован прежде, чем Вы создадите индекс FULLTEXT.

    Таблица должна быть таблицей InnoDB с одним столбцом VARCHAR с именем value.

    См. раздел 13.9.4.
  • innodb_io_capacity

    Формат командной строки --innodb_io_capacity=#
    Системная переменная Имя innodb_io_capacity
    Область действия Глобальная
    Динамическая Да
    Допустимые значения (32-bit platforms)Тип integer
    Значение по умолчанию 200
    Минимум 100
    Максимум 2**32-1
    Допустимые значения (64-bit platforms)Тип integer
    Значение по умолчанию 200
    Минимум 100
    Максимум 2**64-1

    innodb_io_capacity ставит верхний предел для деятельности ввода/вывода, выполненной фоновыми задачами InnoDB, например, сбросом страниц из буферного пула и слиянием данных из буфера изменений.

    innodb_io_capacity полный предел для всех экземпляров буферного пула. Когда грязные страницы сбрасываются, предел разделен одинаково среди буферных экземпляров.

    innodb_io_capacity должен быть установлен в приблизительно число операций ввода/вывода, которые система может выполнить в секунду. Идеально сохранить установку столь низкой, как возможно, но не настолько низкой, что фоновые действия отстают. Если значение слишком высоко, данные удалены из буферного пула и буфера вставок слишком быстро, чтобы кэшироваться и обеспечить существенную выгоду.

    Значение по умолчанию 200. Для занятых систем, способных к более высоким уровням ввода/вывода, Вы можете установить более высокое значение, чтобы помочь серверу обработать фоновую работу обслуживания, связанную с высоким показателем изменений строки.

    Вообще, Вы можете увеличить значение как функцию числа дисков, используемых для ввода/вывода. Например, Вы можете увеличить значение на системах, которые используют много дисков или диски (SSD).

    Настройка по умолчанию 200 вообще достаточна для SSD более низкого уровня. Для более высокого уровня bus-attached SSD считают более высокую установку, например 1000. Для систем с отдельными дисками на 5400 RPM или 7200 RPM Вы могли бы снизить значение до 100, которое представляет предполагаемую пропорцию операций в секунду ввода/вывода (IOPS), доступную дисководам старшего поколения, которые могли выполнить приблизительно 100 IOPS.

    Хотя Вы можете определить очень высокое значение, например, миллион, практически у таких больших значений мало пользы. Вообще, значение 20000 или выше не рекомендуется, если Вы не доказали, что меньшие значения недостаточны для Вашей рабочей нагрузки.

    Рассмотрите рабочую нагрузку, настраивая innodb_io_capacity. Системы с большими записями, вероятно, извлекут выгоду из более высокой установки. Более низкая установка может быть достаточной для систем с маленьким уровнем записи.

    Вы можете установить innodb_io_capacity в 100 или больше до максимума, определенного innodb_io_capacity_max. innodb_io_capacity может быть установлен в файле опции MySQL (my.cnf или my.ini) или изменен динамически использованием SET GLOBAL, что требует привилегии SUPER.

    innodb_flush_sync вызывает установку innodb_io_capacity, которая будет проигнорирована во время взрывов деятельности ввода/вывода, которые происходят в контрольных точках. innodb_flush_sync включен по умолчанию.

    См. раздел 16.6.7 .

  • innodb_io_capacity_max

    Формат командной строки --innodb_io_capacity_max=#
    Системная переменная Имя innodb_io_capacity_max
    Область действия Глобальная
    Динамическая Да
    Допустимые значения (32-bit platforms)Тип integer
    Значение по умолчанию see description
    Минимум 100
    Максимум 2**32-1
    Допустимые значения (Unix, 64-bit platforms)Тип integer
    Значение по умолчанию См. описание
    Минимум 100
    Максимум 2**64-1
    Допустимые значения (Windows, 64-bit platforms)Тип integer
    Значение по умолчанию См. описание
    Минимум 100
    Максимум 2**32-1

    Если сброс отстает, InnoDB может начать сбрасывать более настойчиво чем предел, наложенный innodb_io_capacity. innodb_io_capacity_max определяет верхний предел ввода/вывода в таких ситуациях.

    innodb_io_capacity_max это полный предел для всех буферных экземпляров.

    Если Вы определяете innodb_io_capacity при запуске, но не определяете значение для innodb_io_capacity_max, innodb_io_capacity_max по умолчанию дважды значение innodb_io_capacity, но минимум 2000.

    Конфигурируя innodb_io_capacity_max, дважды innodb_io_capacity часто хорошая начальная точка. Значение по умолчанию 2000 предназначено для рабочих нагрузок, которые используют диск SSD или больше, чем один обычный диск. Установка 2000, вероятно, слишком высока для рабочих нагрузок, которые не используют SSD или много дисков, и могли позволить слишком большой сброс. Для единственного диска рекомендуется установка между 200 и 400. Для bus-attached SSD ставьте более высокую установку, около 2500. Как с innodb_io_capacity, сохраните установку столь низкой, как можно, но не настолько низкой, чтобы InnoDB не может достаточно масштабироваться вне предела innodb_io_capacity , если это надо.

    Рассмотрите рабочую нагрузку, настраивая innodb_io_capacity_max. Системы с большой записью могут извлечь выгоду из более высокой установки. Более низкая установка может быть достаточной для систем с маленьким объемом записей.

    innodb_io_capacity_max не может быть установлен в значение ниже, чем innodb_io_capacity .

    Установка innodb_io_capacity_max в DEFAULT через SET (SET GLOBAL innodb_io_capacity_max=DEFAULT) ставит innodb_io_capacity_max к максимальному значению.

    См. раздел 16.6.3.7 .

  • innodb_limit_optimistic_insert_debug

    Формат командной строки --innodb_limit_optimistic_insert_debug=#
    Системная переменная Имя innodb_limit_optimistic_insert_debug
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 0
    Минимум 0
    Максимум 2**32-1

    Ограничивает число записей на страницу B-tree. Значение по умолчанию 0 указывает, что никакой предел не наложен. Эта опция доступна только если поддержка отладки собрана с использованием WITH_DEBUG в CMake.

  • innodb_lock_wait_timeout

    Формат командной строки --innodb_lock_wait_timeout=#
    Системная переменная Имя innodb_lock_wait_timeout
    Область действия Global, Session
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 50
    Минимум 1
    Максимум 1073741824

    Отрезок времени в секундах, который транзакция ждет a блокировки строки перед отказом. Значение по умолчанию составляет 50 секунд. Транзакция, которая пытается получить доступ к строке, которая заблокирована другой транзакция ждет самое большее это число секунд для доступ к строке прежде, чем выпустить следующую ошибку:

    ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
    

    Когда блокировка ждет и тайм-аут происходит, текущий запрос откатывается (не вся транзакция!). Чтобы вся транзакция откатывалась до прежнего уровня, запускайте сервер с --innodb_rollback_on_timeout. См. раздел 16.20.4.

    Вы могли бы уменьшить это значение для очень интерактивных приложений или систем OLTP, чтобы вывести на экран пользовательскую обратную связь быстро или поместить обновление в очередь для того, чтобы обработать позже. Вы могли бы увеличить это значение для продолжительных операций, таких как шаг преобразования в хранилище данных, которые ждут большой вставки или операций обновления, чтобы закончиться.

    innodb_lock_wait_timeout относится только к строковой блокировке. Табличная блокировка MySQL не происходит внутри InnoDB и этот тайм-аут не относится к ожиданию табличных блокировок.

    Значение тайм-аута не относится к тупикам, когда innodb_deadlock_detect включен (значение по умолчанию) потому, что InnoDB обнаруживает тупики и откатывает одну из заведенных в тупик транзакций. Когда innodb_deadlock_detect включен, InnoDB полагается на innodb_lock_wait_timeout для операционной отмены, когда тупик происходит.

    innodb_lock_wait_timeout может быть установлен во время выполнения с помощью SET GLOBAL или SET SESSION. Изменение GLOBAL требует привилегии SUPER и влияет на работу всех клиентов, которые впоследствии соединяются. Любой клиент может изменить SESSION для innodb_lock_wait_timeout, который затрагивает только того клиента.

  • innodb_log_buffer_size

    Формат командной строки --innodb_log_buffer_size=#
    Системная переменная Имя innodb_log_buffer_size
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип integer
    Значение по умолчанию 16777216
    Минимум 1048576
    Максимум 4294967295
    Допустимые значения Тип integer
    Значение по умолчанию 1048576
    Минимум 1048576
    Максимум 4294967295

    Размер в байтах буфера для записи на диск файлов системного журнала. Значение по умолчанию составляет 16 МБ. Большой буфер журнала позволяет большим транзакциям работать без потребности писать журнал на диск прежде, чем транзакция transactions завершится. Таким образом, если у Вас есть транзакции, которые обновляют, вставляют или удаляют много строк, увеличение журнала сохраняет дисковый ввод/вывод. См. раздел 9.5.8.

  • innodb_log_checksums

    Формат командной строки --innodb_log_checksums=#
    Системная переменная Имя innodb_log_checksums
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию ON

    Включает или отключает контрольные суммы для страницы журнала redo. innodb_log_checksums=ON включает алгоритм CRC-32C контрольной суммы для страницы журнала redo. Когда innodb_log_checksums отключен, содержание области контрольной суммы страницы журнала проигнорировано.

    Контрольные суммы на заголовке страницы журнала и странице контрольной точки журнала никогда не отключаются.

  • innodb_log_compressed_pages

    Формат командной строки --innodb_log_compressed_pages=#
    Системная переменная Имя innodb_log_compressed_pages
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип boolean
    Значение по умолчанию ON

    Определяет, записаны ли образы пересжатых страниц в журнал redo. Пересжатие может произойти, когда изменения произведены в сжатых данных.

    innodb_log_compressed_pages включен по умолчанию, чтобы предотвратить повреждение, которое могло произойти, если иная версия алгоритма сжатия zlib используется во время восстановления. Если Вы уверены, что версия zlib не будет изменяться, Вы можете отключить innodb_log_compressed_pages, чтобы уменьшить журнал для рабочих нагрузок, которые изменяют сжатые данные.

    Измерить эффект включения или отключения innodb_log_compressed_pages можно, сравнивая генерацию журнала redo для обеих настроек при той же самой рабочей нагрузке. Это включает наблюдение за Log sequence number (LSN) в разделе LOG вывода SHOW ENGINE INNODB STATUS или мониторинг Innodb_os_log_written для числа байтов, написанных в файлы журнала redo.

  • innodb_log_file_size

    Формат командной строки --innodb_log_file_size=#
    Системная переменная Имя innodb_log_file_size
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип integer
    Значение по умолчанию 50331648
    Минимум 4194304
    Максимум 512GB / innodb_log_files_in_group
    Допустимые значения Тип integer
    Значение по умолчанию 5242880
    Минимум 1048576
    Максимум 4294967295

    Размер в байтах каждого файла системного журнала в группе журнала. Объединенный размер файлов системного журнала (innodb_log_file_size* innodb_log_files_in_group) не может превысить максимальное значение, которое является немного меньше 512 ГБ. Пара файлов по 255 GB , например, позволила бы Вам приближаться к пределу, но не превышать его. Значение по умолчанию составляет 48 МБ. Заметные значения колеблются от 4 МБ до 1/N размера буферного пула, где N число файлов системного журнала в группе. Чем больше значение, тем меньше деятельности потока контрольной точки необходимо в буферном пуле, сохраняя дисковый ввод/вывод. Большие файлы системного журнала также делают восстановление катастрофического отказа медленнее, хотя усовершенствования работы восстановления в MySQL 5.5 и выше делают размер файла системного журнала меньше.

    Минимум innodb_log_file_size увеличен с 1MB до 4MB в MySQL 8.0.

  • innodb_log_files_in_group

    Формат командной строки --innodb_log_files_in_group=#
    Системная переменная Имя innodb_log_files_in_group
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип integer
    Значение по умолчанию 2
    Минимум 2
    Максимум 100

    Число файлов системного журнала в группе журнала. InnoDB пишет файлы круговым способом. Значение по умолчанию (и рекомендуемое) значение 2. Местоположение этих файлов определено innodb_log_group_home_dir. Объединенный размер файлов системного журнала ( innodb_log_file_size*innodb_log_files_in_group) может быть до 512 ГБ.

  • innodb_log_group_home_dir

    Формат командной строки --innodb_log_group_home_dir=dir_name
    Системная переменная Имя innodb_log_group_home_dir
    Область действия Глобальная
    Динамическая Нет
    Допустимые значения Тип directory name

    Путь к каталогу с файлами журнала redo, число которых определено innodb_log_files_in_group. Если Вы не определяете переменные журнала, значение по умолчанию должно создать два файла ib_logfile0 и ib_logfile1 в каталоге данных MySQL. Их размер задан в innodb_log_file_size.

  • innodb_log_write_ahead_size

    Формат командной строки --innodb_log_write_ahead_size=#
    Системная переменная Имя innodb_log_write_ahead_size
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 8192
    Минимум 512 (log file block size)
    Максимум Equal to innodb_page_size

    Размер блока для журнала redo в байтах. Чтобы избежать avoid чтения на записи, установите innodb_log_write_ahead_size, чтобы соответствовать размеру блока кэша файловой системы. Чтение на записи происходит, когда блоки журнала не полностью кэшируются файловой системой из-за несоответствия написанным размером блока и размером блока кэша файловой системы.

    Минимальное значение размер блока файла системного журнала (512). Предзапись не происходит, когда минимальное значение определено. Максимальное значение равно innodb_page_size. Если Вы определяете значение для innodb_log_write_ahead_size больше innodb_page_size , innodb_log_write_ahead_size усечено к innodb_page_size .

    Установка innodb_log_write_ahead_size слишком низко относительно операционной системы или размера блока кэша файловой системы приведет к чтению на записи. Установка значения слишком высоким может оказать небольшое влияние на производительность fsync для файла системного журнала из-за нескольких блоков, написанных сразу.

  • innodb_lru_scan_depth

    Формат командной строки --innodb_lru_scan_depth=#
    Системная переменная Имя innodb_lru_scan_depth
    Область действия Глобальная
    Динамическая Да
    Допустимые значения (32-bit platforms)Тип integer
    Значение по умолчанию 1024
    Минимум 100
    Максимум 2**32-1
    Допустимые значения (64-bit platforms)Тип integer
    Значение по умолчанию 1024
    Минимум 100
    Максимум 2**64-1

    Параметр, который влияет на алгоритмы и эвристику для работы the сброса буферного пула. Прежде всего интересен для исполнительных экспертов, настраивающих рабочие нагрузки. Это определяет для экземпляра буферного пула как далеко вниз поток уборщика страницы просматривает список LRU, ища грязные страницы, чтобы сбросить. Это фоновая работа, выполненная раз в секунду.

    Установка, меньшая чем значение по умолчанию, является вообще подходящей для большинства рабочих нагрузок. Значение, которое намного выше, чем необходимо, может воздействовать на работу. Рассмотрите увеличение значения только если у Вас есть запас ввода/вывода при типичной рабочей нагрузке. Наоборот, если рабочая нагрузка насыщает Ваш ввод/вывод, уменьшите значение, особенно в случае большого буферного пула.

    Настраивая innodb_lru_scan_depth, начните с низкого значения и сконфигурируйте установку с целью редкого наблюдения нулевых свободных страниц. Кроме того, рассмотрите корректировку innodb_lru_scan_depth, изменяя число буферных экземпляров. innodb_lru_scan_depth* innodb_buffer_pool_instances определяет объем работы, выполненный потоком уборщика страницы каждую секунду.

  • innodb_max_dirty_pages_pct

    Формат командной строки --innodb_max_dirty_pages_pct=#
    Системная переменная Имя innodb_max_dirty_pages_pct
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип numeric
    Значение по умолчанию 75
    Минимум 0
    Максимум 99.99
    Допустимые значения Тип numeric
    Значение по умолчанию 90
    Минимум 0
    Максимум 100

    InnoDB пытается сбросить данные из буферного пула, чтобы процент грязных страниц не превысил это значение. Значение по умолчанию 75.

    innodb_max_dirty_pages_pct устанавливает цель для сброса. Это не затрагивает уровень сброса. Для информации об управлении уровнем сброса см. раздел 16.6.3.6.

    Подробности в разделе 16.6.3.7.

  • innodb_max_dirty_pages_pct_lwm

    Формат командной строки --innodb_max_dirty_pages_pct_lwm=#
    Системная переменная Имя innodb_max_dirty_pages_pct_lwm
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип numeric
    Значение по умолчанию 0
    Минимум 0
    Максимум 99.99

    Нижний процент грязных страниц , где предварительный сброс управляет коэффициентом грязных страниц. Значение по умолчанию 0 отключает предварительный сброс полностью. Для дополнительной информации об этой переменной см. раздел 16.6.3.7.

  • innodb_max_purge_lag

    Формат командной строки --innodb_max_purge_lag=#
    Системная переменная Имя innodb_max_purge_lag
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 0
    Минимум 0
    Максимум 4294967295

    Эта переменная управляет, как задержатся INSERT, UPDATE и DELETE, когда чистка отстает (см. раздел 16.3). Значение по умолчанию 0 (никаких задержек).

    Система транзакций поддерживает список транзакций, которые имеют индексные записи, помеченные для удаления, UPDATE или DELETE. Длина этого списка представляет purge_lag. Когда purge_lag превышает innodb_max_purge_lag , каждый запрос INSERT, UPDATE и DELETE задержится.

    Чтобы предотвратить чрезмерные задержки, где purge_lag становится огромным, Вы можете поправить количество задержки, устанавливая innodb_max_purge_lag_delay. Задержка вычислена в начале пакета чистки.

    Типичная установка для проблематичной рабочей нагрузки могла бы быть 1 миллионом, предполагая, что транзакции являются маленькими, только 100 байтов в размере, и допустимо иметь 100 МБ неочищенных строк таблиц.

    Значение задержки выведено на экран как длина списка истории в разделе TRANSACTIONS InnoDB Monitor. Например, если вывод включает следующие строки, значение задержки 20:

    ------------
    TRANSACTIONS
    ------------
    Trx id counter 0 290328385
    Purge done for trx's n:o < 0 290315608 undo n:o < 0 17
    History list length 20
    
  • innodb_max_purge_lag_delay

    Формат командной строки --innodb_max_purge_lag_delay=#
    Системная переменная Имя innodb_max_purge_lag_delay
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 0
    Минимум 0

    Определяет максимальную задержку в миллисекундах для задержки, наложенной innodb_max_purge_lag . Любое ненулевое значение представляет верхний предел времени задержки, вычисленном от формулы, основанной на значении innodb_max_purge_lag. Значение по умолчанию 0 значит, что нет никакого верхнего предела, наложенного на интервал задержки.

  • innodb_max_undo_log_size

    Формат командной строки --innodb_max_undo_log_size=#
    Системная переменная Имя innodb_max_undo_log_size
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 1073741824
    Минимум 10485760
    Максимум 2**64-1

    innodb_max_undo_log_size определяет пороговый размер для табличных пространств отмены. Если табличное пространство отмены превышает порог, оно может быть отмечено для усечения, когда innodb_undo_log_truncate включен. Значение по умолчанию 1024 MiB (1073741824 байт).

    См. раздел 16.7.8.

  • innodb_merge_threshold_set_all_debug

    Формат командной строки --innodb_merge_threshold_set_all_debug=#
    Системная переменная Имя innodb_merge_threshold_set_all_debug
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип integer
    Значение по умолчанию 50
    Минимум 1
    Максимум 50

    Переопределяет текущее значение MERGE_THRESHOLD указанным значением для всех индексов, которые в настоящее время находятся в кэше словаря. Эта опция доступна только, если поддержка отладки собрана с использованием WITH_DEBUG в CMake. См. раздел 16.6.11.

  • innodb_monitor_disable

    Формат командной строки --innodb_monitor_disable=[counter|module|pattern|all]
    Системная переменная Имя innodb_monitor_disable
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип string

    Выключает один или более счетчиков в таблице INFORMATION_SCHEMA.INNODB_METRICS. См. раздел 22.30.16.

    innodb_monitor_disable='latch' отключает набор статистики для SHOW ENGINE INNODB MUTEX. См. раздел 14.7.5.15.

  • innodb_monitor_enable

    Формат командной строки --innodb_monitor_enable=[counter|module|pattern|all]
    Системная переменная Имя innodb_monitor_enable
    Область действия Глобальная
    Динамическая Да
    Допустимые значения Тип string

    Включает один или более счетчиков в таблице INFORMATION_SCHEMA.INNODB_METRICS. См. раздел 22.30.16.

    innodb_monitor_enable='latch' включает набору статистики для SHOW ENGINE INNODB MUTEX. См. раздел 14.7.5.15.

  • innodb_monitor_reset

    Формат командной строки --innodb_monitor_reset=[counter|module|pattern|all]
    Системная переменная Имя