Задать вопрос

Как организовать систему обновлений БД?

Приведу простой пример (реальный пример по работе со steam - steamworks). Вместо БД может быть любой файл - это не суть.

Есть игра. Игра состоит из исполняемого файла (exe) и файла базы данных.
Exe файл содержит код, работающий с БД. В БД хранятся данные, в том числе сохранение игрока.

Игра обновляется. При каждом обновлении игроку закачивается новый exe файл. Файл БД не закачивается т.к. он хранит сохранения игрока и его перезапись приведет к потере сохранений.

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

Было решено фиксировать версию БД и хранить информацию о версии в таблице/поле в этой же БД.
Изначально БД версии 1.0.

Обновление игры содержит патч, выполняющийся автоматически при запуске exe файла. Патч обновляет БД.
Патч содержит команды вида версия БД - действие
1.0 добавь поле количество монет
1.0 запиши версию БД 1.01

Патч выполнил эти команды. В БД есть поле с количеством монет и версия БД 1.01. Exe файл работает - всё хорошо.

В очередном обновлении было принято решение добавить новый параметр - количество жизней.
Патч содержит команды
1.0 добавь поле количество монет
1.0 запиши версию БД 1.01
1.01 добавь поле количество жизней
1.01 запиши версию БД 1.02

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

---
Итого мы видим, что с каждым патчем БД меняет свою структуру. И изменения должны быть последовательные - т.е. нельзя выполнить команды 1.01 до 1.0 т.к. изменения могут удалять поля, переименовывать их несколько раз и т.д.

Проблема в том что при ошибке, нарушении выполнения хоть одной команды мы теряем возможность продолжения обновления БД. В идеале ошибки быть не может, но на практике такое случается.
И exe файл не может работать с БД т.к. она не была обновлена для работы с этим файлом.

Одно из решений - при ошибке работы с БД (что то там не обновилось) загрузить чистую (актуальную) версию базы.
Это возможно. Но тогда мы сотрем сохранения игрока.

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

Как решить эту проблему?
  • Вопрос задан
  • 89 просмотров
Подписаться 1 Средний Комментировать
Пригласить эксперта
Ответы на вопрос 4
VoidVolker
@VoidVolker
Dark side eye. А у нас печеньки! А у вас?
Это называется "Миграция БД". Для этого уже давно есть готовые инструменты, которые уже много лет применяются везде.
Ответ написан
Комментировать
@elderl
Последовательные обновления: фиксируется текущее состояние (BACKUP DATABASE), обновляется, при необходимости восстанавливается сохранённое предыдущее. (Старый вариант обновления Windows)
Кумулятивное обновление.
Ответ написан
Комментировать
Если это какая-то игра, то должно быть несколько файлов сохранений и меняться они должны не автоматически при установке обновления, а только при обращении.

Менять сохранение нужно только тогда, когда пользователь явно попросит загрузить сохранение из старой версии. Предварительно напомнить пользователю сделать резервную копию (либо вообще сделать её автоматом)

Если возникла ошибка - придётся смириться. Пусть пользователь скинет пример сохранения с которым произошла проблема - возможно исправишь в следующей версии.
Если посмотришь на практику - так все и поступают.

И по возможности лучше стараться делать обратно-совместимые форматы данных.

И раз загрузка файлов cо старых версий - это вполне обычный сценарий работы, то его обязательно нужно покрывать тестами.

В остальном всё так, как написал в вопросе
Ответ написан
Комментировать
mayton2019
@mayton2019
Bigdata Engineer
Хорошая архитектура БД должна быть толерантной миграции версий. Например
если состояние пользователя хранится в XML то можно договориться что поле
"coins" (количество монет имеет дефолтное значение = 0) и не требует
принудительного обновления всех записей. Фактически это поле сохранится
в save файл только когда игрок заработает не нулевое число coins.

<player name="Иванов" coins=12 />
<player name="mayton" />


При моем подходе никакая миграция БД не нужна.

Мне эта модель также напоминает "schema evolution" из области BigData.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы