sql >> Databasteknik >  >> RDS >> PostgreSQL

Hur man får ut det bästa av PostgreSQL-loggar

Som ett modernt RDBMS kommer PostgreSQL med många parametrar för finjustering. Ett av områdena att överväga är hur PostgreSQL ska logga sina aktiviteter. Loggning förbises ofta i Postgres databashantering, och om den inte ignoreras, vanligtvis felaktigt inställd. Detta händer eftersom syftet med loggning för det mesta är oklart. Naturligtvis är den grundläggande orsaken till loggning välkänd, men det som ibland saknas är en förståelse för hur loggarna kommer att användas.

Varje organisations loggningskrav är unika, och därför kommer hur PostgreSQL-loggning ska konfigureras också vara olika. Vad ett finansiellt tjänsteföretag behöver fånga i sina databasloggar kommer att skilja sig från vad ett företag som hanterar kritisk hälsoinformation behöver registrera. Och i vissa fall kan de också vara lika.

I den här artikeln kommer jag att täcka några grundläggande metoder för att få ut det bästa av PostgreSQL-loggar. Den här bloggen är ingen hård och snabb regelbok; läsare är mer än välkomna att dela sina tankar i kommentarsfältet. För att få ut det bästa värdet av det dock ber jag läsaren att tänka på hur de vill använda sina PostgreSQL-databasserverloggar:

  • Orsak för laglig efterlevnad där specifik information behöver samlas in
  • Säkerhetsrevision där specifika händelsedetaljer måste finnas
  • Felsökning av prestanda där frågor och deras parametrar ska registreras
  • Dag till dag driftstöd där ett visst antal mätvärden ska övervakas

Med det sagt, låt oss börja.

Gör inte manuella ändringar av postgresql.conf

Alla ändringar i postgresql.conf-filen bör göras med hjälp av ett konfigurationshanteringssystem som Puppet, Ansible eller Chef. Detta säkerställer att ändringar är spårbara och säkert kan återställas till en tidigare version vid behov. Detta gäller när du gör ändringar i loggningsparametrarna.

DBA:er skapar ofta flera kopior av postgresql.conf-filen, var och en med lite olika parametrar, var och en för olika ändamål. Att manuellt hantera olika konfigurationsfiler är en besvärlig uppgift om den inte är utsatt för fel. Å andra sidan kan ett konfigurationshanteringssystem fås att byta namn på och använda olika versioner av postgresql.conf-filen baserat på en parameter som skickas till den. Denna parameter kommer att diktera syftet med den aktuella versionen. När behovet är uppfyllt kan den gamla konfigurationsfilen läggas tillbaka genom att ändra samma indataparameter.

Till exempel, om du vill logga alla programsatser som körs på din PostgreSQL-instans, kan en konfigurationsfil med parametervärdet "log_statement=all" användas. När det inte finns något behov av att spela in alla uttalanden – kanske efter en felsökningsövning – kan den tidigare konfigurationsfilen återställas.

Använd separata loggfiler för PostgreSQL

Jag rekommenderar att du aktiverar PostgreSQL:s inbyggda loggningssamlare under normala operationer. För att aktivera inbyggd PostgreSQL-loggning, ställ in följande parameter på on:

logging_collector = on

Det finns två anledningar till det:

Först och främst, i upptagna system, kanske operativsystemet inte konsekvent registrerar PostgreSQL-meddelanden i syslog (förutsatt en nix-baserad installation) och ofta släpper meddelanden. Med inbyggd PostgreSQL-loggning tar en separat demon hand om att registrera händelserna. När PostgreSQL är upptagen kommer denna process att skjuta upp skrivningen till loggfilerna för att låta frågetrådarna avslutas. Detta kan blockera hela systemet tills logghändelsen skrivs. Det är därför användbart att spela in mindre utförliga meddelanden i loggen (som vi kommer att se senare) och använda förkortade loggradsprefix.

