Data og stabil drift

SQL og PostgreSQL: få styr på data, før andre bruger appen

En AI-bygget app kan se færdig ud, selv om databasen stadig accepterer dubletter, forældreløse poster og ændringer uden historik. En driftsklar SQL-løsning kræver en tydelig datamodel, regler i databasen, afgrænset adgang og en sikker måde at ændre strukturen på.

Hvornår er SQL et godt valg?

SQL passer typisk godt, når appens data har tydelige relationer og regler: en sag tilhører en kunde, en ordre har flere linjer, eller en registrering skal kunne indgå i rapporter på tværs. PostgreSQL er en udbredt SQL-database og bruges blandt andet af Supabase, men principperne i denne guide gælder også andre relationelle databaser. Den konkrete syntaks og platformopsætning kan være anderledes.

SQL er ofte relevant
Relationer, joins, transaktioner, rapportering og faste krav til datakvalitet.
Et andet datalager kan passe bedre
Meget enkle dokumenter, filer, cache eller hændelser med andre adgangs- og skaleringsmønstre.
Databasetypen skal følge problemet. Det er ikke et kvalitetsstempel at vælge SQL, og en fungerende Firestore- eller Table Storage-løsning skal ikke flyttes alene for at følge denne guide.

Tegn forretningen som data

Start med de begreber, virksomheden allerede bruger: kunde, projekt, opgave, ordre, dokument eller godkendelse. Skriv derefter relationerne og de regler, som altid skal gælde. Datamodellen bør kunne forklares uden at åbne kodebasen.

  • Identitet: Hvilken stabil nøgle identificerer hver post, også når et navn eller nummer ændres?
  • Ejerskab: Hvilken virksomhed, bruger eller sag tilhører posten?
  • Relationer: Hvad må eksistere alene, og hvad skal pege på en gyldig overordnet post?
  • Livscyklus: Hvilke statusser findes, og må data slettes, arkiveres eller kun markeres som inaktive?
  • Tid og sporbarhed: Skal oprettelse, ændring, godkendelse eller historik gemmes?

Gem ikke alt i én stor tabel eller i frie JSON-felter, hvis virksomheden faktisk har relationer og regler, der skal kunne kontrolleres og rapporteres på. Omvendt behøver en lille app ikke en avanceret model for tænkte fremtidsscenarier.

Læg de vigtigste regler i databasen

Validering i brugerfladen giver gode fejlbeskeder, men den kan omgås. Constraints beskytter data uanset om ændringen kommer fra appen, et script, en integration eller et administrationsværktøj.

Nøgler og relationer

Brug en primary key på hver tabel og foreign keys til relationer. Vælg bevidst, hvad der skal ske ved sletning. Automatisk cascade kan være rigtigt for en ren underpost, men farligt for selvstændige forretningsdata.

Påkrævede og unikke værdier

Brug NOT NULL, når en værdi reelt er obligatorisk, og en unik constraint, når eksempelvis et eksternt hændelses-id eller et kundenummer ikke må optræde flere gange i den relevante sammenhæng.

Gyldige værdier

En check constraint kan afvise umulige beløb, datoer eller statusværdier. Regler, der afhænger af andre tabeller eller komplekse arbejdsgange, kræver en anden mekanisme og tests i applikationen.

Pas på sletning. Et genereret forslag som ON DELETE CASCADE kan fjerne langt mere end den synlige post. Beskriv konsekvensen med forretningens ord og test den på realistiske relationer.

Adskil ejerskab, migrering og daglig appadgang

Appen bør normalt ikke forbinde som databaseejer eller superbruger. Opret en rolle til den daglige runtime med de nødvendige handlinger og ikke mere. Brug en særskilt, kontrolleret adgang til schemaændringer og administrative opgaver.

  • Backend med direkte forbindelse: Hold forbindelsesstrengen ude af frontend og Git, og begræns netværk og databaseprivilegier.
  • Supabase Data API: Aktivér Row Level Security på eksponerede tabeller og test både tilladte og afviste handlinger.
  • Administrativ adgang: Brug den kun til migrering, fejlsøgning og drift – ikke som appens normale identitet.
  • Miljøer: Produktion, test og lokal udvikling skal have separate databaser, brugere og secrets.

Row Level Security er relevant, når databasen eller en Data API skal håndhæve adgang til den enkelte række. Den erstatter ikke en gennemtænkt adgangsmatrix, og privilegerede serverroller kan omgå politikkerne.

Ændr schemaet med migreringer – ikke hukommelse

