Вопрос

При выполнении инструкции ALTER TABLE в MySQL вся таблица блокируется на чтение на время выполнения инструкции.Если это большая таблица, это означает, что операторы вставки или обновления могут быть заблокированы на очень долгое время.Есть ли способ выполнить «горячее изменение», например добавить столбец таким образом, чтобы таблица могла обновляться на протяжении всего процесса?

В основном меня интересует решение для MySQL, но меня интересуют и другие СУБД, если MySQL не сможет этого сделать.

Чтобы уточнить, моя цель — просто избежать простоя, когда новая функция, требующая дополнительного столбца таблицы, будет запущена в производство.Любая схема базы данных воля меняются со временем, это просто факт жизни.Я не понимаю, почему мы должны признать, что эти изменения неизбежно приведут к простоям;это просто слабо.

Это было полезно?

Решение

Единственный другой вариант — сделать вручную то, что в любом случае делают многие системы РСУБД...
- Создать новую таблицу

Затем вы можете скопировать содержимое старой таблицы по частям за раз.Всегда будьте осторожны с любыми INSERT/UPDATE/DELETE в исходной таблице.(Можно управлять с помощью триггера.Хоть это и приведет к замедлению, но это не блокировка...)

После завершения измените имя исходной таблицы, а затем измените имя новой таблицы.Желательно в транзакции.

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

РЕДАКТИРОВАТЬ:

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

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

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

Другие советы

Percona создает инструмент под названием pt-online-схема-изменение что позволяет это сделать.

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

Это похоже на метод, предложенный Демсом выше, но происходит автоматически.

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

Бывший:

pt-online-schema-change --alter "ADD COLUMN c1 INT" D=db,t=numbers_are_friends

Этот вопрос с 2009 года. Теперь MySQL предлагает решение:

онлайн DDL

  

Функция, которая улучшает производительность, параллелизм и доступность   таблиц InnoDB во время операций DDL (прежде всего ALTER TABLE). Увидеть   Раздел 14.11, & # 8220; InnoDB и Online DDL & # 8221; для деталей.

     

Детали могут различаться в зависимости от типа операции. В некоторых случаях,   таблица может быть изменена одновременно, пока ALTER TABLE находится в   прогресс. Операция может быть выполнена без выполнения   копирование таблицы или использование специально оптимизированного типа копирования таблицы. Космос   использование контролируется innodb_online_alter_log_max_size   опция конфигурации.

Он позволяет настроить баланс между производительностью и параллелизмом во время операции DDL, выбрав, следует ли полностью блокировать доступ к таблице (условие LOCK = EXCLUSIVE), разрешать запросы, но не DML (предложение LOCK = SHARED), или разрешать полное запрос и доступ DML к таблице (предложение LOCK = NONE). Когда вы опускаете предложение LOCK или задаете LOCK = DEFAULT, MySQL разрешает как можно больше параллелизма в зависимости от типа операции.

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

см. Справочное руководство по MySQL 5.6 - > ; InnoDB и Online DDL для получения дополнительной информации.

Похоже, что онлайн DDL также доступен в MariaDB

  

Кроме того, вы можете использовать ALTER ONLINE TABLE, чтобы убедиться, что ваш ALTER   TABLE не блокирует параллельные операции (не блокирует). это   эквивалентно LOCK = NONE.

КБ MariaDB об ALTER TABLE

См. онлайн-инструмент для изменения схемы Facebook.

http://www.facebook.com/notes / MySQL-на-facebook / онлайн-схема замены-в-MySQL / 430801045932

Не для слабонервных; но это сделает работу.

Я рекомендую Postgres, если это вариант.При использовании postgres простои практически отсутствуют при выполнении следующих процедур:

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

Я написал этот немного назад, возможно, это сможет пролить больше внимания на другие достоинства.

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

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

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

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

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

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

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

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

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

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

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

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

Это настолько масштабное изменение, что я сомневаюсь, что какая-либо СУБД его поддержит.Возможность делать это с данными в таблице считается преимуществом.

Временное решение ...

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

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

Когда вы можете получить время простоя, вы можете изменить исходную таблицу, изменить запросы DML и удалить новую таблицу, созданную ранее

Иначе, вы можете выбрать метод кластеризации, репликации, инструмент pt-online-schema из percona