För det andra – och som vi kommer att se senare – bör loggar samlas in, tolkas, indexeras och analyseras med ett Log Management-verktyg. Att låta PostgreSQL registrera sina händelser i syslog kommer att innebära att man skapar ett extra lager av filtrering och mönstermatchning i Log Management-delen för att filtrera bort alla "brusmeddelanden". Dedikerade loggfiler kan enkelt analyseras och indexeras för händelser med de flesta verktyg.

Ställ in loggdestination till stderr

Låt oss överväga parametern "log_destination". Den kan ha fyra värden:

log_destination = stderr | syslog | csv | eventlog

Om det inte finns en bra anledning att spara logghändelser i kommaseparerat format eller händelselogg i Windows, rekommenderar jag att du ställer in den här parametern till stderr. Detta beror på att med en CSV-fildestination kommer ett anpassat "log_line_prefix"-parametervärde inte att ha någon effekt, och ändå kan prefixet fås att innehålla värdefull information.

Men på baksidan kan en CSV-logg enkelt importeras till en databastabell och senare efterfrågas med standard SQL. Vissa PostgreSQL-användare tycker att det är bekvämare än att hantera råa loggfiler. Som vi kommer att se senare kan moderna Log Management-lösningar tolka PostgreSQL-loggar och automatiskt skapa meningsfulla insikter från dem. Med CSV måste rapporteringen och visualiseringen göras manuellt av användaren.

I slutändan beror det på ditt val. Om du är bekväm med att skapa din egen datainmatningspipeline för att ladda CSV-loggarna till databastabeller, rensa och transformera data och skapa anpassade rapporter som passar dina affärsbehov, se till att "log_destination" är inställd på CSV.

Använd meningsfulla loggfilnamn

När PostgreSQL-loggfiler sparas lokalt kanske det inte är nödvändigt att följa en namngivningsstil. Standardfilnamnsstilen är "postgresql-%Y-%m-%d_%H%M%S.log" för icke-CSV-formaterade loggar, vilket är tillräckligt för de flesta fall.

Namngivning blir viktigt när du sparar loggfiler från flera servrar till en central plats som en dedikerad loggserver, en monterad NFS-volym eller en S3-hink. Jag rekommenderar att du använder två parametrar i sådana fall:

log_directory
log_filename

För att lagra loggfiler från flera instanser på ett ställe, skapa först en separat kataloghierarki för varje instans. Detta kan vara något i stil med följande:

/<Application_Name>/<Environment_Name>/<Instance_Name>

Varje PostgreSQL-instanss "log_directory" kan sedan pekas på dess utsedda mapp.

Varje instans kan sedan använda samma parametervärde för "log_filename". Standardvärdet kommer att skapa en fil som

postgresql_2020-08-25_2359.log

För att använda ett mer meningsfullt namn, ställ in "log_filename" till något så här:

log_filename = "postgresql_%A-%d-%B_%H%M"

Loggfilerna kommer då att heta så här:

postgresql_Saturday-23-August_2230

Använd meningsfullt logglinjeprefix

PostgreSQL-loggradsprefix kan innehålla den mest värdefulla informationen förutom själva meddelandet. Postgres-dokumentationen visar flera escape-tecken för konfiguration av logghändelseprefix. Dessa escape-sekvenser ersätts med olika statusvärden vid körning. Vissa applikationer som pgBadger förväntar sig ett specifikt logglinjeprefix.

Jag rekommenderar att du inkluderar följande information i prefixet:

  • Tid för händelsen (utan millisekunder):%t
  • Fjärrklientnamn eller IP-adress:%h
  • Användarnamn:%u
  • Åtkomst till databas:%d
  • Programnamn:%a
  • Process ID:%p
  • Avslutande icke-sessionsprocessutgång:%q
  • Loggradnumret för varje session eller process, från 1:%l

