metaclass: (Default)
[personal profile] metaclass
В связи с тем, что я таки частично реализовал свою давнишнюю идею генерить опердень из модели опердени, хранящейся в этой же опердени, очередной раз решил поразмыслить над вопросом "как же должна выглядеть миграция данных при изменении модели".

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

Но предположим, что мы сделали генератор опердени и дали его специально обученным настройщикам клепать предметную область. При этом они могут менять описания таблиц и полей (как сделано на данный момент) или структуры хранящихся объектов (как хотелось бы сделать будущем) и это, само собой, должно как-то в итоге отобразится на рабочей базе.
Первая мысль - что их изменения в рабочую базу попадают только в виде сгруппированного набора непротиворечивых действий, т.е. вперемежку изменений данных и метаданных таким образом чтобы база не оказалась в состоянии типа "в not null полях сидят null". Некоторые базы такое не дают делать, у некоторых при DDL операциях такое возможно, потом бэкап черезжопными методами восстанавливать придется.
Второе - что их работа над моделью должна вестись под системой контроля версий. Но работа ведется, во-первых, не над текстом модели, а в специализированном GUI (который может отражать состояние некоего текста, а может и не отражать - сейчас модель хранится в специально заточенной базе Firebird), а во вторых, _текстовый_ контроль версий не отражает происходящего с моделью в, условно говоря, строго типизированном виде.
Т.е. например "добавить поле в таблицу" с точки зрения системы типов выглядит как модификация описания этого типа методом "добавить в список полей еще один элемент", а с точки зрения какого-нибудь меркуриала - это просто появление новой строки где-то в середине файла модели и ему пофиг на смысл этой строки. Конечно, из hg diff можно было бы сделать описание операции в типизированном виде, но это, по моему убеждению, есть удаление гланд через задницу, т.к. текст должен генерироваться из строго типизированных данных, а не оные данные должны доставаться методом парсинга текста хз какого формата.

На данный момент у меня рабочая идея примерно такая: закрыть бухгалтерам доступ к базе опердени, написать по емылу им, что их софт больше не обслуживается, выключить телефон, завтра вместо работы пойти купить зеркалку и поехать фотографировать уток на речку к базе данных модели добавляется лог всех произведенных в ней изменений в отдельные таблицы со сквозной нумерацией. Этот номер в логе и будет текущей "ревизией" модели. При каждой генерации и деплойменте в результатирующий скрипт деплоймента вставляется номер ревизии. И в состав скрипта деплоймента будут входить все изменения от начала (ну или если мы точно знаем что база какой-то версии - от этой версии) до текущей ревизии.

Сейчас у меня кодогенерация происходит по текущей модели, т.е. условно говоря, это "создать базу с нуля до текущего состояния". А реально нужно другое, более сложное: нужно накатить на существующую базу изменения "от прошлой кодогенерации до текущей". Причем накатить непротиворечивым образом. И вместо кодогенератора который делает из модели просто скрипты создания всех нужных объектов базы данных и описание GUI к ним, нужно каким-то образом из списка изменений сделать скрипты изменения схемы базы данных и обновления данных в базе (я думаю, не всегда тривиальных).
И в таком случае вылазят всякие хитрые заморочки, в основном связанные с зависимостями объектов на уровне метаданных и зависимостями на уровне данных - например, в Firebird грохнуть объект, на который ссылается другой объект просто невозможно - нужно сначала грохнуть зависимый(а если от него еще что-нибудь зависит - то по цепочке, или же сделать объект с пустым телом). На уровне данных - это всякие внешние ключи, которые не дадут изменить данные если их создать слишком рано (поэтому всякие утилиты импорта данных сначала всасывают данные а потом создают внешние ключи).

С теоретической точки зрения это все выглядит как список функций "МодельN+1=F(N)(МодельN)", потом функция, которая из функций преобразования модели генерит скрипты преобразования базы данных, возможно, анализируя список изменений на предмет "сгрупировать изменения в один скрипт", и функций преобразования "старая версия объекта"->"новая версия объекта" и анализа "можно это сделать средствами SQL(alter table) или придется долбится курсорами по всей базе до посинения".

Кстати, я до сих пор не очень понимаю, что в таких случаях предлагаю всякие NoSQL базы. Я так понимаю, там же ложится/достается чисто объект по ключу в хранилище. А если мы поменяем описание объекта в коде программы, нужно ж будет описывать явно "что делаем при загрузке старой версии объекта". О ад-хок запросах к таким вещам даже и думать не хочется.

Date: 2010-04-07 12:01 pm (UTC)
From: [identity profile] metaclass.livejournal.com
У меня места и производительности хватает, а вот у клиентов то места нет, то комп медленный, то времени мало - нужно базу в онлайн возвращать.

Profile

metaclass: (Default)
metaclass

April 2017

S M T W T F S
      1
2345678
9101112 131415
16171819202122
23242526272829
30      

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Aug. 27th, 2025 03:38 pm
Powered by Dreamwidth Studios