05/01/2013
At forstå, hvad der sker inde i en database, især under langvarige operationer, kan være forskellen mellem en velfungerende applikation og en frustrerende brugeroplevelse. I mange år var det en udfordring at få detaljeret indsigt i fremdriften af kommandoer i PostgreSQL. Administratorer og udviklere måtte ty til kreative, men ofte begrænsede, metoder. Heldigvis har nyere versioner af PostgreSQL introduceret en række kraftfulde værktøjer, der giver præcis og realtidsinformation om status for kritiske opgaver. Denne artikel vil guide dig gennem både de klassiske teknikker og de moderne, indbyggede funktioner til overvågning af fremdrift.

De Klassiske Metoder: Tricks fra Fortiden
Før de dedikerede fremdriftsvisninger blev en del af kernen, fandtes der flere smarte løsninger til at få en fornemmelse af, hvor langt en forespørgsel var nået. Selvom de nu er mindre relevante, er det nyttigt at kende dem, især hvis man arbejder med ældre systemer.
Brug af Sekvenser
En simpel, men effektiv metode involverer brugen af sekvenser. Hvis en langvarig UPDATE, INSERT eller SELECT-forespørgsel kan modificeres til at inkludere et kald til nextval('min_sekvens') for hver række, der behandles, kan man overvåge fremskridtet fra en anden session. Ved at jævnligt kalde SELECT last_value FROM min_sekvens;, kan man se, hvor mange rækker der er blevet behandlet. Dette virker, fordi sekvensopdateringer ikke er transaktionsbundne og er synlige med det samme.
Denne metode har dog klare begrænsninger. Den kræver en ændring af selve forespørgslen og fungerer kun, hvis eksekveringsplanen behandler rækkerne lineært.
Tricket med pgstattuple
Et andet trick, forbeholdt superbrugere, er at bruge pgstattuple-modulet. Når man indsætter data i en tom tabel, vil de nye, endnu ikke-commitede tupler blive talt i feltet dead_tuple_count. Ved at køre SELECT dead_tuple_count FROM pgstattuple('tabelnavn'); gentagne gange i en separat session, kan man se antallet af indsatte rækker stige. Når transaktionen committes, falder tælleren tilbage til nul, da tuplerne bliver 'live'.

Ulemperne er tydelige: Det virker primært på tomme tabeller, kræver superuser-rettigheder, og hvert kald til pgstattuple scanner hele tabellen, hvilket kan være en dyr operation i sig selv.
Den Moderne Tilgang: pg_stat_progress Visninger
Den mest pålidelige og anbefalede metode til at overvåge fremdrift i moderne PostgreSQL-versioner er ved at bruge den familie af systemvisninger, der starter med pg_stat_progress_. Disse visninger giver detaljeret, realtidsinformation for specifikke, langvarige kommandoer.
De kommandoer, der i øjeblikket understøtter denne form for rapportering, inkluderer:
VACUUMANALYZECLUSTERogVACUUM FULLCREATE INDEXogREINDEXCOPYBASE_BACKUP
Lad os dykke ned i, hvordan man bruger de mest almindelige af disse visninger.
Overvågning af VACUUM med pg_stat_progress_vacuum
En af de mest kritiske vedligeholdelsesopgaver er VACUUM. En langsom vacuum-proces kan påvirke hele systemets ydeevne. Med pg_stat_progress_vacuum kan du se præcis, hvad der sker.

For at se status for alle kørende VACUUM-processer (både manuelle og autovacuum), kan du køre:
SELECT pid, datname, relid::regclass AS table_name, phase, heap_blks_scanned, heap_blks_total, round(100.0 * heap_blks_scanned / heap_blks_total, 2) AS scan_progress_percent FROM pg_stat_progress_vacuum WHERE heap_blks_total > 0;Dette giver dig proces-ID, databasenavn, tabelnavn, den aktuelle fase og en procentvis fremdrift af scanningen af tabellen (heap scan).
VACUUM Faser
phase-kolonnen er særligt informativ. Den viser, hvilket trin processen er i. Her er en oversigt over faserne:
| Fase | Beskrivelse |
|---|---|
| initializing | Processen forbereder sig på at scanne tabellen. Meget kort fase. |
| scanning heap | Hovedfasen, hvor tabellens blokke scannes for døde tupler. Fremskridt kan ses i heap_blks_scanned. |
| vacuuming indexes | Indekser bliver renset for henvisninger til døde tupler. |
| vacuuming heap | De døde tupler fjernes fra tabel-blokkene. |
| cleaning up indexes | Endelig oprydning af indekser. |
| truncating heap | Tomme sider i slutningen af tabellen frigives tilbage til operativsystemet. |
| performing final cleanup | Statistikker opdateres, og processen afsluttes. |
Bemærk: VACUUM FULL rapporteres ikke her, men i pg_stat_progress_cluster, da den omskriver hele tabellen.
Overvågning af Indeksoprettelse med pg_stat_progress_create_index
At bygge et indeks på en stor tabel kan tage lang tid og låse ressourcer. pg_stat_progress_create_index giver dig indsigt i denne proces.
SELECT pid, relid::regclass AS table_name, index_relid::regclass AS index_name, command, phase, blocks_done, blocks_total, tuples_done, tuples_total FROM pg_stat_progress_create_index;Denne visning er uvurderlig, især når du kører CREATE INDEX CONCURRENTLY, da den har flere faser, hvor den venter på andre transaktioner. Du kan se, hvilken fase den er i (f.eks. 'building index: scanning table' eller 'waiting for old snapshots') og hvor langt den er nået i den pågældende fase.

Generel Forespørgsels-Overvågning med pg_stat_activity
Mens pg_stat_progress_* visningerne er fantastiske til specifikke kommandoer, er pg_stat_activity det primære værktøj til at få et overblik over *alle* aktive forbindelser og deres nuværende status. Det viser ikke fremdrift i procent, men det fortæller dig, hvad der kører, hvor længe det har kørt, og om det venter på noget.
Find Langsomme Forespørgsler
For at finde de forespørgsler, der har kørt længst, kan du bruge følgende:
SELECT pid, usename, datname, now() - query_start AS duration, state, wait_event, query FROM pg_stat_activity WHERE state = 'active' ORDER BY duration DESC;Dette er et essentielt værktøj for enhver databaseadministrator. Her er nøglekolonnerne:
- duration: Hvor længe forespørgslen har været aktiv.
- state: Status for backend-processen. 'active' betyder, at den udfører en forespørgsel. 'idle' betyder, den venter på en kommando. 'idle in transaction' er en farlig tilstand, hvor en transaktion er åben, men inaktiv, hvilket kan holde på låse og ressourcer.
- wait_event: Hvis processen venter, viser denne kolonne, hvad den venter på (f.eks. 'Lock', 'ClientRead', 'IO'). Dette er guld værd for fejlfinding af flaskehalse.
- query: Selve SQL-forespørgslen, der bliver udført.
Sammenligning af Metoder
For at give et klart overblik, er her en sammenligningstabel over de diskuterede metoder.
| Metode | Anvendelsesområde | Fordele | Ulemper |
|---|---|---|---|
pg_stat_progress_* | Specifikke kommandoer (VACUUM, INDEX, etc.) | Detaljeret, indbygget, pålidelig, lav overhead. | Understøtter ikke alle kommandoer (f.eks. SELECT, UPDATE). |
pg_stat_activity | Alle kørende forespørgsler | Giver et komplet overblik, viser ventestatus, indbygget. | Viser ikke procentvis fremdrift. |
| Sekvens-trick | Række-for-række operationer | Simpelt at implementere. | Kræver ændring af forespørgsel, upræcist. |
| pgstattuple | Store INSERTs i tomme tabeller | Kan give et estimat for INSERT-fremdrift. | Kræver superuser, høj overhead, begrænset brug. |
Ofte Stillede Spørgsmål (FAQ)
- Kan jeg se fremdriften for en almindelig `SELECT`-forespørgsel?
- Generelt nej. Der er ingen indbygget `pg_stat_progress_select`-visning. For simple, lineære scans kan sekvens-tricket teoretisk anvendes, men for komplekse forespørgsler med joins og aggregeringer er det ikke muligt at få en meningsfuld procentvis fremdrift.
- Hvorfor kan jeg ikke se min `VACUUM`-kommando i `pg_stat_progress_vacuum`?
- Hvis du kører `VACUUM FULL`, skal du kigge i `pg_stat_progress_cluster` i stedet. Almindelig `VACUUM` vises i `pg_stat_progress_vacuum`.
- Hvilke rettigheder kræves for at se disse visninger?
- Almindelige brugere kan typisk se deres egne processer i disse visninger. For at se alle processer på tværs af databasen kræves der normalt superuser-rettigheder eller medlemskab af den foruddefinerede rolle `pg_monitor` (i PostgreSQL 10 og nyere).
- Hvordan kan jeg stoppe en langsom forespørgsel, jeg har identificeret?
- Når du har fundet proces-ID (pid) fra `pg_stat_activity`, kan du forsøge at annullere forespørgslen pænt med `SELECT pg_cancel_backend(pid);`. Hvis det ikke virker, kan du tvinge forbindelsen til at lukke med `SELECT pg_terminate_backend(pid);`. Vær forsigtig med sidstnævnte, da det brat afslutter hele forbindelsen.
Konklusion
Evnen til at overvåge fremdriften af langvarige operationer i PostgreSQL er gået fra at være en kunst baseret på 'hacks' til at være en videnskab baseret på præcise, indbyggede værktøjer. Ved at kombinere brugen af de specifikke pg_stat_progress_* visninger med det generelle overblik fra pg_stat_activity, har databaseadministratorer og udviklere nu et stærkt arsenal til at diagnosticere flaskehalse, estimere færdiggørelsestider og sikre en sund og velfungerende database.
Hvis du vil læse andre artikler, der ligner Overvågning af Fremdrift i PostgreSQL, kan du besøge kategorien Sundhed.