För att förstå vad varje fält i prefixet handlar om kan vi lägga till en liten bokstavlig sträng före fältet. Så, process-ID-värdet kan föregås av den bokstavliga "PID=", databasnamnet kan ha prefixet "db=" osv. Här är ett exempel:

log_line_prefix = 'time=%t, pid=%p %q db=%d, usr=%u, client=%h , app=%a, line=%l '

Beroende på var händelsen kommer ifrån kommer loggradens prefix att visa olika värden. Både bakgrundsprocesser och användarprocesser kommer att registrera sina meddelanden i loggfilen. För systemprocesser har jag specificerat %q, vilket kommer att undertrycka all text efter process-ID (%p). Alla andra sessioner kommer att visa databasnamn, användarnamn, klientadress, applikationsnamn och en numrerad rad för varje händelse.

Jag inkluderade också ett enda mellanslag efter loggradens prefix. Detta utrymme separerar logghändelseprefixet från det faktiska händelsemeddelandet. Det behöver inte vara ett blanksteg – något som ett dubbelt kolon (::), bindestreck (-) eller annan meningsfull avgränsare kan användas.

Ställ också in parametern "log_hostname" till 1:

log_hostname = 1

Utan detta kommer endast klientens IP-adress att visas. I produktionssystem kommer detta vanligtvis att vara adressen till proxyn, lastbalanseraren eller anslutningspoolaren. Om du inte kan IP-adresserna för dessa system utantill kan det vara värt att logga deras värdnamn. DNS-sökningen kommer dock också att lägga till extra tid för loggningsdemonen att skriva till filen.

En annan parameter som bör ställas in tillsammans med "log_line_prefix" är "log_timezone". Om du ställer in detta till serverns lokala tidszon säkerställer du att loggade händelser är lätta att följa från deras tidsstämpel istället för att konvertera till lokal tid först. I kodavsnittet nedan ställer vi in ​​log_timzeone till Australian Eastern Standard Timezone:

log_timezone = 'Australia/Sydney'

Endast logganslutningar

Två parametrar styr hur PostgreSQL registrerar klientanslutningar och frånkopplingar. Båda parametrarna är avstängda som standard. Baserat på din organisations säkerhetskrav kanske du vill ställa in en av dessa till 1 och den andra till 0 (såvida du inte använder ett verktyg som pgBadger – mer om det senare).

log_connections = 1
log_disconnections = 0

Om du ställer in log_connections till 1 registreras alla auktoriserade anslutningar samt försök anslutningar. Detta är uppenbarligen bra för säkerhetsrevision:en brute force attack kan lätt identifieras från loggarna. Men med den här inställningen aktiverad kan en hektisk PostgreSQL-miljö med tusentals eller till och med hundratals kortlivade giltiga anslutningar se att loggfilen blir översvämmad.

Ändå kan den också identifiera applikationsproblem som annars kanske inte är uppenbara. Ett stort antal anslutningsförsök från många olika giltiga klientadresser kan indikera att instansen behöver en lastbalanserare eller anslutningspoolningstjänst framför sig. Ett stort antal anslutningsförsök från en enda klientadress kan avslöja ett program med för många trådar som behöver någon typ av strypning.

Logga endast DDL- och DML-operationer

Det finns en hel del debatt kring vad som ska registreras i Postgres-loggen - dvs vad som ska vara värdet på parametern "log_statement". Den kan ha tre värden:

log_statement = 'off' | 'ddl' | 'mod' | 'all'

Det kan vara frestande att ställa in detta på "alla" för att fånga alla SQL-satser som körs på servern, men det kanske inte alltid är en bra idé i verkligheten.

Upptagna produktionssystem kör oftast SELECT-satser, ibland tusentals av dem per timme. Förekomsten kanske fungerar utmärkt, utan några prestandaproblem. Att ställa in denna parameter på "alla" i sådana fall skulle onödigt belasta loggningsdemonen eftersom den måste skriva alla dessa uttalanden till filen.

