Какой лучший способ сохранить изменения в записях базы данных, которые требуют одобрения, прежде чем они будут видны?
Мне нужно сохранить внесенные пользователем изменения в определенную таблицу, но не показывать эти изменения, пока они не будут просмотрены и одобрены административным пользователем. Хотя эти изменения все еще находятся в состоянии ожидания, я все равно буду отображать старую версию данных. Каким будет наилучший способ хранения этих изменений в ожидании утверждения?
Я подумал о нескольких путях, но не могу понять, что является лучшим методом. Это очень маленькое веб-приложение. Один из способов - иметь таблицу PendingChanges, которая имитирует другую схему таблицы, а затем, как только изменение будет одобрено, я могу обновить реальную таблицу с информацией. Другой подход состоял бы в том, чтобы сделать какое-то рекордное управление версиями, где я храню несколько версий данных в таблице, а затем всегда извлекаю запись с наивысшим номером версии, который был отмечен как одобренный. Это ограничило бы количество дополнительных таблиц (мне нужно сделать это для нескольких таблиц), но потребовалось бы, чтобы я делал дополнительную обработку каждый раз, когда я вытаскиваю набор записей, чтобы убедиться, что я получу нужные.
Любой личный опыт с этими методами или другими, которые могут быть хорошими?
Обновление: просто чтобы уточнить, в этой конкретной ситуации меня не интересуют исторические данные. Мне просто нужно каким-то образом одобрить любые изменения, сделанные пользователем до того, как они начнут жить на сайте. Таким образом, пользователь отредактирует свой "профиль", а затем администратор просмотрит эту модификацию и одобрит ее. После утверждения это станет отображаемым значением, и старая версия не будет сохранена.
Кто-нибудь пробовал решение ниже, где хранятся ожидающие изменения из любой таблицы, которая должна отслеживать их как XML в специальной таблице PendingChanges? В каждой записи будет столбец, в котором указана таблица, в которую были внесены изменения, столбец, в котором может быть сохранен идентификатор записи, который будет изменен (если это новая запись), столбца datetime для хранения, когда это изменение было сделано, и столбец для хранения xml измененной записи (может быть, сериализовать мой объект данных). Поскольку мне не нужна история, после того, как было одобрено изменение, реальная таблица будет обновлена, и запись PendingChange может быть удалена.
Любые мысли об этом методе?
Ответы
Ответ 1
Размер - ваш враг. Если вы имеете дело с большим количеством данных и большим количеством строк, то с историей, смешанной с текущим, вы будете забивать вас. У вас также будут проблемы, если вы присоединитесь к другим данным, убедившись, что у вас есть правильные строки.
Если вам нужно сохранить исторические данные для отображения изменений с течением времени, я бы пошел с отдельной исторической таблицей, которая обновляет текущие реальные данные после ее утверждения. Это просто крутой уборщик.
Если у вас много типов данных, которые будут иметь этот механизм, но не должны содержать историческую запись, я бы предложил общую очередь для просмотра ожидающих элементов, например, хранимых как xml. Это позволит читать только одну таблицу администраторами и позволит вам легко добавить эту функциональность в любую таблицу в вашей системе.
Ответ 2
Определенно хранить их в основной таблице со столбцом, чтобы указать, одобрены ли данные или нет.
Когда изменение одобрено, копирование не требуется. Дополнительная работа по фильтрации несанкционированных данных - это то, что должны делать базы данных, когда вы об этом думаете. Если вы указали утвержденный столбец, это не должно быть слишком обременительным, чтобы делать правильные вещи.
Ответ 3
Я работаю в банковском домене, и у нас есть эта необходимость - изменения, сделанные одним пользователем, должны отражаться только после утверждения другим. Дизайн, который мы используем, ниже
- Основная таблица A
- Другая таблица B, в которой хранится измененная запись (и так точно аналогична первой) + 2 дополнительных столбца (FKey-C и код для указания вида изменений)
- Третья таблица C, в которой хранятся все такие записи, требующие утверждения
- Четвертая таблица D, в которой хранится история (вам, вероятно, это не нужно).
Я рекомендую этот подход. Он очень грамотно обрабатывает все сценарии, включая обновления и удаления.
Ответ 4
Учитывая движение за соблюдение SOx, которое было выпущено перед лицом большинства компаний, торгуемых на публике, у меня был довольно много опыта в этой области. Обычно я использую отдельную таблицу с отложенными в ожидании изменениями с каким-то столбцом флага. Лицо, ответственное за администрирование этих данных, получает список ожидающих изменений и может принять или принять. Когда часть данных принимается, я использую триггеры для интеграции новых данных в таблицу. Хотя некоторым людям не нравится метод триггера, и он скорее кодирует это в хранимые procs. Это хорошо работает для меня, даже в довольно больших базах данных. Сложность может немного затрудниться, особенно при работе с ситуацией, когда одно изменение напрямую конфликтует с другим изменением и каким приказом обрабатывать эти изменения. Таблица, содержащая данные запроса, никогда не сможет быть удалена, поскольку она держит "хлебные крошки", так сказать, которые требуются в случае необходимости отследить, что произошло в конкретной ситуации. Но в любом подходе необходимо оценивать риски, например, то, что я упомянул в конфликтующих данных, и уровень бизнес-логики должен быть установлен для определения процесса в этих ситуациях.
Мне лично не нравится один и тот же метод таблицы, потому что в случаях постоянно меняющихся хранилищ данных эти дополнительные данные в таблице могут излишне заглушить запрос в таблице и потребовать гораздо больше деталей как вы индексируете таблицу и планы выполнения.
Ответ 5
Я бы создал таблицу с флагом и создал вид, похожий на
CREATE OR REPLACE VIEW AS
SELECT * FROM my_table where approved = 1
Он может помочь разделить зависимости между объявлением и запросами. Но может быть, это не лучшая идея, если нужно делать обновления для представления.
Перемещение записей может иметь некоторые соображения производительности. Но разделенные таблицы могли бы делать что-то совершенно похожее.
Ответ 6
Поскольку это веб-приложение, я собираюсь предположить, что есть больше чтений, чем пишет, и вы хотите что-то достаточно быстро, и ваше разрешение конфликтов (т.е. отсутствие одобрения заказа) приводит к такому же поведению - последнее обновление тот, который используется.
Обе стратегии, которые вы предлагаете, схожи, они оба держат одну строку в наборе изменений, должны иметь дело с конфликтами и т.д., единственная разница заключается в том, хранить ли данные в одной таблице или двух. Учитывая сценарий, две таблицы выглядят лучшим решением по соображениям производительности. Вы также можете решить эту проблему с помощью одной таблицы и просмотреть последние одобренные изменения, если ваша база данных поддерживает ее.
Ответ 7
Еще одна идея состоит в том, чтобы иметь три таблицы.
- Одна из основных таблиц для хранения исходных данных.
- Вторая будет содержать предлагаемые данные.
- Третий будет содержать исторические данные.
Этот подход дает вам возможность быстро и легко откатываться назад, а также дает вам контрольный журнал, если вам это нужно.
Ответ 8
Я думаю, что второй способ - лучший подход, просто потому, что он лучше масштабируется для нескольких таблиц. Кроме того, дополнительная обработка будет минимальной, так как вы можете создать индекс в таблице на основе "одобренного" бита, и вы можете специализировать свои запросы, чтобы либо получить одобренные (для просмотра), либо неутвержденные (для утверждения) записи.