sql >> Database teknologi >  >> RDS >> PostgreSQL

Håndtering af frysning i PostgreSQL

Postgres indeholder en bevægende begivenhedshorisont, som i realiteten er omkring 2 milliarder transaktioner før eller efter det aktuelle transaktions-id. Transaktioner op til 2 milliarder før eller mere end 2 milliarder bag det nuværende transaktions-id anses for at være i fremtiden og vil således være usynlige for nuværende transaktioner.

Postgres undgår dette katastrofale datatab ved at markere gamle rækker specielt, så de vil være synlige, uanset hvor de er i forhold til det aktuelle transaktions-id.

Frysning er denne proces med at markere gamle levende tupler (dvs. databaserækker), så de ikke bliver kørt over af den bevægende begivenhedshorisont, som ellers ville få dem til at se ud til at være i fremtiden. Dette er i modsætning til støvsugning, som er at frigøre plads, der forbruges af gamle døde tupler, der ikke længere er synlige for nogen transaktion.

Begge processer styres af vakuum.

Der er en række indstillinger, der styrer, hvordan indfrysning udføres.

Først vacuum_freeze_min_age styrer, om en tupel vil blive frosset, mens vakuum allerede kigger på en side for at se, om den har døde tuple, der kan ryddes op. Tuples ældre end vacuum_freeze_min_age vil blive frosset i dette tilfælde. Hvis du sætter dette lavt, betyder det, at der vil være mindre arbejde at gøre senere, men på den mulige pris af ekstra indsats både i CPU- og IO- eller WAL-aktivitet. Generelt vil du sandsynligvis have dette sæt til mindst et par timers transaktioner. Lad os sige, at du forventer at udføre op til 2000 transaktioner i sekundet som en vedvarende hastighed. 2000 TPS er 7,2 millioner transaktioner i timen. En temmelig aggressiv indstilling for denne sag kan således være f.eks. 20m. Standardindstillingen er 50m. Tilsvarende for vacuum_multixact_freeze_min_age . Bemærk, at tællerne for transaktions-id og multioxid er uafhængige – du skal holde styr på dem begge.

For det andet er der vacuum_freeze_table_age og vacuum_multixact_freeze_table_age . Disse indstillinger styrer, hvornår autovakuum ikke kun ser på sider, der kan have døde rækker, men enhver side, der kan have ufrosne rækker. Standardindstillingerne for disse indstillinger er 150m. Hvis du har reduceret vacuum_freeze_min_age nok, i mange tilfælde vil dette mere aggressive vakuum have lidt eller intet arbejde at gøre. Under alle omstændigheder er denne proces ikke så travl, som den plejede at være, da moderne versioner af Postgres (9.6 og op) holder et kort over sider, hvor alle tupler er frosset, og kun besøger de sider, der ikke alle er frosne. Det betyder, at dette ikke længere er en fuld tabelscanning.

Sidst er der autovacuum_freeze_max_age . Hvis sidste gang, bordet blev scannet fuldstændigt for ikke-frosne rækker, var mere end for mange transaktioner siden, vil autovacuum starte et anti-omviklingsvakuum på bordet. Standard er 200m. Tilsvarende for autovacuum_multixact_freeze_max_age hvor standarden er 400m. Dette er noget, du virkelig gerne vil undgå. Der er to ting, der kan gøres. For det første er det meget almindeligt at øge disse indstillinger til noget i retning af 1 milliard, for at give dig selv mere plads, især på systemer, der er storforbrugere af transaktioner. Du kan gøre det mere, men du vil gerne have masser af transaktionsplads mellem din ældste tuple og begivenhedshorisonten. For det andet er det vigtigt at overvåge dine systemer og træffe afhjælpende foranstaltninger, før nogen databaser løber ind i dette. Denne afhjælpende handling omfatter ofte manuel støvsugning.

Et problem, der kan opstå, er, hvor du har DDL, der får normal (dvs. ikke anti-omvikling) autovakuum til at annullere sig selv. Hvis du gør dette nok til sidst, vil du få tvunget et anti-omviklingsvakuum, og enhver DDL stiller sig derefter i kø bagved vakuumprocessen, og det blokerer igen for yderligere DML. På dette tidspunkt er dit bord i praksis ulæselig, indtil støvsugningen er færdig. Dette afhænger af din databases brugsmønster, men dette er ikke kun en teoretisk mulighed, og Postgres-implementeringer og DBA'er skal tage højde for det.

Overvågning af din databaseklynge er afgørende for at administrere dette. Du skal især overvåge datfrozenxid og datminmxid af hver database i klyngen, og hvis disse bliver for gamle, tag afhjælpende foranstaltninger, før der kræves et anti-omviklingsstøvsuger. Ofte er problemet med en eller nogle få tabeller i databasen. Hvilke der er problemet kan opdages ved at undersøge relfrozenxid og relminmxid af tabellerne i databasen. age() og mxid_age() funktioner er nyttige til at finde alderen for henholdsvis transaktions-id og multioxidtællere.

Frysning er ikke noget, du kan undgå, det er en væsentlig vedligeholdelsesaktivitet i Postgres, der skal styres aktivt.


  1. Sådan aktiveres/deaktiveres CHECK-begrænsninger i SQLite

  2. Modellering af produktvarianter

  3. Introduktion til PL/SQL-funktioner i Oracle-databasen

  4. Få Short Day Name i PostgreSQL