Vad du dock vill fånga är eventuell datakorruption eller förändringar i databasstrukturen som orsakade någon typ av problem. Oönskade eller obehöriga databasändringar orsakar fler programproblem än att välja data; det är därför jag rekommenderar att ställa in den här parametern till "mod". Med den här inställningen kommer PostgreSQL att registrera alla DDL- och DML-ändringar i loggfilen.

Om din PostgreSQL-instans är måttligt upptagen (dussintals frågor per timme), ställ gärna in den här parametern till "alla". När du felsöker långsamma SELECT-frågor eller letar efter obehörig dataåtkomst, kan du också ställa in detta på "alla" tillfälligt. Vissa applikationer som pgBadger förväntar sig också att du ställer in detta på "alla".

Logga "Varnings"-meddelanden och uppåt

Om parametern "log_statement" avgör vilken typ av satser som kommer att spelas in, bestämmer följande två parametrar hur detaljerat meddelandet kommer att vara:

log_min_messages
log_min_error_statement

Varje PostgreSQL-händelse har en tillhörande meddelandenivå. Meddelandenivån kan vara allt från utförlig DEBUG till kortfattad PANIK. Ju lägre nivå, desto mer utförligt är meddelandet. Standardvärdet för parametern "log_min_messages" är "VARNING". Jag rekommenderar att du håller den på denna nivå om du inte vill att informationsmeddelanden också ska loggas.

Parametern "log_min_error_statement" styr vilka SQL-satser som ger fel som kommer att loggas. Som "log_min_message", kommer alla SQL-satser som har en felsvårhetsnivå som är lika med eller över värdet som anges i "log_min_error_statement" att registreras. Standardvärdet är "ERROR", och jag rekommenderar att du behåller standardvärdet.

Behåll loggvaraktighetsparametrar som standard

Då har vi följande två parametrar:

log_duration
log_min_duration_statement

Parametern "log_duration" har ett booleskt värde. När den är inställd på 1, loggas varaktigheten av varje avslutat uttalande. Om inställningen är 0, loggas inte uttalandets varaktighet. Detta är standardvärdet, och jag rekommenderar att du håller det till 0 om du inte felsöker prestandaproblem. Att beräkna och registrera uttalandens varaktighet gör att databasmotorn gör extra arbete (oavsett hur liten den är), och när den extrapoleras till hundratals eller tusentals frågor kan besparingarna bli betydande.

Slutligen har vi parametern "log_min_duration_statement". När den här parametern är inställd (utan några enheter, den tas som millisekunder), loggas varaktigheten av en sats som är lika med eller längre än parametervärdet. Om du ställer in detta parametervärde till 0 registreras varaktigheten av alla avslutade uttalanden. Om du ställer in detta till -1 inaktiveras loggning av uttalandes varaktighet. Detta är standardvärdet, och jag rekommenderar att du behåller det så.

Den enda gången du vill ställa in den här parametern till 0 är när du vill skapa en prestandabaslinje för ofta körda frågor. Kom dock ihåg att om parametern "log_statement" är inställd, kommer de påståenden som loggas inte att upprepas i loggmeddelandena som visar varaktigheter. Så du måste ladda loggfilerna i en databastabell och sedan sammanfoga värdena för process-ID och sessions-ID från loggradens prefix för att identifiera relaterade uttalanden och deras varaktighet.

Oavsett vad det innebär, när du väl har en baslinje för varje fråga som körs ofta, kan du ställa in parametern "log_min_duration_statement" till det högsta av baslinjevärdena. Nu kommer varje fråga som körs längre än det högsta baslinjevärdet att vara en kandidat för finjustering.

Behåll felmeddelandens innehåll till standard

Parametern "log_error_verbosity" kan ha tre möjliga värden:

log_error_verbosity = terse | standard | verbose

Denna parameter styr mängden information som PostgreSQL kommer att registrera för varje händelse som registreras i loggfilen. Såvida du inte felsöker en databasapplikation är den här parametern bäst att hålla till "standard". Det utförliga läget kommer att vara användbart när du behöver fånga fil- eller funktionsnamnet och radnumret där som genererade felet. Om du ställer in detta på "terse" kommer loggningen av frågan undertryckas, vilket kanske inte heller är användbart.

Hitta en loggrotationspolicy som fungerar för din Användningsfall

Jag rekommenderar att du skapar en loggrotationspolicy baserad på antingen storleken eller åldern på loggfilen, men inte båda. Två PostgreSQL-konfigurationsparametrar dikterar hur gamla loggar arkiveras och nya loggar skapas:

log_rotation_age = <number of minutes>
log_rotation_size = <number of kilobytes>

Standardvärdet för "log_rotration_age" är 24 timmar och standardvärdet för "log_rotation_size" är 10 megabyte.

I de flesta fall garanterar inte alltid att det sista loggmeddelandet i den arkiverade loggfilen är fullständigt inkluderat i endast den filen.

Om "log_rotation_age" hålls till sitt standardvärde på 24 timmar, kan varje fil lätt identifieras och granskas individuellt, eftersom varje fil kommer att innehålla en dags händelser. Men inte heller detta garanterar att varje fil kommer att vara en fristående enhet av loggar för de senaste 24 timmarna. Ibland kan det ta mer än 24 timmar att slutföra en fråga som går långsamt. händelser kan hända när den gamla filen stängs och den nya genereras. Detta kan vara fallet under ett nattligt batchjobb, vilket resulterar i att vissa delar av frågorna registreras i en fil och resten i en annan.

Vår rekommendation är att hitta en loggrotationsperiod som fungerar för din användningsfall. Kontrollera tidsskillnaden mellan två på varandra följande perioder med lägst aktivitet (till exempel mellan en lördag till nästa). Du kan sedan ställa in värdet "log_rotation_age" till den tidsskillnaden och under en av dessa perioder starta om PostgreSQL-tjänsten. På så sätt kommer PostgreSQL att rotera den aktuella loggfilen när nästa pausperiod inträffar. Men om du behöver starta om tjänsten mellan dessa perioder kommer loggrotationen igen att skevt. Du måste sedan upprepa denna process. Men som många andra saker i PostgreSQL, kommer trial and error att diktera det bästa värdet. Dessutom, om du använder ett logghanteringsverktyg kommer loggrotationens ålder eller storlek inte att spela någon roll eftersom logghanterarens agent kommer att mata in varje händelse från filen när den läggs till.

Använd verktyg som pgBadger

pgBadger är en kraftfull PostgreSQL-logganalysator som kan skapa mycket användbara insikter från Postgres-loggfiler. Det är ett verktyg med öppen källkod skrivet i Perl med ett mycket litet fotavtryck i maskinen där det körs. Verktyget körs från kommandoraden och kommer med ett stort antal alternativ. Det tar en eller flera loggar som indata och kan producera en HTML-rapport med detaljerad statistik om:

  • De vanligaste väntande frågorna.
  • Frågor som genererar de flesta temporära filerna eller de största temporära filerna
  • Långsammast körande frågor
  • Genomsnittlig frågelängd
  • De vanligaste sökfrågorna
  • De vanligaste felen i frågor
  • Användare och program som kör frågor
  • Statistik för kontrollpunkter.
  • Autovacuum och autoanalysera statistik.
  • Låsstatistik
  • Felhändelser (panik, dödlig, fel och varning).
  • Anslutnings- och sessionsprofiler (efter databas, användare, applikation)
  • Sessionsprofiler
  • Frågeprofiler (frågetyper, frågor per databas/applikation)
  • I/O-statistik
  • osv.

