Jurnal modificări date

Salutare :smiley:
La proiectul la care lucrez acum, am întâmpinat o “mică” problemă, așa că am decis să apelez la ajutorul vostru.

Am mai multe formulare prin care pot adăuga și edita informațiile existente. Ideea de bază este că mi-aș dori să am o evidență la absolut tot ce se adaugă sau se modifică, cu alte cuvinte un log a activității. Cel mai bun exemplu pe care l-am găsit este în Zoho CRM (am adăugat o poză mai jos).

Dilema cea mare este că nu îmi dau seama care este cel mai eficient mod de a stoca aceste informații în baza de date. Precizez că am nevoie de aceste date doar pentru a afișa acest jurnal, nu o să le mai folosesc și în alte părți.

1 Like

Există multe soluții faine, unul din ele e https://getstream.io.

1 Like

Daca esti pe mysql 5.7, poti sa incerci noua coloana de tip json. E pentru date cam de genul asta. Niste articole despre asta: unu, doua, plus un video cu un tip de la Oracle care vorbeste despre asta (partea de indecsi este extrem de interesanta).

2 Likes

Depinde mult de ce tech stack folosesti. Daca ai un CRM care iti impune o anumita structura a tabelelor din DB, o sa-ti fie mai greu decat daca folosesti ceva gen Django/Laravel etc. unde tu decizi ce tabele ai si cum.

O strategie OK este urmatoarea: pentru fiecare entitate X sa ai doua tabeluri Xs si XEvents. X este tableful standard pe care l-ai avea, iar XEvents este un jurnal al fiecărei modificări din X. Ideal e sa pui modificări semantice, la nivelul serviciului care controlează entitatea. De exemplu, pentru o sesiune ai avea evenimente de genul creat, expirat, ok la cookies, logout etc. Asadar nu modificari de genul “câmpul Z devine 10”. Ca model e folositor sa ai un id, timestamp, id-ul entității care este vizata și o coloana Json cu date despre schimbare. Un index pe (entity_id, timestamp) e folositor de asemena.

1 Like

Mulțumesc pentru sugestie. Am încercat până acum să nu externalizez niciun serviciu din diferite motive. Nu pare o treabă atât de complicată ținând cont că nu gestionez un volum mare de informații.

PS: Mi-a plăcut modul de a trimite id-ul “picture:10”, “activity:10”. Asta m-a făcut să regândesc o parte din sistemul de notificări.

Este o idee chiar bună ținând cont că nu o să am niciodată nevoie de a face o interogare pe acea coloana. Nu îmi pot face griji cu privire la timpul de execuție.

Mulțumesc pentru sfat.

Este o mică aplicație făcută de mine. Are la bază CodeIgniter, deci în teorie nu sunt limitat de o anumită structură a tabelelor.

Cât ține strategia ta, mi-aș dori să o explici mai detaliat să ma asigur că înțeleg ceea ce trebuie.

Am sa incerc sa scriu un articol pe blog despre treabă asta, pentru că un comentariu nu e cel mai bun mediu ptr elaborarea de tipul asta. Un mic tutorial. Revin de indata ce e gata.

1 Like

Nu stiu daca ajuta, caci nu am avut timp sa studiez mai indeaproape.

Insa mi s-a parut interesant ce face:

Salutare!

Noi avem creata o astfel de situatie (ecommerce), unde problema este foarte simpla si anume.

  1. creat tabela (user_logs): user_id (INT, user-ul logat), description (varchar 200, scriem log-ul), data_up (DATETIME)
  2. creat clasa separata cu o serie de functii:
    2.1 add_log() -> user_id (luat din sesiunea user-ului logat), description: 2 variante: adaugat String in limba romana sau parametrizat cu un lang_event_id

Asa scriem log-uri pe fiecare user la operatiile necesare.
Apoi un modul separat care facem doar afisarea, dupa bunul plac.

Succes!

Ce parere aveti de urmatoarea abordare? Triggeri la nivelul bazei de date care se declanseaza “before update”, prin care se salveaza inregistrarile intr-un tabel separat? O implementare de genul asta:

In SQL Server am implementat cu temporal tables.

How does temporal work?

System-versioning for a table is implemented as a pair of tables, a current table and a history table. Within each of these tables, the following two additional datetime2 columns are used to define the period of validity for each row.

The current table contains the current value for each row. The history table contains each previous value for each row, if any, and the start time and end time for the period for which it was valid.

https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables

1 Like

Salutare,

Event Sourcing este un pattern destul de vechi si des folosit in multe aplicatii enterprise. Atunca o privire si vezi daca ti se pare ok pentru ce ai tu nevoie.

Also, daca o tabela mysql pentru stocat evenimentele respective ti se pare o solutie ne-eleganta(nu este, dar in fine, alta discutie), poti implementa ca solutie de stocare elasticsearch, ca apoi sa accesezi usor respectivul endpoint(chiar restful).

4 Likes

Nu detaliez pana la capat, insa notez cateva observatii:

  1. Triggerele sunt bune in development mode / MVP mode, etc, in cazurile in care nu se cere performanta si consistenta 100%. E de retinut faptul ca pt fiecare insert in baza de date, triggerele asociate vor incetini performanta sistemului, practic pe cel care face operatia de insert il costa si asteptatul dupa logarea diverselor date aditionale Si odata pornit bulgărele de triggere, se vor dori tot mai multe.
  2. Ca preferință personală, și eu as merge pe ideea lui @tacheshun cu evenimentele. În ideea în care am un RESTful API care primește cereri de a loga diverse evenimente, iar acesta folosește 204 trick pentru a nu aștepta după răspunsul sistemului de logare. Se poate lansa comanda de logare fie din controllerul care a persistat informația inițială, fie din client (ex. browser). Aici strategia depinde de proiect.
  3. Pentru a nu încărca sistemul cu prea multe moduri de persistare, un tabel cu loguri e o bună soluție de start. Eu aș face 4 coloane: user_id (cine a declansat evenimentul), category (de ce fel e evenimentul), details (json cu datele), occurred_at (cand s-a petrecut). In functie de ati ales la itemul 2 ca declansator (controllerul sau clientul) data poate diferi cu cateva ms.
8 Likes

@liviuroman IDK cat mai este relevant, dar am terminat articolul pe care-l promisesem

http://horia141.com/history-tables.html

7 Likes