Ответ 1
Прежде всего, обновления БД являются злыми, но blog описывает общий кошмар.
Можно создать матрицу компетенций программиста на основе подхода к обновлению:
- Уровень 0: нет обновлений вообще. Клиенты испуганы и перемещают данные вручную, используя пользовательский интерфейс, предоставляемый приложением или сторонними решениями управления БД (поверьте, это действительно возможно).
- Уровень 1: для обновления дампа базы данных существует script. Клиенты чувствуют себя в безопасности, но они исправят крошечные и очень раздражающие проблемы в течение следующих 1-2 лет. Система работает, но никаких изменений не было.
- Уровень 2: изменение таблицы. Чудовищное время простоя, особенно в случае возникновения проблемы при обновлении. Огромные проблемы и практически никаких гарантий для получения 100% безопасного результата. Преобразование данных управляется с помощью buggy script. Клиенты не довольны.
- Уровень 3: схема без схемы: простоя в течение одного-двух часов, чтобы позволить скриптам с ошибками переводить конфигурацию в БД (этот шаг может повредить БД во многих случаях). У парней поддержки все запасы кофе полностью исчерпаны.
- Уровень 4: ленивые прозрачные обновления: нулевой простоя, но все же возможны некоторые проблемы. Клиенты почти счастливы, но все же помнят предыдущий опыт.
- Уровень 5: Идеальная архитектура, не требуется явное обновление. Полное счастье. Клиенты не знают, что такое процедура обновления. Разработчики продуктивны и спокойны.
Я опишу все технические проблемы, но до этого позвольте мне изложить следующее (пожалуйста, простите мне довольно длинный ответ):
- В настоящее время циклы разработки очень сжаты, а базы данных большие.
- практически любая функция может вносить изменения в схему и прерывать совместимость, поэтому либо у нас есть простая и стабильная процедура обновления, либо мы можем отложить функцию
- проблемы могут быть идентифицированы клиентом, поэтому есть шанс получить срочную сборку исправлений с некоторыми требуемыми шагами обновления.
- Вообще говоря, гораздо лучше избегать любых барьеров между вами и вашим клиентом.
Уровень 0 и уровень 1 Оба случая очевидны и глупы. Никто не должен этого избегать.
Уровень 2 Изменение не так уж плохо для небольших таблиц, но это может быть проблемой для большого. На действительно больших таблицах ( > 1 Гб) для завершения ALTER TABLE, вероятно, потребуется несколько часов или даже дней. Более того, он решает только проблему обновления схемы, но как насчет сохраненных данных? Я также предлагаю подумать о макете физических данных, чтобы понять фактические препятствия, стоящие за этим подходом. Вся процедура может быть небезопасной, поэтому убедитесь, что у вас есть резервные копии.
Решения:
- скопировать и переименовать: http://www.rndblog.com/don%E2%80%99t-alter-table-do-copy-and-rename/
- разбиение таблиц (разбиение на уровне приложений): http://www.mysqlperformanceblog.com/2006/10/08/small-things-are-better/
- разбиение (имеет некоторые ограничения)
Уровень 3 Проблема с обновлением схемы решается путем перемещения схемы на более высокий уровень. Решение, ограниченное схемой, несколько ограничено, главным образом потому, что оно отключает всю мощность за реляционной моделью. Гибридный подход может предлагаться как для быстрого обновления, так и для использования реляционной алгебры. Есть интересные статьи:
- http://backchannel.org/blog/friendfeed-schemaless-mysql
- http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html
Обратите внимание, что сложность процедуры обновления все еще существует, она просто перешла на уровень приложения. Существует много соответствующих сценариев, но я собираюсь описать одну гибридную систему, с которой я работаю уже несколько лет. Я могу описать модель данных как "сущности с отношениями". Отношения между объектами были представлены на уровне БД, сами сущности были сохранены как XML-блобы.
Эта система была зрелой и имела достаточно клиентов. Было много запросов функций, поэтому команды R & D и QA были немного подчеркнуты. Первоначально процедура обновления была реализована как автономное приложение Java, которое считывало XML-фрагменты из БД, обновляя его с помощью DOM API и записывая его обратно в БД. Фактический подход выглядит довольно просто, но есть несколько скрытых проблем:
- логика обновления может быть несколько ошибочной, поэтому есть возможность написать неправильные XML-данные, значительно увеличивающие время простоя для клиента
- может потребоваться некоторое время для чтения-преобразования-записи 1-2GB XML файлов.
- все шаги процедуры обновления должны быть покрыты автоматическими тестами (я бы сказал, что CI является ДОЛЖНЫ)
- скрытые сбои могут быть найдены через день или два, поэтому резервные копии больше не полезны, поскольку новые данные вставлены
- код обновления может стать немного грязным, особенно если вы хотите/нуждаетесь в обновлении между сборками (нормальное требование для любой гибкой команды).
Я попытался смягчить все потенциальные риски, используя более строгие определения процедуры обновления, правила проверки и обширные тесты, выполненные системой CI для реальных данных (собранных для всех клиентов). Я был удивлен, увидев, что некоторые шаги терпят неудачу из-за старых проблем, появившихся давным-давно старыми сценариями обновления. Для устранения скрытых проблем были разработаны отдельные этапы обновления. Была также проведена определенная оптимизация для уменьшения времени обновления до разумных 20-30 минут. Все остальное выполнило консоль на основе прогресса.
Быстрое примечание: любой конечный пользователь стремится увидеть прогресс для любой длительной ( > 2 мин) операции. Пожалуйста, не забудьте реализовать такое "удовольствие".
Первоначально версия БД хранилась в отдельной таблице. Пожалуйста, не используйте этот подход, потому что гораздо лучше иметь сущности, версированные отдельно, и избегать полной блокировки БД во время обновления.
Покажет одну процедуру обновления в качестве примера (все шаги проверки и проверки скрыты за логикой обработки <build/>
и <version/>
). '-' означает меньше, '*' - любая сборка
<?xml version="1.0"?>
<upgrade>
<version name="-7.4">
<build name="*">
<script class="upgrade.version7.Replace...Script"/>
<script class="upgrade.version7.Update...Script"/>
<!-- 5 scripts skipped -->
</build>
</version>
<version name="-7.6">
<build name="*">
<script class="core.DatabaseUpdateVersion" version="7.6.48"/>
</build>
</version>
<version name="7.6">
<build name="*">
<script class="upgrade.version7.Update...Script"/>
<script class="core.DatabaseUpdateVersion" version="8.0.40"/>
<!-- 7 scripts skipped -->
</build>
</version>
<version name="8.0">
<build name="-53">... </build>
<build name="+52">... </build>
</version>
<version name="8.1">
<build name="-8"> ... </build>
<build name="-9">...</build>
<build name="-26">...</build>
<build name="-40">...</build>
<build name="-45">...</build>
<build name="-56">...</build>
<build name="-61">...</build>
<build name="-63">...</build>
<build name="-64">...</build>
<build name="-68">...</build>
<build name="-69">...</build>
<build name="-77">...</build>
<build name="-79">...</build>
<build name="-80">...</build>
<build name="-86">...</build>
<build name="-88">...</build>
<build name="-89"> ... </build>
</version>
<version name="8.2">...</version>
</upgrade>
Каждый script представляет собой небольшую реализацию Java или Groovy (также использовался XSLT). Позже была разработана процедура понижения, но это совершенно другая история.
Уровень 4 Схема данных на прикладном уровне позволяет делать довольно много интересного. Например, можно заменить XML protobuf. Как обычно, есть несколько причин для этого (проще, быстрее и т.д.). Если вам не нравится концепция строителей, вы можете вместо этого использовать thrift.
В любом случае protobuf позволяет создавать обратную совместимую систему (с точки зрения хранимых данных) почти без головной боли. Хорошее преимущество, кстати. Имея совместимость с вашей системой, вы можете легко реализовать ленивое и полностью прозрачное обновление. Это может быть фоновый процесс или обновление по запросу и т.д. Хорошей новостью является нулевое время простоя, счастливые пользователи и возможность делать обновления чаще. Это означает, что вы можете быстро развиваться, оперативно реагировать на запросы клиентов, быть более успешными, другими словами.
Уровень 5 Извините, не для этого времени. Будьте осторожны с стратегиями обновления. Это qutie легко продать систему с определенной схемой и заблокировать себя. Нет новых функций - нет клиентов.
Простой, но чрезвычайно полезный контрольный список:
- Вы сможете быстро решить проблему, исходящую от клиента?
- Будет ли безопасно для клиента модернизировать систему (что, если это по крайней мере критически важно)?
- Сколько времени потребуется для определения проблемы?
- Есть ли автоматическая проверка?
Спасибо, что прочитали.