Модификация столбцов очень больших таблиц mysql практически без простоев


18

Мне периодически нужно вносить изменения в таблицы в MySQL 5.1, в основном добавляя столбцы. Очень просто с помощью команды alter table. Но в моих таблицах сейчас до 40 миллионов строк, и они быстро растут ... Так что эти команды изменения таблицы занимают несколько часов. Я думаю, через пару месяцев они займут дни.

Поскольку я использую amazon RDS, у меня не может быть подчиненных серверов, с которыми можно поиграть, а затем повысить их до мастерства. Итак, мой вопрос: есть ли способ сделать это с минимальным временем простоя? Я не возражаю против операции, занимающей часы или даже дни, если пользователи все еще могут использовать БД, конечно ... Могут ли они хотя бы читать, когда добавляются столбцы? Что произойдет, если мое приложение попытается написать? Вставить или обновить? Если он сразу выходит из строя, это на самом деле не так уж плохо, если он просто зависает и вызывает проблемы для сервера БД, это большая проблема.

Это должно быть довольно распространенной проблемой масштабирования, все должны добавлять столбцы. Что обычно делается с производственной БД? Раб -> Мастер миграции?

Обновление - я забыл упомянуть, что я использую механизм хранения innodb


1
В случае, если кто-то все еще ищет ответ .. blog.staginginstance.com/… ^^
анонимный

Ответы:


10

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

Не. Нет, правда. Просто не надо. Это должно быть очень редким случаем, когда это когда-либо необходимо.

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

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

Наконец, если ваша схема действительно нормализована и вы действительно должны продолжать добавлять столбцы, тогда:

  1. Убедитесь, что у вас есть столбец отметки времени в базе данных или что она генерирует журналы репликации
  2. Создайте копию (B) таблицы (A)
  3. добавьте новые столбцы в B (это все еще будет блокироваться с помощью myisam)
  4. отключить транзакции
  5. переименовать исходную таблицу (A) как-то еще (резервная копия)
  6. переименуйте новую таблицу (B) с именем исходной таблицы (A)
  7. воспроизвести транзакции с начала операции из журнала репликации или из таблицы резервного копирования
  8. включить транзакции.

2
Спасибо за ваш пошаговый подход. Действительно ли редко можно изменять таблицы? Я понимаю, что вместо этого я могу добавить другую таблицу с новым столбцом (в случае необходимости добавления столбца) и сделать так, чтобы она ссылалась на исходную большую таблицу в соотношении 1: 1. Но кажется неправильным иметь 15 очень больших таблиц 1: 1, когда все они должны быть в одной таблице ... Производительность запросов, конечно, тоже страдает, не говоря уже о проблемах индексации. Я не эксперт, но моя база данных довольно хорошо нормализована, и кажется естественным, что мне нужно периодически изменять ..
apptree

2
"Неужели редко можно изменять таблицы?" - Да.
Symcbean

1
Нет, но можно утверждать, что если это происходит РЕГУЛЯРНО - не в рамках масштабного обновления программного обеспечения - тогда нужно уволить кого-то за то, что он не осознает, что все таблицы должны быть в первую очередь. Проблема / хитрость здесь в том, чтобы «регулярно», а не «раз в пару месяцев».
TomTom

22
Как разработчик, особенно тот, который работает в стартапах и молодых компаниях, я не мог не согласиться с Symcbean и @TomTom. Вещи меняются, продукты меняются, меняются бизнес-цели и структура базы данных должна меняться вместе с ними. Предоставление хороших услуг администратора баз данных означает сказать «да» этим изменениям, а затем выяснить, как их эффективно реализовать. Сильно нормализованные базы данных - это концепция, которая давно умерла. Они приводят к плохой производительности и медленным циклам разработки.
pents90

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

12

Я просто должен был сделать это недавно. Amazon рекомендовал использовать Percona Toolkit. Я скачал его и смог запустить что-то вроде:

./pt-online-schema-change h=databasenameHostName,D=databasename,t=tablename --recursion-method=none --execute --user username --password password --alter "MODIFY someColumn newDataType"

и это прекрасно работает. Он говорит вам, сколько времени осталось в процессе.

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


У команды Percona есть небольшая статья о включении функции log_bin_trust_function_creators через группы параметров RDS (так как SET GLOBAL log_bin_trust_function_creators = 1 не работает в RDS), что требуется для инструмента изменения схемы pt-online-schema. Более подробная информация: percona.com/blog/2016/07/01/pt-online-schema-change-amazon-rds
user1652110

это сработало для меня
Adiii

4

Symcbean дает некоторые твердые рекомендации .

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

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

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


2

Из руководства: http://dev.mysql.com/doc/refman/5.1/en/alter-table.html

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

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


Итак, я сделал это и отключил части моего сайта, которые пишут в таблицу, которую я сейчас изменяю. До сих пор я получил несколько исключений «Превышено время ожидания блокировки; попробуйте перезапустить транзакцию», это не так уж плохо. Тем не менее, они были на ЧИСТЫХ операциях чтения ...
Apptree

0

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

  1. Используйте прямой ALTER и дайте ему поработать (X числа часов или дня)
  2. Убедитесь, что у вас есть столбец отметки времени в базе данных или что она генерирует журналы репликации
    • Создайте копию (B) таблицы (A)
    • добавьте новые столбцы в B (это все еще будет блокироваться с помощью myisam)
    • отключить транзакции
    • переименовать исходную таблицу (A) как-то еще (резервная копия)
    • переименуйте новую таблицу (B) с именем исходной таблицы (A)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.