ALTER TABLE без блокировки стола?

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

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

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

Ответ 1

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

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

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

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

EDIT:

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

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

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

Ответ 2

Percona делает инструмент под названием pt-online-schema-change, который позволяет это сделать.

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

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

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

Пример:

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

Ответ 4

Я рекомендую Postgres, если это опция. С postgres практически нет простоя со следующими процедурами:

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

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

Ответ 5

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

онлайн DDL

Функция, улучшающая производительность, concurrency и доступность таблиц InnoDB во время операций DDL (в основном ALTER TABLE). Видеть Раздел 14.11, "InnoDB и Online DDL" для деталей.

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

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

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

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

Кажется, что онлайн-DDL также доступен в MariaDB

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

MariaDB KB об ALTER TABLE

Ответ 6

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

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

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

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

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

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

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

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

Ответ 7

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

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

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

Ответ 8

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

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

Ответ 9

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

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

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

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

Кроме того, вы можете пойти для метода кластеризации, репликации, инструмента pt-online-schema из percona

Ответ 10

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

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

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

Ответ 11

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

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

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

Ответ 12

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

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

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

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

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

Ответ 13

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

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

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

Ответ 14

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

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

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

Ответ 15

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

Ответ 16

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

Блог: http://mrafayaleem.com/2016/02/08/live-mysql-schema-changes-with-percona/

Ответ 17

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

MyISAM будет блокировать все, если вы даже укажете имя таблицы по прошествии, по телефону, в аэропорту. Он просто делает это...

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

Ответ 18

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

Ответ 19

Не совсем.

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

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