Дизайн базы данных для моментального момента "моментального снимка" данных?

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

Это даст пользователю возможность вернуться назад и посмотреть, как выглядели их данные в прошлом.

Предположим, что данные, "снятые снимок", сложны и включают в себя объединения нескольких таблиц.

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

EDIT: Спасибо за ваши ответы. Ответ на 6NF является убедительным, как и предложение де-нормализовать данные моментальных снимков из-за его простоты.

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

Ответ 1

Мы сделали это один раз, создав отдельные таблицы базы данных, содержащие данные, которые мы хотели сделать с моментальным снимком, но денормализованные, т.е. каждая запись содержит все необходимые данные, а не ссылки на id, которые могут или не могут существовать. Он также добавил дату для каждой строки.

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

Таким образом, было бы тривиально написать то, что восстановило данные пользователей до определенного момента.

Если у вас есть таблица:

Пользователь:

id, firstname, lastname, department_id

Департамент:

id, name, departmenthead_id

ваш снимок таблицы пользователя может выглядеть так:

user_id, user_firstname, user_lastname, department_id, department_name, deparmenthead_id, deparmenthead_firstname, departmenthead_lastname, snapshot_date

и запрос, похожий на

INSERT INTO usersnapshot
SELECT user.id AS user_id, user.firstname AS user_firstname, user.lastname AS user_lastname,
department.id AS department_id, department.name AS department_name
departmenthead.id AS departmenthead_id, departmenthead.firstname AS departmenthead_firstname, departmenthead.lastname AS departmenthead_lastname,
GETDATE() AS snapshot_date
FROM user
INNER JOIN department ON user.department_id = department.id
INNER JOIN user departmenthead ON department.departmenthead_id = departmenthead.id

Это гарантирует, что каждая строка моментального снимка верна для этого момента времени, даже если отдел или глава отдела изменились за это время.

Ответ 2

Это НЕ легко.

В основном вы запрашиваете временную базу данных (то, что дата Кристофера называет шестую обычную форму или 6NF).

Для того чтобы быть 6NF, схема также должна быть 5NF и, в основном, для каждой точки привязки, вам необходимо прикрепить временной диапазон, для которого применима привязка к этому значению. Затем в соединениях соединение должно включать только строки, находящиеся в пределах рассматриваемого временного диапазона.

Временное моделирование сложно - это то, что 6-й адрес нормальной формы - и не поддерживается в текущих RDBMS.

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

В принципе, везде, где у вас есть отношение ( "ted владеет сертификатом запаса GM с идентификатором 789" ), вы добавляете время: "ted владеет сертификатом запаса GM с идентификатором 789 сейчас", чтобы вы могли одновременно сказать: "fred владеет сертификат запаса GM с номером 789 с 3 февраля 2000 года по вчерашний день". Очевидно, что эти отношения много-ко-многим, (ted может владеть более чем одним сертификатом сейчас и более чем один за всю свою жизнь), и fred может владеть владельцем сертификата сейчас.)

Итак, у нас есть таблица владельцев, таблица сертификатов акций и таблица "многие ко многим", которая связывает владельцев и сертификаты по id. Для таблицы "многие-ко-многим" мы добавляем start_date и end_date.

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

Если владелец находится, очевидно, может измениться независимо от владения акциями; ted может жить в Небраске, покупать 10 акций, получать дивиденды, что налоги в Небраске, переезд в Неваду, продает 5 акций в fred, покупают еще 10 акций.

Но для нас он может переехать в Небраску в какое-то время, купить 10 акций в какое-то время, получить дивиденды в какое-то время, которые неграбские налоги, переехать в Неведу в какое-то время, продать 5 акций Фреду в какой-то момент, купите еще 10 акций в течение некоторого времени.

Нам нужно все это, если мы хотим рассчитать, какие налоги необходимы в Небраске и в штате Невада, объединяясь на совпадающих/перекрывающихся диапазонах дат в person_stockcertificate и person_address. Адрес человека уже не является индивидуальным, он один-ко-многим, потому что он адресуется во временном диапазоне.

Если ted покупает десять акций, мы моделируем событие покупки с одной датой покупки или добавляем date_bought к каждой акции? В зависимости от вопроса нам нужна модель для ответа.

Ответ 3

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

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

По какой-то логике вы можете воссоздать то, как выглядели данные в данный момент времени. Для простого способа установить это в Sybase см.: http://www.theeggeadventure.com/wikimedia/index.php/Sybase_Tips#create_.27audit.27_columns

Если вам нужно сделать много исторических снимков, вы можете сохранить данные в одной таблице. В принципе, создайте два столбца - добавленный и удаленный столбец. Недостатком является то, что для каждого запроса вы должны добавить предложение where. Конечно, вы можете создать представление, в котором отображаются только активные записи. Это становится немного сложнее, если у вас есть нормализованная база данных с несколькими таблицами, все с историей.

Однако он работает. У вас просто есть "добавленные" и "удаленные" столбцы для каждой таблицы, а затем ваш запрос имеет момент времени интереса. Всякий раз, когда данные изменяются, вы должны скопировать текущую строку и пометить ее как удаленную.

Ответ 4

Используйте Триггеры журнала

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

Ответ 6

Oracle из версии 9i имеет технологию Flashback, которая в Oracle 10g и 11g значительно улучшена, и вы можете увидеть состояние своей базы данных в любой момент истории, если вы включили flashback.

Проверьте этот документ: Обзор Flashback

Ответ 7

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

Чтобы получить снимок ваших данных, просто учтите все журналы, созданные до желаемого момента времени. Затем вы выполняете "воспроизведение" этих журналов, чтобы получить реальную базу данных с восстановленными данными.

Как получить доступ и "воспроизвести" журналы, зависит от конкретного продукта RDBMS, который вы используете.

Другая возможность - использовать временные базы данных. Они имеют встроенные временные аспекты и позволяют "вернуться назад". Ищите "Oracle Flashback Technology", например. http://www.stanford.edu/dept/itss/docs/oracle/10g/appdev.101/b10795/adfns_fl.htm#ADFNS1008

Ответ 8

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

Затем вы можете сделать резервную копию момента времени.

Это плохое решение.

Что именно хочет ваш клиент? Это для аналитических целей (т.е. Вопросы похожи на то, сколько заказов у ​​нас было две недели назад)? Потому что именно эта проблема решает проблемы с хранилищем данных.

Ответ 9

Возможно, рассмотрите возможность использования решения NoSql, такого как MongoDB, для агрегирования всех ваших реляционных данных в один документ, а затем сохраните этот документ с меткой времени или номером версии. Такие решения, как Kafka-Connect или Oracle Golden Gate, упрощают реляционные данные трубопроводов в хранилища NoSql.