При выполнении оператора ALTER TABLE в MySQL вся таблица блокируется для чтения (разрешает одновременное чтение, но запрещает одновременную запись) на время выполнения оператора. Если это большая таблица, инструкции INSERT или UPDATE могут быть заблокированы на очень долгое время. Есть ли способ выполнить «горячее изменение», например, добавить столбец таким образом, чтобы таблица оставалась обновляемой на протяжении всего процесса?
В основном меня интересует решение для MySQL, но мне были бы интересны другие СУБД, если MySQL не может этого сделать.
Чтобы уточнить, моя цель - просто избежать простоев, когда новая функция, для которой требуется дополнительный столбец таблицы, отправляется в производство. Любая схема базы данных со временем будет меняться, это просто факт жизни. Я не понимаю, почему мы должны признать, что эти изменения неизбежно приводят к простоям; это просто слабо.
источник
Ответы:
Единственный другой вариант - сделать вручную то, что и так делают многие системы СУБД ...
- Создать новую таблицу
Затем вы можете копировать содержимое старой таблицы по фрагменту за раз. При этом всегда будьте осторожны с любыми INSERT / UPDATE / DELETE в исходной таблице. (Можно управлять с помощью триггера. Хотя это приведет к замедлению, это не блокировка ...)
По завершении измените имя исходной таблицы, а затем измените имя новой таблицы. Желательно в сделке.
После завершения перекомпилируйте все хранимые процедуры и т. Д., Которые используют эту таблицу. Планы выполнения, скорее всего, больше не будут действительны.
РЕДАКТИРОВАТЬ:
Были сделаны некоторые комментарии по поводу того, что это ограничение немного скудно. Так что я подумал, что взгляну на это с новой точки зрения, чтобы показать, почему это так ...
источник
Percona создает инструмент под названием pt-online-schema-change, который позволяет это сделать.
По сути, он делает копию таблицы и изменяет новую таблицу. Чтобы синхронизировать новую таблицу с исходной, она использует триггеры для обновления. Это позволяет получить доступ к исходной таблице, пока новая таблица готовится в фоновом режиме.
Это похоже на метод, предложенный Демсом выше, но выполняется автоматически.
Некоторые из их инструментов требуют обучения, а именно подключения к базе данных, но как только вы это сделаете, они станут отличными инструментами.
Пример:
источник
Этот вопрос от 2009 года. Теперь MySQL предлагает решение:
Онлайн DDL (язык определения данных)
Он позволяет вам регулировать баланс между производительностью и параллелизмом во время операции DDL, выбирая, следует ли полностью блокировать доступ к таблице (предложение LOCK = EXCLUSIVE), разрешать запросы, но не DML (предложение LOCK = SHARED), или разрешать полный запрос и DML доступ к таблице (предложение LOCK = NONE). Когда вы опускаете предложение LOCK или указываете LOCK = DEFAULT, MySQL допускает максимально возможный параллелизм в зависимости от типа операции.
Выполнение изменений на месте, где это возможно, вместо создания новой копии таблицы, позволяет избежать временного увеличения использования дискового пространства и накладных расходов ввода-вывода, связанных с копированием таблицы и реконструкцией вторичных индексов.
см. Справочное руководство MySQL 5.6 -> InnoDB и Online DDL для получения дополнительной информации.
Кажется, что онлайн-DDL также доступен в MariaDB
КБ MariaDB об ALTER TABLE
источник
См. Онлайн-инструмент изменения схемы Facebook.
http://www.facebook.com/notes/mysql-at-facebook/online-schema-change-for-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 выполнялась во время нормальной работы приложения, если вы не готовы ждать или не изменяете крошечные таблицы.
источник
Я бы порекомендовал один из двух подходов:
Создавайте таблицы базы данных с учетом возможных изменений. Например, я работал с системами управления контентом, которые регулярно меняют поля данных в контенте. Вместо того, чтобы строить физическую структуру базы данных в соответствии с начальными требованиями к полям CMS, гораздо лучше создать гибкую структуру. В этом случае используется текстовое поле большого двоичного объекта (например, varchar (max)) для хранения гибких данных XML. Это значительно снижает частоту структурных изменений. Структурные изменения могут быть дорогостоящими, поэтому здесь тоже есть выгода.
Имейте время на обслуживание системы. Либо система отключается во время изменений (ежемесячно и т. Д.), И изменения планируются на наименее загруженное время дня (например, 3-5 утра). Изменения производятся до развертывания производственной среды, поэтому вы будете иметь хорошую фиксированную оценку времени простоя.
2а. Иметь резервные серверы, чтобы во время простоя системы не выходил из строя весь сайт. Это позволит вам «выкатывать» обновления в шахматном порядке без остановки всего сайта.
Варианты 2 и 2а могут оказаться невозможными; они, как правило, предназначены только для крупных сайтов / операций. Однако это допустимые варианты, и я лично использовал все варианты, представленные здесь.
источник
Если кто-то все еще читает это или приходит сюда, это большое преимущество использования системы баз данных NoSQL, такой как mongodb. У меня была такая же проблема, связанная с изменением таблицы для добавления столбцов для дополнительных функций или индексов в большой таблице с миллионами строк и большим количеством записей. Это привело бы к блокировке на очень долгое время, поэтому выполнение этой операции в базе данных LIVE расстроило бы наших пользователей. На небольших столах это может сойти с рук.
Я ненавижу тот факт, что мы должны «проектировать наши таблицы, чтобы не изменять их». Я просто не думаю, что это работает в современном мире веб-сайтов. Вы не можете предсказать, как люди будут использовать ваше программное обеспечение, поэтому вы быстро меняете вещи на основе отзывов пользователей. С mongodb вы можете добавлять «столбцы» по желанию без простоев. Вы даже не добавляете их, вы просто вставляете данные с новыми столбцами, и он делает это автоматически.
Стоит проверить: www.mongodb.com
источник
В общем, ответ будет «Нет». Вы меняете структуру таблицы, что потенциально потребует большого количества обновлений », и я определенно согласен с этим. Если вы ожидаете, что будете делать это часто, я предложу альтернативу« фиктивным »столбцам -
VIEW
вместо этого используйте s таблиц дляSELECT
данных. IIRC, изменение определения представления является относительно легким, и косвенное обращение к представлению выполняется при компиляции плана запроса. Расходы состоят в том, что вам придется добавить столбец в новую таблицу и сделать посмотретьJOIN
в колонке.Конечно, это работает только в том случае, если вы можете использовать внешние ключи для выполнения каскадных удалений и прочего. Другой бонус заключается в том, что вы можете создать новую таблицу, содержащую комбинацию данных, и указать на нее точку зрения, не мешая использованию клиента.
Просто мысль.
источник
Разница между Postgres и MySQL в этом отношении заключается в том, что в Postgres он не воссоздает таблицу заново, а изменяет словарь данных, аналогичный Oracle. Следовательно, операция выполняется быстро, хотя по-прежнему требуется выделить исключительную блокировку таблицы DDL на очень короткое время, как указано выше другими.
В MySQL операция будет копировать данные в новую таблицу при блокировании транзакций, что было основной проблемой для администраторов баз данных MySQL до версии 5.6.
Хорошая новость заключается в том, что с момента выпуска MySQL 5.6 ограничение было в основном снято, и теперь вы можете наслаждаться истинной мощью базы данных MYSQL.
источник
Как уже упоминал Шон Дауни,
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-schema-changes-with-percona/
источник
Фиктивные столбцы - хорошая идея, если вы можете предсказать их тип (и сделать их допускающими значение NULL). Проверьте, как ваш механизм хранения обрабатывает нули.
MyISAM заблокирует все, если вы хотя бы мимоходом упомянете имя стола по телефону в аэропорту. Он просто делает это ...
При этом замки на самом деле не такая уж большая проблема; до тех пор, пока вы не пытаетесь добавить значение по умолчанию для нового столбца в каждую строку, но позволяете ему оставаться равным нулю, а ваш механизм хранения достаточно умен, чтобы не писать его, вы должны быть в порядке с блокировкой, которая только достаточно долго, чтобы обновить метаданные. Если вы все же попытаетесь написать новое значение, то вы - тост.
источник
TokuDB может добавлять / удалять столбцы и добавлять индексы «горячо», таблица полностью доступна на протяжении всего процесса. Он доступен на сайте www.tokutek.com.
источник
На самом деле, нет.
В конце концов, вы изменяете базовую структуру таблицы, и это часть информации, которая очень важна для базовой системы. Вы также (вероятно) перемещаете большую часть данных на диске.
Если вы планируете делать это часто, вам лучше просто заполнить таблицу «фиктивными» столбцами, которые будут доступны для использования в будущем.
источник