En migration er en versionsstyret beskrivelse af en databaseændring. Den gør det muligt at se, teste og gentage ændringen i samme rækkefølge på tværs af miljøer. Gem hele migrationshistorikken i Git sammen med den kode, der afhænger af den.

  1. Tilføj: Opret den nye tabel eller kolonne uden straks at fjerne det gamle.
  2. Udfyld: Flyt eller beregn eksisterende data i kontrollerede portioner, og verificér resultatet.
  3. Skift appen: Udgiv kode, som bruger den nye struktur, mens den gamle stadig kan læses ved behov.
  4. Stram og ryd op: Tilføj eventuelle krav og fjern først den gamle struktur, når den ikke længere bruges.

Mønstret kaldes ofte expand-and-contract. Det er især nyttigt ved nye obligatoriske felter, ændrede typer og omdøbning af kolonner. Den præcise plan afhænger af datamængde, database, ORM og hvor meget nedetid virksomheden accepterer.

Redigér ikke en allerede anvendt migration. Lav en ny rettelse, så test og produktion beholder samme historik. Tag en relevant backup, test på en kopi eller et separat miljø, og planlæg både applikations- og datavejen tilbage.

Forbindelser og indeks er driftskapacitet

En app kan virke med én testbruger og alligevel fejle, når serverless-funktioner åbner mange samtidige databaseforbindelser. Vælg forbindelsesmetode efter hostingformen og databaseudbyderens dokumentation. En pooler kan genbruge forbindelser ved mange korte kald, mens migrering og backup ofte kræver en anden forbindelse.

  • Mål før optimering: Find langsomme forespørgsler og højt forbindelsesforbrug i platformens målinger.
  • Indeksér efter brug: Indeks hjælper opslag og joins, men fylder og gør skrivninger dyrere. Tilføj dem til konkrete forespørgsler.
  • Husk foreign keys: PostgreSQL opretter ikke automatisk indeks på den refererende kolonne, selv om et sådant indeks ofte er nyttigt.
  • Bevar driftsadgang: Brug ikke alle forbindelser til apptrafik; platformens grænser og pool skal give plads til migration og fejlsøgning.

Typiske fejl

  • Datamodellen findes kun i kode: Databasen kan gemme tilstande, som appen ikke kan håndtere.
  • Produktion ændres i et dashboard: Ingen kan bagefter genskabe eller gennemgå den præcise ændring.
  • Appen bruger ejerkontoen: En fejl eller lækket adgang får unødigt store konsekvenser.
  • Test og produktion deler database: Testdata, sletninger og eksperimenter rammer rigtige brugere.
  • En kolonne slettes i samme udgivelse: Ældre kode eller igangværende jobs forventer stadig den gamle struktur.
  • Alle relationer bruger cascade: En enkel sletning forplanter sig til data, virksomheden skulle bevare.
  • Indeks tilføjes på gæt: Databasen bruger mere plads og langsommere skrivninger uden at løse den reelle flaskehals.
  • Serverless åbner for mange forbindelser: Appen rammer databasegrænsen under trafikspidser.

Tjekliste før medarbejdere eller kunder får adgang

  • ☐ Det er dokumenteret, hvorfor SQL passer til appens data og forespørgsler.
  • ☐ Hver central tabel har stabil identitet, ejerskab og tydelige relationer.
  • ☐ Primary keys, foreign keys, unikke værdier, obligatoriske felter og gyldige værdier håndhæves, hvor de er forretningskritiske.
  • ☐ Sletteadfærd er valgt og testet for hver vigtig relation.
  • ☐ Appens normale databasebruger er ikke ejer eller superbruger.
  • ☐ Forbindelsesstrenge og privilegerede nøgler findes kun i godkendt serverkonfiguration.
  • ☐ Direkte klientadgang er beskyttet med Row Level Security eller tilsvarende politikker.
  • ☐ Lokal udvikling, test og produktion har separate data, roller og secrets.
  • ☐ Schemaændringer ligger som migrationsfiler i Git og testes før produktion.
  • ☐ Risikable ændringer har plan for backup, datakontrol og en kompatibel vej tilbage.
  • ☐ Forbindelsesmetode og pool passer til vedvarende server, serverless eller edge-runtime.
  • ☐ En navngiven systemejer ved, hvor databasen ligger, hvordan den ændres, og hvem der har administrativ adgang.

Relaterede guides

Officielle kilder

Kommandoer og driftsvalg afhænger af database, udbyder, ORM og hosting. Kontrollér den aktuelle dokumentation for jeres konkrete løsning, gennemgå genereret SQL, og afprøv ændringer på data, der ikke er produktionens eneste kopi.