Som jag nämnde tidigare måste några av de loggrelaterade konfigurationsparametrarna vara aktiverade för att fånga alla logghändelser så att pgBadger effektivt kan analysera dessa loggar. Eftersom detta kan producera stora loggfiler med många händelser, bör pgBadger endast användas för att skapa benchmarks eller felsöka prestandaproblem. När de detaljerade loggarna har genererats kan konfigurationsparametrarna ändras tillbaka till sina ursprungliga värden. För kontinuerlig logganalys är det bäst att använda en dedikerad logghanteringsapplikation.

Om du är mer bekväm med att göra saker i kommandotolken och använda systemvyer, skulle du vilja använda pg_stat_statements. I själva verket borde detta vara aktiverat i alla PostgreSQL-produktionsinstallationer.

pg_stat_statements är ett PostgreSQL-tillägg och med standardinstallationen nu. För att aktivera det bör konfigurationsparametern "shared_preload_libraries" ha pg_stat_statements som ett av dess värden. Det kan sedan installeras som alla andra tillägg med kommandot "CREATE EXTENSION". Tillägget skapar vyn pg_stat_statement som ger värdefull frågerelaterade information.

Använd ett logghanteringsprogram för att få insikt

Det finns många logghanteringsverktyg på marknaden, och de flesta organisationer använder en eller flera nu för tiden. Oavsett vilket verktyg som finns på plats rekommenderar jag att du använder det för att samla in och hantera PostgreSQL-loggar.

Det finns några anledningar till det:

Det är mycket lättare att analysera, analysera och filtrera bort brus från loggfiler med ett automatiserat verktyg. Ibland kan en händelse sträcka sig över flera loggfiler baserat på händelsens varaktighet och loggrotationens ålder eller storlek. Att ha en logghanterare gör det mycket enklare att få denna information presenterad som en helhet.

Logghanteringslösningar idag kommer vanligtvis med inbyggd förmåga att tolka PostgreSQL-loggar. Vissa kommer också med instrumentpaneler som kan visa de vanligaste mätvärdena som extraherats från dessa loggar.

De flesta moderna logghanteringsapplikationer erbjuder också kraftfulla funktioner för sökning, filter, mönstermatchning, händelsekorrelation och AI-aktiverade trendanalysfunktioner. Det som inte är synligt för vanliga ögon kan lätt göras uppenbart med dessa verktyg.

Slutligen, att använda en logghanterare för att lagra PostgreSQL-loggar kommer också att innebära att händelserna sparas för eftervärlden, även om originalfilerna raderas av misstag eller av uppsåt.

Även om det finns uppenbara fördelar med att använda ett logghanteringsprogram, har många organisationer begränsningar för var deras stockar kan leva. Det här är ett typiskt fall med SaaS-baserade lösningar där loggar ofta sparas utanför en organisations geografiska gräns – något som kanske inte överensstämmer med regulatoriska krav.

I sådana fall rekommenderar jag att du väljer en leverantör med lokal närvaro i ett datacenter – om möjligt – eller använder en självhanterad logghanterare som finns i organisationens nätverk, till exempel en ELK-stack.

Slutord

PostgreSQL-serverloggar kan vara en guldgruva av information när de är lämpligt konfigurerade. Tricket är att bestämma vad som ska loggas och hur mycket som ska loggas, och ännu viktigare, testa om loggarna kan leverera rätt information när det behövs. Det kommer att bli en fråga om försök och misstag, men det jag har diskuterat här idag borde ge en ganska hyfsad start. Som jag sa i början skulle jag mer än gärna höra om din erfarenhet av att konfigurera PostgreSQL-loggning för optimala resultat.


  1. Hur PATINDEX()-funktionen fungerar i SQL Server (T-SQL)

  2. Oracle databas backup:Typ av backup och backup strategi

  3. Hur man installerar och konfigurerar MaxScale för MariaDB

  4. Oracle Concurrent Manager – CP Analyzer för E-Business Suite