Подтвердить что ты не робот

Правильная стратегия для базы данных контроля версий

Я читаю этот blog, и у меня есть вопрос относительно 5 сообщений, которые написаны. Из того, что я понимаю, вы создаете на большой базовой линии script, которая включает в себя все записи SQL DDL. После этого вы отслеживаете каждое изменение в отдельных сценариях.

Однако я не понимаю, как имя файла script может быть связано с конкретной сборкой вашего приложения? Он говорит, что если пользователь сообщает об ошибке в 3.1.5.6723, вы можете повторно запустить скрипты для этой версии. И вы могли бы отслеживать изменения в таблице и т.д. В собственном файле или иметь все DLL-изменения в том же файле script, а затем просматривать и т.д. В собственных файлах, как он говорит?

4b9b3361

Ответ 1

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

Можно создать матрицу компетенций программиста на основе подхода к обновлению:

  • Уровень 0: нет обновлений вообще. Клиенты испуганы и перемещают данные вручную, используя пользовательский интерфейс, предоставляемый приложением или сторонними решениями управления БД (поверьте, это действительно возможно).
  • Уровень 1: для обновления дампа базы данных существует script. Клиенты чувствуют себя в безопасности, но они исправят крошечные и очень раздражающие проблемы в течение следующих 1-2 лет. Система работает, но никаких изменений не было.
  • Уровень 2: изменение таблицы. Чудовищное время простоя, особенно в случае возникновения проблемы при обновлении. Огромные проблемы и практически никаких гарантий для получения 100% безопасного результата. Преобразование данных управляется с помощью buggy script. Клиенты не довольны.
  • Уровень 3: схема без схемы: простоя в течение одного-двух часов, чтобы позволить скриптам с ошибками переводить конфигурацию в БД (этот шаг может повредить БД во многих случаях). У парней поддержки все запасы кофе полностью исчерпаны.
  • Уровень 4: ленивые прозрачные обновления: нулевой простоя, но все же возможны некоторые проблемы. Клиенты почти счастливы, но все же помнят предыдущий опыт.
  • Уровень 5: Идеальная архитектура, не требуется явное обновление. Полное счастье. Клиенты не знают, что такое процедура обновления. Разработчики продуктивны и спокойны.

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

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

Уровень 0 и уровень 1 Оба случая очевидны и глупы. Никто не должен этого избегать.

Уровень 2 Изменение не так уж плохо для небольших таблиц, но это может быть проблемой для большого. На действительно больших таблицах ( > 1 Гб) для завершения ALTER TABLE, вероятно, потребуется несколько часов или даже дней. Более того, он решает только проблему обновления схемы, но как насчет сохраненных данных? Я также предлагаю подумать о макете физических данных, чтобы понять фактические препятствия, стоящие за этим подходом. Вся процедура может быть небезопасной, поэтому убедитесь, что у вас есть резервные копии.

Решения:

Уровень 3 Проблема с обновлением схемы решается путем перемещения схемы на более высокий уровень. Решение, ограниченное схемой, несколько ограничено, главным образом потому, что оно отключает всю мощность за реляционной моделью. Гибридный подход может предлагаться как для быстрого обновления, так и для использования реляционной алгебры. Есть интересные статьи:

Обратите внимание, что сложность процедуры обновления все еще существует, она просто перешла на уровень приложения. Существует много соответствующих сценариев, но я собираюсь описать одну гибридную систему, с которой я работаю уже несколько лет. Я могу описать модель данных как "сущности с отношениями". Отношения между объектами были представлены на уровне БД, сами сущности были сохранены как 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 легко продать систему с определенной схемой и заблокировать себя. Нет новых функций - нет клиентов.

Простой, но чрезвычайно полезный контрольный список:

  • Вы сможете быстро решить проблему, исходящую от клиента?
  • Будет ли безопасно для клиента модернизировать систему (что, если это по крайней мере критически важно)?
  • Сколько времени потребуется для определения проблемы?
  • Есть ли автоматическая проверка?

Спасибо, что прочитали.

Ответ 3

Изменения в таблицах и представлениях не будут сохраняться в их собственном файле. Для каждого изменения вы создадите новое изменение script. Поэтому, если вы измените таблицу "Х" 5 раз, у вас будет 5 разных сценариев изменений для каждого из этих изменений.

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

db_scripts/

2012-01-01 baseline.sql:
create table book (
   book_name varchar(100),
   author_name varchar(100)
)
--- label version_1.0

2012-02-01 add_publisher.sql:
alter table book add column publisher varchar(100)
--- label version_1.1

2012-03-01 add_publish_date.sql:
alter table book add column publish_date datetime
--- label version_1.2

2012-04-01 add_rating.sql:
alter table book add column rating integer
--- label version 1.3

Теперь скажем, что вы хотите воссоздать базу данных с версии 1.2:

  • вы должны синхронизировать код с меткой version_1.2
  • запустите скрипты в порядке выполнения baseline.sql, add_publisher.sql, add_publish_date.sql

Ответ 4

Вместо Liquibase вы можете использовать Flyway (http://flywaydb.org/), который позволяет вам создавать собственные сценарии SQL для обновления/понижения. Это обеспечивает большую гибкость, а также работает для представлений и хранимых процедур.

Liquibase требует от вас изменения схемы с использованием собственного языка на основе XML, который может быть несколько ограниченным.

Ответ 5

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

Здесь как работает запуск:

  • проверяет запись DB_VERSION в базе данных,
  • находит обновления > текущая версия; возможно, по коду.
  • запускает каждое применимое "обновление", script или программные действия.
  • DB_VERSION обновляется после каждого, поэтому повторный запуск отказа может быть повторно запущен.

Пример:

  • Найти DB_VERSION в настоящее время = 789;
  • сложный код или большая длинная цепочка IF, находит обновления 790 и выше.
  • update # 790, обновить таблицы клиентов и учетных записей;
  • обновление # 791, обновить таблицу электронной почты;
  • update # 792, реструктурировать таблицу заказов;
  • версия базы данных сейчас = 792.

Есть несколько предостережений. Это работает достаточно хорошо; люди утверждают, что он должен быть на 100% надежным, но это не так.

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

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

public void runDatabaseUpgrades() {
    if (version < 790) {
      // upgrade Customer and Account tbls
      version = 790;
    }
    if (version < 791) {
      // upgrade Email tbl
      version = 791;
    }
}