Ведение истории изменений страниц. Немного похоже на то, что делает SO для ревизий

У меня есть система CMS, которая хранит данные в таблицах вроде этой:

Entries Table
+----+-------+------+--------+--------+
| id | title | text | index1 | index2 |
+----+-------+------+--------+--------+

Entries META Table
+----+----------+-------+-------+
| id | entry_id | value | param |
+----+----------+-------+-------+

Files Table
+----+----------+----------+
| id | entry_id | filename |
+----+----------+----------+

Entries-to-Tags Table
+----+----------+--------+
| id | entry_id | tag_id |
+----+----------+--------+

Tags Table
+----+-----+
| id | tag |
+----+-----+

Я пытаюсь реализовать систему исправлений, немного похожую на SO. Если бы я просто делал это для таблицы записей , я планировал просто хранить копии всех изменений в этой таблице в отдельной таблице. Поскольку я должен сделать это как минимум для 4 таблиц (таблица TAGS не требует изменений), это совсем не похоже на элегантное решение.

Как бы вы это сделали?

Обратите внимание, что мета-таблицы смоделированы в EAV (значение-атрибута объекта) .

Заранее благодарю.

10
задан Jacob 25 August 2010 в 19:04
поделиться

3 ответа

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

взяв вашу таблицу записей в качестве примера

Entries Table
+----+-------+------+--------+--------+
| id | title | text | index1 | index2 |
+----+-------+------+--------+--------+

превращается в

entries             entries_data
+----+----------+   +----------+----+--------+------+--------+--------+
| id | revision |   | revision | id |  title | text | index1 | index2 |
+----+----------+   +----------+----+--------+------+--------+--------+

, чтобы запросить

select * from entries join entries_data on entries.revision = entries_data.revision;

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

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

8
ответ дан 3 December 2019 в 22:34
поделиться

Взгляните на этот вопрос: Как управлять версиями записи в базе данных

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

6
ответ дан 3 December 2019 в 22:34
поделиться

Для одного из наших проектов мы пошли следующим путем:

Entries Table
+----+-----------+---------+
| id | date_from | date_to |
+----+--------_--+---------+

EntryProperties Table
+----------+-----------+-------+------+--------+--------+
| entry_id | date_from | title | text | index1 | index2 |
+----------+-----------+-------+------+--------+--------+

Довольно сложно, но позволяет отслеживать полный жизненный цикл объекта. Таким образом, для запроса активных сущностей мы собирались:

SELECT 
entry_id, title, text, index1, index2
FROM
Entities INNER JOIN EntityProperties
ON Entities.id = EntityProperties.entity_id
AND Entities.date_to IS NULL
AND EntityProperties.date_to IS NULL

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

Общий недостаток любой подобной попытки очевиден — вам нужно написать тонны TSQL, где неверсионные БД будут использовать что-то вроде select A join B.

1
ответ дан 3 December 2019 в 22:34
поделиться
Другие вопросы по тегам:

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