Управление изменениями базы данных - PullRequest
4 голосов
/ 29 марта 2012

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

У меня проблемы со "стандартным" способом переноса базы данных в сиквел и activerecord. И сиквел, и activerecord позволяют помещать произвольный SQL-код в файлы с метками времени. При запуске каждого файла таблица schema_versions обновляется именем файла (или отметкой времени в имени файла), в котором хранится запись о том, какие миграции были применены к текущей базе данных.

Если на уровне базы данных выполняется много кодирования, это означает, что изменения существующих представлений, функций и т. Д. Выполняются по следующей схеме:

Миграция 1 определяет функцию и представление, которое использует эту функцию.

-- Migration 1
create function calculate(x int) returns int as $$                              
  return x + 1;                                                                 
$$ language sql;                                                                

create view foos as (                                                           
  select something, calculate(something) from a_table                           
);  

Требования меняются, и мне нужно изменить тип функции. В Миграция 2 мне нужно отбросить все объекты, которые зависят от foo, и воссоздать их, скопировав все их тело - даже если в большинстве других кодов не было никаких изменений!

-- Migration 2                                                              

-- Have to drop all views and functions that depend on the                  
-- `calculate(int)` function.                                               
drop view foos;                                                             
create or replace calculate(x bigint) returns bigint as $$                  
  return x + 1;                                                             
$$ language sql;                                                            

-- I could do `drop function calculate(int) cascade`,                       
-- but I might accidentally drop some objects that wouldn't get recreated below.

-- Now I have to recreate foo.                                              
create view foos as (                                                       
  select something, calculate(something) from a_table                       
);

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

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

Есть идеи как решить эту проблему?

Моя лучшая идея заключается в том, чтобы sql-код содержался в их собственных канонических файлах (app / sql / orders / shipping.sql, app / sql / orders / creation.sql и т. Д.). Каждый развивается непосредственно на этом. Всякий раз, когда наступает время для выпуска, вы захотите создать новый файл миграции, посмотреть на весь измененный код со времени предыдущего выпуска, выяснить цепочку зависимостей объектов базы данных, которые необходимо удалить и воссоздать, а затем скопировать sql из канонических файлов sql в новый файл миграции сиквел / activerecord. Но это боль. : /

Мысли очень приветствуются. Надеюсь, я объяснил это достаточно хорошо, я сокращаю потребление кофеина и немного нервничаю.

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

  • SQL-код для запуска
  • представления базы данных для удаления и воссоздания

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

Ответы [ 2 ]

4 голосов
/ 30 марта 2012

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

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

1 голос
/ 30 марта 2012

Вы можете найти интересную запись в блоге Дейва Уилера, начиная с этой страницы:

http://justatheory.com/computers/databases/simple-sql-change-management.html

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

  1. Makefile, который может перестроить базу данных разработки с нуля
  2. Набор файлов схемы, разделенных на «модули» (lookups_schema.sql, lookup_data.sql)
  3. Набор файлов обновлений, которые переходят от одной ревизии к следующей
  4. У меня обычно нет соответствующих сценариев понижения, некоторые люди делают
  5. Скрипт для заполнения моей базы правдоподобным количеством тестовых данных
  6. Очень важно, набор тестов через pgTAP , который проверяет мои различные функции, представления, а также сценарии обновления. Тесты обновления также можно запускать на действующей базе данных.

Если у вас есть отдельный экземпляр PostgreSQL, настроенный с fsync, включенным / выключенным ramdisk и т. Д., То для восстановления всей БД и ее заполнения может потребоваться несколько секунд (если у вас не слишком много тестовых данных).

Начните с # 1, # 2, затем добавьте # 6 (pgTAP это очень круто), затем все остальное. Важнейшая вещь - это набор тестов, который проверяет ваш код в базе данных.

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

...