Pull to refresh

Comments 55

Если честно, то как-то неубедительно.

Проблемы с БД решились только после того, как ею стали заниматься всерьез.

Не совсем понимаю, как переход к хранению в XML избавил от версионности.
Она осталась, пусть теперь для XML а не полей БД.

Да и плохо я представляю, как можно перейти к XML, если в база используется для чего-то большего, чем хранение данных. Скажем, отчетности, различные выборки и т.д.
Вы правы, версионность осталась на месте. Но, сравните ресурсоемкость добавление/удаления 100 полей в таблицу с измеенением структуры XML представления.

Касательно второй части вопроса: при переходе к scheme-less базе потери и ограничения очевидны. В описываемом случае специфика продукта позволяла выполнить такой переход практически без боли. Пожалуйста, не воспринимайте написанное как абсолютный рецепт счастья. Говорить о применимости того или иного подхода имеет смысл исключительно в контексе конкретной проблем/продукта.

На всякий случай: система интенсивно использующая SQL с частотой изменений базы 2-3 обновления в год вполне нормально будет переносить ALTER TABLE. Система с 30-100 новыми параметрами в месяц и достаточно сложными структурами данных при аналогичном подходе покажется адом.
В принципе, при переходе к XML я вижу 1 существенный "+":
Можно реализовать схему, когда изменять структуру непосредственно в момент обновления не нужно.

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

В результате задача «обновить структуру» решается не на сервере в момент обновления, а на клиенте по мере обращения к данным. Но опять же — все зависит от специфики.
Такой подход уменьшит размер хранимых данных еще на порядок. По сути вы предлагаете хранить изменения в инкрементальном виде.

Я все еще не отсавляю идею описать другой проект, в котором переход базы с несколькими миллионами пользовательских профайлов (структуры с пользовательскими настройками средней сложности) не требовал ни какого-либо времени бездействия ни дополнительных операций. Редеплой приложение — все что реально было нужно.
Если у вас действительно такая задача — NoSQL ждет вас с распростертыми объятиями.
Не смогли осилить, да? Пришлось писать велосипед? Жаль.
Не смогли осилить что? Люди решали вполне реальные задачи, допуская вполне человеческие ошибки.
Особенности современной разработки
мы не смогли справиться с апгрейдом баз и решили использовать самую разрекламированную технологию на тот момент. оказалось, что у этой технологии тоже есть недостатки! кроме того, в базе скопилась огромная куча говна. говно мы пожали архиватором.
Заключение
ещё мы очень много коммитили, потому что было много ошибок. но мы тут не виноваты совсем, а нам оно так досталось от предыдущих разработчиков.
Бонус
мы думали о том, чтобы использовать ещё более ебанутую технологию. вот красивый график, который показывает преимущества:
прошу прощения. ничего личного, я только описал свои впечатления от статьи
Никаких проблем. Проект пришел в компанию таким каким пришел. Предполагаю, опыт в любом случае интересен. Любая компания, занимающаяся аутсорсингом, может получить нечто похожее.

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

Ну а с XSLT — да, многим вариант покажется ужасным. Нам он не совсем подошел.
Ха-ха! Спасибо. Я как раз надеялся найти в коментах краткое содержание :)
А вообще, следовало вместо хранения в столбцах хранить в строках…
Вы о сolumn-oriented базах (оставим линк интересующимся). Согласен, вариант.

Признаюсь, я собирался заменить базу key-value хранилищем. Напримре: project-voldemort
Нет, я говорю о денормализации бд. Вместо заведения колонки типа X — добавлять в таблицу values_x поле id,column_name,value.
То есть заводятся таблицы для хранения чисел, дат, строк и тп; и в них добавляю строки вида idобъект, поле, значение.
В общем-то да, это аналог key-value, только с проверкой типов, индексацией и прочими плюшками.
Хотя, разумеется, это не панацея, и сложные составные индексы отпадают — тем не менее, для хранения метаданных (А параметры конфигурации это и есть метаданные по сути) подходят прекрасно.
зачем хранить XML как BLOB? по нему же нельзя xpath'ом искать, да и индексы опять же
или MySQL не поддерживает тип данных XML? я просто в другом стеке работаю
какой смысл в MySQL, если в ней все данные хранятся в XML? или не все?
MySQL — наследие предков (еще раньше оракл был), но вы правы, желание избавиться от реляционной базы данных появилось сразу после анализа системы. Но мешало этому следующее:

1. заказчик с огромным нежеланием соглашался на какие-либо серьезные изменения (очень часто заказчик создает больше проблем, чем сам продукт)
2. остается проблема существующих клиентов, их нужно опять «мигрировать» (кстати, изначально на выбор хранилища повлияло наличие у потенциальных клиентов баз данных и MySQL, в частности, хотя даже встраиваемый вариант, BerkeleyDB например, был бы в разы лучше)
3. заметил в корпоративной среде наличие некоторых предубеждений, яркий пример: «вы используете хранилище название которого я не знаю? тогда я не могу купить вашу систему», а знают обычно oracle, продвинутые еще mysql
Перечисленные вами проблемы — не технические. То есть, в вашем проекте технические решения принимались как результат политических проблем. Поэтому ваш пример хотя и показателен, но развитие событий в нем не может служить ориентиром для преимущественного большинства других проектов.
Я перечислил не все проблемы, но соглашусь с вами полностью. Описываемые решения не являются ни руковдством к действию ни готовым рецептом.

Тем не менее, суть проблемы сводится к внесению большого количества изменений в структуру хранимых данных. Соответственно, могут быть рассмотрены два варианта: структура совпадает со структурой базы данных и не совпадает с ней (реализована на более высоком уровне).

Мой вывод: первый вариант не позволяет свободно выполнять достаточный набор преоразований без существенных последствий, ввиду очевидных ограничений СУБД.

Другой реальный пример:
In particular, making schema changes or adding indexes to a database with more than 10 — 20 million rows completely locks the database for hours at a time. Removing old indexes takes just as much time, and not removing them hurts performance because the database will continue to read and write to those unused blocks on every INSERT, pushing important blocks out of memory.
UFO just landed and posted this here
Да, с миллионами блобов бывает весело, не то слово ;)
UFO just landed and posted this here
Да, вы правы, документо-ориентированные базы являются вполне естественным и очень рациональным решением.

Идею, кстати, можно развить и попытаться абстрагироваться от хранилища как такового. Если вам близка экосистема Java неплохим ответом может стать Content repository API for Java и
ModeShape в качестве реализации.
интересно было бы прочитать про «реализацию непрерывной интеграции (continuous integration) для существующего уже длительное время большого проекта»
как раз занимаюсь аналогичной темой, хотелось бы услышать про вариант решения
Материал обязательно подготовлю. Кратко: использую Hudson (стоит обратить внимание на Jenkins после раскола) и набор плагинов под конкретного заказчика.

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

Пара хитростей:
1. тестами в первую очередь становятся реальные проблемы
2. тесты, по времени выполнения, делятся на три категории: до 60 секунд, до 5 минут, до 10 минут. Стараюсь поддерживать соотношение 80% 15% 5%. Первый тип запускается после каждого комита.
Заголовок «Версионная миграция структуры БД: почему так лучше не делать»
Так и не нашел в статье ответа почему же так лучше не делать.
Описываема история реальна и вполне определенно намекает на большое число проблем как с процессом разработки (набор инкреметальных изменений, затрагивающих структуру базы данных) так и с последующим обновлением реальных баз данных.

Коротко: если production база имеет значительный размер и вы захотите менять ее структуру часто и кардинально — потери времени, нервов и волос, в разных пропорциях, неизбежны.
И все-таки, не совсем понятно, как именно лучше не делать (следуя заголовку статьи).
Вообще, позвольте представится. Я — автор статьи, которая, похоже, и послужила толчком к написанию всех последующих статей с описанием практического опыта версионной миграции.

Так как вы упомянули мою статью во вступлении, было бы интересно узнать, какой же из трех способов, в ней описанных, вы изначально использовали в своем проекте. Похоже, это было что-то близкое к методу, который я назвал «методом инкрементных изменений». Причем, действительно, в нем существует такой недостаток: потенциально долгое/неоптимальное выполнение миграций — из-за того, что инкрементных изменений может быть много, и более новые могут перетирать старые. Поэтому выполнение всех изменений нерационально, хотя и практически неизбежно (в рамках этого метода).

Но в моей статье также описан и другой метод: «уподобление структуры БД исходному коду». В этом случае diff-скрипт для миграции между двумя конкретными версиями генерируется непосредственно перед миграцией и изменяет структуру БД наиболее рациональным способом, без промежуточных состояний. Этот метод не лишен своих недостатков, но относительно вашего критерия — скорости выполнения миграций — ему, похоже, нет равных.
Интересно, рассматривали ли вы этот метод в своем проекте.

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

