Задать вопрос
@historydev
long long long long long .... int

Как вести историю работы с записями во всех таблицах для всех пользователей?

Я хочу отслеживать кто и когда: создаёт, изменяет, удаляет сущности.
- Если оставить текущее решение, гор копи-паста не избежать.

Текущая схема prisma (только затронутые поля):
model UserAccount {
  id Int @id @unique @default(autoincrement()) @map("id")

  creatorAccount UserAccount? @relation("CreatorAccount", fields: [createdBy], references: [id])
  editorAccount  UserAccount? @relation("EditorAccount", fields: [editedBy], references: [id])
  deleterAccount UserAccount? @relation("DeleterAccount", fields: [deletedBy], references: [id])

  isDeleted      Boolean   @default(false) @map("is_deleted")
  deletedBy      Int       @map("deleted_by")
  deletedAt      DateTime? @map("deleted_at") @db.Timestamptz()
  deletionReason String?   @map("deletion_reason") @db.VarChar(128)

  createdUsers UserAccount[] @relation("CreatorAccount")
  editedUsers  UserAccount[] @relation("EditorAccount")
  deletedUsers UserAccount[] @relation("DeleterAccount")

  createdBy Int?      @map("created_by")
  createdAt DateTime @map("created_at") @db.Timestamptz()

  editedBy Int?      @map("edited_by")
  editedAt DateTime? @map("edited_at") @db.Timestamptz()

  @@map("user_accounts")
}


Решил идти в сторону отдельной таблицы (или множества) для истории.
Вижу 2 варианта:
1. Самый удобный как по мне, но наименее компактный и трудно-поддерживаемый - по таблице с историей на каждую таблицу.
2. Одна общая таблица с полями oldData (JSON), newData (JSON).

И есть такой:
- Массив как поле у записи.

Как поступают в таком случае?

P.S: Уровень БД.
  • Вопрос задан
  • 256 просмотров
Подписаться 2 Простой 15 комментариев
Помогут разобраться в теме Все курсы
  • OTUS
    PostgreSQL. Advanced
    4 месяца
    Далее
  • Учебный центр IBS
    QPT PostgreSQL 16. Оптимизация запросов
    1 неделя
    Далее
  • Слёрм
    PostgreSQL База
    4 недели
    Далее
Решения вопроса 2
Vamp
@Vamp
У себя на проекте я сделал по вашему второму варианту. Колонки date, user_id, ip, table, data. Где data - json структура вида {"field_name": {"old": "было", "new": "стало"}}

Затем в отдельном разделе в админке этот лог можно смотреть в удобном виде, фильтровать, выгружать для аудита в сторонних программах.
Ответ написан
@rPman
Есть один способ (видел давно и позже в другом проекте использовал), он почти универсальный, обладает кучей достоинств по возможностям аналитики, но повышает требования к месту на диске (и незначительно нагрузку на базу, но это в зависимости от типа аналитики, т.е. необходимости создания индексов). Например позволяет восстанавливать состояние базы на указанный момент времени (вырожденный случай но да). И главное, почти полностью автоматическое создание этой архивной базы (и с оговорками обновление при изменениях), без необходимости ковыряться в ее DDL.

Создание полной копии записи базы с каждым изменением, проводимым в них. Создается новая база данных (или в той же самой базе, но имена таблиц снабжаются унифицированным преффиксом), настоятельно рекомендуется отдельное хранилище для таблиц (отдельный диск еще лучше), но не другой сервер. Каждая архивная таблица структурно (список полей и их типы) без индексов и информации об ограничениях (все поля могут быть null, кстати тут есть оговорка, если оригинальные таблицы не будут содержать null то возможна значительная оптимизация по размеру архивных таблиц) должна дублировать оригинальные, с добавлением полей - тип действия (insert/update/delete), время, пользователь или ссылка на таблицу архива сессий авторизации (в этой таблице время, пользователь и информация о его сессии например ip,..). Каждая оригинальная таблица должна быть снабжена тригером на insert/update/delete который будет дублировать предыдущее значение (или сохранять новое - оба варианта подходят но я рекомендую второе) в архивной таблице, в простом варианте дублируя всю запись, но в расширенном варианте возможно сохранение только изменившихся колонок (сравнением new и old) а для остальных полей и для delete оставлять нули и primary key.

Все можно сделать скриптами, которые анализируют структуру базы и создают (пересоздают) тригеры и таблицы.
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

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