Используя плагин Innodb, операторы ALTER TABLE, которые только добавляют или отбрасывают вторичные индексы, могут быть выполнены " быстро " ;, т. е. без перестройки таблицы.

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

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

Я бы рекомендовал один из двух подходов:

  1. Создавайте таблицы базы данных с учетом возможных изменений.Например, я работал с системами управления контентом, которые регулярно меняют поля данных в контенте.Вместо построения физической структуры базы данных, соответствующей первоначальным требованиям к полям CMS, гораздо лучше создать гибкую структуру.В этом случае используется текстовое поле большого двоичного объекта (например, varchar(max)) для хранения гибких данных XML.Это делает структурные изменения гораздо менее частыми.Структурные изменения могут быть дорогостоящими, поэтому и здесь есть выгода от затрат.

  2. Иметь время на обслуживание системы.Либо система отключается во время изменений (ежемесячно и т. д.), а изменения планируются на наименее загруженное время суток (например, с 3 до 5 утра).Изменения вносятся до развертывания производства, поэтому у вас будет точная оценка времени простоя в фиксированном окне.

2а.Имейте резервные серверы, чтобы в случае простоя системы весь сайт не отключался.Это позволит вам «выпускать» обновления в шахматном порядке, не отключая весь сайт.

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

Если кто-то все еще читает это или собирается сюда прийти, это большое преимущество использования системы баз данных NoSQL, такой как mongodb. У меня была та же проблема, связанная с изменением таблицы для добавления столбцов для дополнительных функций или индексов для большой таблицы с миллионами строк и высокой записью. Это приведет к блокировке в течение очень долгого времени, так что выполнение этого в базе данных LIVE разочаровывает наших пользователей. На маленьких столах вы можете сойти с рук.

Я ненавижу тот факт, что мы должны & разрабатывать наши таблицы, чтобы не изменять их " ;. Я просто не думаю, что это работает в современном мире веб-сайтов. Вы не можете предсказать, как люди будут использовать ваше программное обеспечение, поэтому вы быстро меняете ситуацию, основываясь на отзывах пользователей. С mongodb вы можете добавить & Quot; columns & Quot; по желанию без простоя. Вы на самом деле даже не добавляете их, вы просто вставляете данные с новыми столбцами, и это происходит автоматически.

Стоит проверить: www.mongodb.com

В общем случае ответ будет & "Нет &". Вы изменяете структуру таблицы, которая потенциально потребует много обновлений & Quot; и я определенно согласен с этим. Если вы собираетесь делать это часто, я предложу альтернативу & Quot; dummy & Quot; столбцы - используйте VIEW вместо таблиц для SELECT данных. IIRC, изменение определения представления является относительно легким, и перенаправление через представление выполняется при компиляции плана запроса. Сложность заключается в том, что вам придется добавить столбец в новую таблицу и создать представление JOIN в столбце.

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

Просто мысль.

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

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

Хорошей новостью является то, что с момента выпуска MySQL 5.6 ограничение было в основном поднятый , и теперь вы можете наслаждаться настоящей мощью БД MYSQL.

Как уже упоминал SeanDowney, pt-online-schema-change - один из лучших инструментов для выполнения того, что вы описали в этом вопросе. Недавно я сделал много изменений схемы на живой БД, и все прошло довольно хорошо. Подробнее об этом можно прочитать в моем блоге здесь: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/ .

Обязательно попробуйте pt-online-schema-change. Я использовал этот инструмент для миграции на AWS RDS с несколькими ведомыми устройствами, и он мне очень помог. Я написал подробное сообщение в блоге о том, как сделать то, что может быть полезно для вас

Блог: http://mrafayaleem.com / 2016/02/08 / Live-Mysql-схемы-изменения-с-Percona /

Пустые столбцы - хорошая идея, если вы можете предсказать их тип (и сделать их обнуляемыми). Проверьте, как ваш механизм хранения обрабатывает нули.

MyISAM заблокирует все, если вы случайно упомянете имя таблицы, по телефону, в аэропорту. Это просто делает это ...

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

TokuDB может добавлять / удалять столбцы и добавлять индексы " hot " таблица полностью доступна на протяжении всего процесса. Это доступно через www.tokutek.com

Не совсем.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top