Ответил вам ранее. Постараюсь кратко сформулировать все замечания, предположения и выводы для облегчения последующей дискуссии:
1. Современный процесс разработки ориентирован на короткие итерации, частые билды и т.д.
2. Инкрементальные изменения структуры баз данных весьма дороги ввиду явных ограничений СУБД
3. На ранних этапах разработки ограничения СУБД не всегда очевидны/интересны (показано в статье)
4. Успешный продукт столкнется с большинством проблем достигнув значительных размеров, именно тогда многие проблемы будет очень сложно исправить
5. Выбор способа хранения и обработки данных зачастую определяет/является архитектурой приложения
6. Внесение значительных изменений в архитектуру на поздних стадиях является очень дорогим удовольствием
7. Именно на поздних стадиях разработки процесс пытаются ускорить ввиду явных преимуществ с точки зрения прибыльности
8. Изменения структуры базы данных часто влекут за собой дополнительную обработку/преобразование хранимых данных
9. На поздних стадиях любые изменения структуры базы данных, ввиду многих ограничений СУБД, оборачиваются проблемами.
10. Для многих проектов версионная миграция структуры БД на ранних этапах покажется очевидным решением, впоследствии став серьезным ограничением. Более или менее универсальный рецепт — необходимо стараться избегать частого изменения структуры базы данных.

Повторю ссылку на другой пример — пример
UFO just landed and posted this here
Вам будет интересна вторая часть. В первой постарался описать проблему и привести реальный пример.
но вы же сами упоминали более оптимальный вариант миграций БД путем copy/rename вместо alter table. для кардинальных изменений сойдет, разве нет?
Сopy-rename — более безопасный и предсказуемый вариант выполнения миграции структуры. Проблему он не решает и для больших баз достаточно накладен.
IMHO, оправдано только в одном случае: если с системой работают меньше чем её обновляют. Видел в своей жизни высоконагруженные реляционные базы на сотни террабайт. Версии ПО менялись практически каждый месяц(специфика такая). Даже боюсь представить, что было бы, засунь туда XML.

И да, как справедливо заметили выше — документо-ориентированные базы никто не отменял.

Статья вредная — вдруг кто-то реализует, а другим потом мучаться…
С системой работали продолжая развивать — характерная ситуация для многих современных проектов. Касательно вышего примера: если данные/структура БД не меняется во время обновления ПО — обновления можно проводить хоть каждый час.

Что делать если во время обновления вам необходимо изменить структуру базы или трансформировать данные, делая их совместимыми с новой версией ПО? В этом случае процесс перехода/преобразования будет занимать значительное время. Именно такая ситуация описывается в статье.

Касательно «вредности»: предупрежден — вооружен. Никто не призывал реализовать описываемый метод, наоборот, статья демонстрирует реальные проблемы из жизни реального продукта и призывает не делать ошибок на самых ранних стадия проектирования.
Структура менялась, незначительно, но все же(учитывая объем базы).
Если необходимо изменить структуру — меняй. Есть специальные инструменты для этого. Например www.liquibase.org/
А есть ли утилиты, которые бы анализировали изменения в структуре бд (например локальной) и накатывали изменения на другую бд (общий продакшн) и наоборот?
Другими словами, возможность update-commit-rollback из VCS перенесенная на БД.

Пусть будут свои служебные таблицы, пусть будут свои форматы файлов, все что угодно, лишь бы была возможность вносить измнения на локальную БД, сделанные напарником (и приехавшие через subversion) НО без создания описывающего файла xml.
В общем, считаю, что проблема у вас была не в ошибочности подхода версионной миграции структуры, а в её реализации.
Понимаю вашу позицию и благодарен за комментарии. Все что хотел сказать: если зменения структуры происходят часто — механизм (который так или иначе базируется на инструментарии базы данных, ALTER TABLE и т.д.) начнет отравлять жизнь, требуя дополнительных затрат ресурсов. Эту проблему нужно решать заранее.

Liquibase не является панацеей, не обладает магическими свойствами и не сможет обойти ограничения СУБД.
Будет. Требуется некоторое время на подготовку.
… а теперь попробуем построить по этой базе большой красивый отчет. Или экспортировать ее под OLAP. Oooops.

