Ведение истории изменений страниц. Немного похоже на то, что 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. Если бы я делал это только для Entries Table, я планировал просто хранить копии всех изменений в этой таблице в отдельной таблице. Поскольку я должен сделать это как минимум для 4 таблиц (таблица TAGS не требует изменений), это совсем не похоже на элегантное решение.

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

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

Заранее спасибо.


person Frankie    schedule 14.08.2010    source источник


Ответы (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;

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

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

person ejrowley    schedule 17.08.2010
comment
Почему кто-то проголосовал против ответа Эйроули? Я все еще ищу наилучшее возможное решение и буду отдавать должное там, где это необходимо. Но это швы как жизнеспособное решение, не так ли? - person Frankie; 18.08.2010
comment
даже если ваша система не совсем то, что я собираюсь делать; Я считаю, что схема таблиц в Эдварде Вильямсе является более точным ответом с точки зрения как производительности, так и доступности; Я считаю, что ваш ответ находится в строке ответа Эдвардса с лучшими схемами, поэтому я принимаю его. Спасибо! - person Frankie; 26.08.2010

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

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

person Community    schedule 14.08.2010
comment
ваш ответ очень интересен. Специально Media Wiki схема базы данных. Он создает дополнительный уровень table -> revisions keys -> revisions data, сохраняя data table как можно меньше, обеспечивая при этом историю изменений и возможность перемещаться между ревизиями назад и вперед, как это делает SO. Мне все еще интересно, есть ли более элегантный способ его хранения. - person Frankie; 19.08.2010

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

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.

person Vitaly    schedule 26.08.2010