Лучшие практики для изменения схемы и миграции данных в оперативную базу данных без простоев?

43

Как вы вносите изменения в схему действующей базы данных без простоев?

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

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

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

(Я использую PostgreSQL на Heroku .)

Дэн Лири
источник
2
Facebook разработал инструмент для этого для MySQL.
Ник Чаммас
2
К. Скотт Аллен писал о системе управления версиями схемы здесь . Я создал DbUpdater, инструмент с открытым исходным кодом для развертывания схемы с учетом версий. Больше здесь - http://www.tewari.info/dbupdater
ясень
@NickChammas Спасибо, что поделились этим. У меня много вопросов по этому поводу. Не могли бы вы предложить более подробное руководство, желательно видео, которое объясняет такие вещи, как битовый журнал, некластеризованные индексы, и отвечает на такие вопросы, как - 1. Как выбор данных из исходной таблицы в файл сокращает нагрузку по сравнению с копированием в место назначения стол напрямую. 2. Когда закончится фаза копирования? У меня есть только несколько вопросов, и я только начал их читать.
Сандипан Нат
@SandeepanNath - Извините, я не настолько знаком с инструментом Facebook и поэтому не могу указать вам больше ресурсов. Я прочитал объявление об этом и разместил свой комментарий несколько лет назад, но я никогда не использовал его.
Ник Чаммас

Ответы:

27

Вы уже почти получили свой ответ:

  1. Создать новую структуру параллельно
  2. Начните писать в обе структуры
  3. Перенос старых данных в новую структуру
  4. Только писать и читать новую структуру
  5. Удалить старые столбцы

Что касается шага 3 , используйте что-то вроде этого (в одной транзакции):

Вставьте то, чего еще нет:

INSERT INTO new_tbl (old_id, data)
SELECT old_id, data
FROM   old_tbl
WHERE  NOT EXISTS (SELECT * FROM new_tbl WHERE new_tbl.old_id = old_tbl.old_id);

Обновите то, что изменилось за это время:

UPDATE new_tbl
SET    data  = old.data
USING  old_tbl
WHERE  new_tbl.old_id = old_tbl.old_id
AND    new_tbl.data IS DISTINCT FROM old_tbl.data;

Новые данные не будут затронуты, потому что они идентичны в обоих местах.

Эрвин Брандштеттер
источник
У меня есть несколько вопросов, пытаясь понять сценарий, для которого вы предложили этот ответ: 1. Будут ли изменения в коде внедряться вместе с началом изменений в БД? 2. Почему будет необходимость писать в обе структуры? 3. Почему нельзя сначала вызвать новую структуру, а затем перенести существующие данные, а затем развернуть изменения кода, которые заполнят новую структуру? 4. Почему нужно выяснить, чего там нет (ваш 1-й запрос)? Вы предлагаете вставку в нескольких попытках?
Сандипан Нат
2
@SandeepanNath, чтобы ответить на вопрос 3 в своем комментарии: потому что, если вы (а) создадите новую структуру, (б) перенесете в нее данные, (в) измените свой код, чтобы записать данные в новую структуру вместо старой, тогда все изменения данных, сделанные между этапом b и этапом c, будут существовать только в старой структуре. Вопрос заключался в том, как вносить изменения в схему без простоев. Прочтите этот ответ еще раз, внимательно.
Wildcard