Ну и да, тема «почему не надо делать версионную миграцию» незаметно заменена «почему надо использовать document storage вместо реляционного хранилища». А версионные миграции мы оставим, просто на уровне xml.
Вы описываете как все плохо в каком-то подходе и какой-то технологии, и при этом применяете ее не для того сценария.
Ваша задача требует, судя по всему, отказа от схемы как таковой, она — только лишняя проблема, и реляции не имеют нужного профита — к черту их. К черту SQL — нужно смотреть в сторону nosql-document-db. Это то, что реально работает (со своими сложностями, конечно же, но это будет right tool for the right job).
А еще, как отдельный подход к решению проблемы долгого обновления продакшн-серверов, существует балансировка нагрузки (load balancing). Может быть, этому подходу есть более точное название, буду благодарен, если кто-то подскажет.

Суть в том, что есть несколько серверов, на которых крутится одна и та же версия (веб-)приложения, каждая со своим сервером БД. Сервера БД реплицируются между собой время от времени. Юзеры приложения автоматически перенаправляются на назначенный им сервер при помощи load balancer'а, — железного либо софтового, — который равномрно распределяет нагрузку.

Когда нужно обновиться на новую версию, это делается поэтапно. Сначала одна из копий приложения освобождается от юзеров, которые постепенно перенаправляются на другую копию. Затем приложение обновляется вместе с БД и снова становится активным. Юзеры, попавшие на него, увидят обновленную версию.
Затем постепенно таким же образом обновляются и все остальные копии вместе со своими БД.

У этого подхода есть большая сложность в реализации: корректная репликация данных между серверами. Но все сложности преодолимы :)
Данные подход позволяет смягчить проблему обновления, но не решает ее. Репликация — отдельный, далеко не самый простой, вопрос. Кроме того, во время обновления все сервера БД будут ограничены режимом read-only до тех пор, пока процесс не будет завершен.

Думаю наилучший метод — избежать такого рода проблем. Это возможно, но очень сильно зависит от специфики того или иного проекта.
Вы что, серьезно?! Вы действительно это все сделали?..
Блин, я так и не понял как так у вас получилось, что обновление xml-ного блоба быстрее и стабильнее sql миграции.

Или миграции в Java EE какие-то странные, не знаю.
SQL миграция не исключает необходимость последующей обработки/преобразования хранимых данных.

В случае со структурой на уровне XML представления необходимо быть уверенным в следующем:
1. все преобразования корректны (легко тестируется, на проверку всех преобразований необходимо ~1минут)
2. начальные данные корректны (XSD валидация перед запуском преобразований)
3. результат корректен (XSD валидация после запуска)

Кроме того, давайте оценим риски: ошибка во время преобразования XML — легко отлавливается, изменения не сохраняются; ошибка во время смены структуры — чуть более сложный случай :)
У вас там преобразование 100МБ+ XML файлов быстрее, чем миграция SQL базы идёт?
DUMP знаком?
Что с индексами и скоростью выборки в чудо-базе?

В своё время занимался тем же самым, только XML-представление было промежуточным между старой и новой базой, через него переносились только сами данные, был экспорт из старой версии и импорт в новую. Танцы с бубном были, особенно учитывая, что это была DB2, но тем не менее гораздо более простые, нежели с XSLT. Преобразования были на Java.
Тут тоже интересная вещь.

Я бы посмотрел как будете терабайтную базу XSLT'ить.
В описываемом случае преобразования на Java, Groovy и небольшом rule-based движке. XSLT рассматривался, но не прижился.

Касательно миграции — изменение структуры не всегда избавляет от преобразования данных. Собственно, в общем случае мы говорим о миграция+преобразование или преобразование XML.

Касательно индексов — все максимально просто, индекс по OID. По сути, таблица с конфигурацией являлась key-value хранилищем.

Касательно большой базы — для всех преобразований проводилась небольшая оптимизация по скорости, кроме того, поскольку преобразования реализовывались как независимые цепочки переходов от версии X к верси Y для независимых конфигураций — они чудесно параллелились на уровне исполняющего механизма.
Конечно не исключает. Но что вы называли миграциями? SQL файлики что ли?

Я давно ушел с Java EE, просто в Rails принят такой подход

Генерится скрипт миграции.

В нем
— комманды для изменения таблиц
— все необходимые действия с объектами

Причем, принято писать как «накатывание» миграции, так и «откатывание».

Я читаю про XSD и все равно не понимаю, как это вас спасает… Ну да XML будет валидным, но какие гарантии что данные преобразовались?

Насчет оценки рисков тоже непонятно…
Sign up to leave a comment.

Articles

Change theme settings