Управление изменениями в базе данных

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

У меня проблемы со "стандартным" способом переноса базы данных в sequel и activerecord. И sequel, и 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                           
);  

Требования меняются, и мне нужно изменить тип функции. В Migration 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 в новый файл миграции сиквела / активной записи. Но это боль. : /

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

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

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

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


person Joe Van Dyk    schedule 29.03.2012    source источник
comment
github.com/nkiraly/DBSteward выглядит интересным подходом к решению этой проблемы.   -  person Joe Van Dyk    schedule 29.03.2012
comment
Привет, я со-сопровождающий DBSteward. Я знаю, что прошло уже почти 4 года с тех пор, как вы задали этот вопрос, но мы все еще активно развиваем DBSteward. Мне интересно узнать, использовали ли вы DBSteward или нет, и каков был ваш опыт работы с ним или почему это не помогло решить вашу проблему.   -  person Austin Hyde    schedule 23.12.2015


Ответы (2)


Я бы порекомендовал liquibase.

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

person Mark O'Connor    schedule 30.03.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, настроенный с выключенным / включенным ramdisk fsync и т. Д., То восстановление всей БД и ее заполнение может занять секунды (если у вас не слишком много тестовых данных).

Начните с №1, №2, затем добавьте №6 (pgTAP очень круто), а затем все остальное. Ключевым моментом является набор тестов, который проверяет ваш код в базе данных.

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

person Richard Huxton    schedule 30.03.2012