sql >> Databasteknik >  >> RDS >> PostgreSQL

Konfigurera PostgreSQL för observerbarhet

PostgreSQL kommer med en uppsjö av konfigurationsalternativ, men att ändra standardinställningarna för några av dessa alternativ förbättrar avsevärt observerbarheten för din PostgreSQL-server. Du kommer att vilja ställa in och konfigurera dessa alternativ innan problem dyker upp i produktionen, eftersom de kan ge information som är viktig för att förstå och lösa dessa problem.

Läs vidare för att lära dig mer om inställningarna och tilläggen som exponerar statistik och information om din PostgreSQL-servers inre funktioner.

Logglinjeprefix

log_line_prefix konfigurationsalternativet bestämmer vad PostgreSQL skriver i början av varje loggrad. Standardinställningen beror på den specifika Linuxdistribution eller hanterade lösning som du använder, men oftare än inte innehåller den inte några få objekt som kan visa sig vara mycket användbara för att spåra klienter som inte beter sig. Prova detta log_line_prefix :

log_line_prefix = '%m [%p] %a %u %d %h '

Den inkluderar tidsstämpeln (%m ), PID för backend-processen (%p ), programnamnet (%a ) för klienten, användarnamnet som klienten har anslutit till (%u ), databasen som klienten har anslutit till (%d ) och värdnamnet eller IP-adressen där anslutningen kommer från (%h ). Detta resulterar i logglinjer så här:

2021-01-30 05:06:03.675 UTC [73] psql postgres bench 172.17.0.1 ERROR:  relation "pgbench_akkounts" does not exist at character 15
2021-01-30 05:06:03.675 UTC [73] psql postgres bench 172.17.0.1 STATEMENT:  select * from pgbench_akkounts;

som är mycket mer användbara än standard. Du kan se att en klient är ansluten från 172.17.0.1 som användare postgres till databasen bänk , och programmet var psql . Definitivt en förbättring jämfört med standardalternativet, som bara visar detta:

2021-01-30 05:13:22.630 UTC [63] ERROR:  relation "pgbench_akkounts" does not exist at character 15
2021-01-30 05:13:22.630 UTC [63] STATEMENT:  select * from pgbench_akkounts;

Logga långsamma frågor

PostgreSQL kan konfigureras för att logga frågor som tar mer än en viss tid att köra. Dessa går in i samma loggfil; det finns ingen separat långsam frågeloggfil som i MySQL.

Använd log_min_duration_statement för att logga satser som tar mer än 1 sekund att köra alternativ så här:

log_min_duration_statement = 1s

Observera att log_min_duration_statement kommer att överväga alla uttalanden (inklusive till exempel långvariga admin-satser som REINDEX TABLE ) och inte bara frågor (SELECT ). Här är några loggposter som skapas av detta alternativ:

2021-01-30 08:42:57.473 UTC [62] psql postgres postgres 172.17.0.1 LOG:  duration: 1016.283 ms  statement: select pg_sleep(1);
2021-01-30 08:52:00.541 UTC [62] psql postgres postgres 172.17.0.1 LOG:  duration: 1118.277 ms  statement: select pg_sleep(1.1);

Om detta resulterar i för många loggar med liknande uttalanden, kan du berätta för Postgres tolog endast en procentandel av det, med:

log_min_duration_statement = -1
log_min_duration_sample = 1s
log_statement_sample_rate = 0.25

Detta loggar endast 25 % av de uttalanden som blir kvalificerade för loggning (de som tog mer än 1 sekund att köra). Loggutgången är densamma som tidigare. Det finns inget sätt att veta hur många kvalificerade uttalanden som inte loggades.

För att logga alla uttalanden, tillsammans med tiden det tar att köra dem, användlog_statement alternativ istället:

log_statement = mod
log_duration = on

Alternativet "mod" berättar för Postgres att logga DDL:er och datamodifierande uttalanden. Detta resulterar i loggar som dessa:

2021-01-30 08:35:08.985 UTC [64] pgbench postgres bench 172.17.0.1 LOG:  statement: insert into pgbench_tellers(tid,bid,tbalance) values (10,1,0)
2021-01-30 08:35:08.985 UTC [64] pgbench postgres bench 172.17.0.1 LOG:  duration: 0.241 ms

Varnas för att det inte är det möjligt att ta exempel på satsloggning aktiverad på detta sätt, alla satser kommer att loggas och du kommer att sluta med massor av loggposter.

Logga lås och låsta lås

Frågor kan vänta för länge för att få ett lås. Vanligtvis ställs en övre gräns för hur länge man ska vänta med alternativet lock_timeout , vanligtvis på klientsidan. Om en fråga har väntat så länge på att få ett lås, avbryter Postgres körningen av denna fråga och loggar ett felmeddelande:

2021-01-30 09:35:52.415 UTC [67] psql postgres testdb 172.17.0.1 ERROR:  canceling statement due to lock timeout
2021-01-30 09:35:52.415 UTC [67] psql postgres testdb 172.17.0.1 STATEMENT:  cluster t;

Låt oss säga att du vill ställa in en tidsgräns för låsning på 1 minut, men logga frågor som väntar på låsningar i mer än till exempel 30 sekunder. Du kan göra detta med:

log_lock_waits = on
deadlock_timeout = 30s

Detta kommer att skapa loggar så här:

2021-01-30 09:49:22.331 UTC [70] psql postgres testdb 172.17.0.1 LOG:  process 70 still waiting for ShareLock on transaction 493 after 30009.004 ms
2021-01-30 09:49:22.331 UTC [70] psql postgres testdb 172.17.0.1 DETAIL:  Process holding the lock: 68. Wait queue: 70.
2021-01-30 09:49:22.331 UTC [70] psql postgres testdb 172.17.0.1 CONTEXT:  while locking tuple (0,3) in relation "t"
2021-01-30 09:49:22.331 UTC [70] psql postgres testdb 172.17.0.1 STATEMENT:  select * from t for update;

Användningen av deadlock_timeout är inte ett stavfel:det är värdet som låsets väntaloggningsmekanism använder. Helst borde det ha funnits något som log_min_duration_lock_wait ,men det är tyvärr inte fallet.

I händelse av faktiska dödlägen kommer Postgres att avbryta den låsta transaktionen efter deadlock_timeout varaktighet och loggar de kränkande uttalandena. Ingen explicit konfiguration är nödvändig.

2021-01-30 09:55:37.724 UTC [68] psql postgres testdb 172.17.0.1 LOG:  process 68 detected deadlock while waiting for ShareLock on transaction 496 after 30007.633 ms
2021-01-30 09:55:37.724 UTC [68] psql postgres testdb 172.17.0.1 DETAIL:  Process holding the lock: 70. Wait queue: .
2021-01-30 09:55:37.724 UTC [68] psql postgres testdb 172.17.0.1 CONTEXT:  while locking tuple (0,3) in relation "t"
2021-01-30 09:55:37.724 UTC [68] psql postgres testdb 172.17.0.1 STATEMENT:  select * from t where a=4 for update;
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 ERROR:  deadlock detected
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 DETAIL:  Process 68 waits for ShareLock on transaction 496; blocked by process 70.
        Process 70 waits for ShareLock on transaction 495; blocked by process 68.
        Process 68: select * from t where a=4 for update;
        Process 70: select * from t where a=0 for update;
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 HINT:  See server log for query details.
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 CONTEXT:  while locking tuple (0,3) in relation "t"
2021-01-30 09:55:37.725 UTC [68] psql postgres testdb 172.17.0.1 STATEMENT:  select * from t where a=4 for update;

Logga autovacuums

Autovakuumprocessen startar när Postgres fastställer att data i en tabell har ändrats tillräckligt för att motivera ett vakuum och analysera. För att hålla ett öga på den här processen, aktivera loggning av autovakuumkörningar:

log_autovacuum_min_duration = 250ms

Här är ett exempel på posten som orsakades av överdrivna ändringar i en tabell:

2021-01-30 10:23:33.201 UTC [63]     LOG:  automatic vacuum of table "postgres.public.t": index scans: 0
        pages: 0 removed, 95 remain, 0 skipped due to pins, 0 skipped frozen
        tuples: 8991 removed, 10000 remain, 0 are dead but not yet removable, oldest xmin: 492
        buffer usage: 215 hits, 4 misses, 4 dirtied
        avg read rate: 1.885 MB/s, avg write rate: 1.885 MB/s
        system usage: CPU: user: 0.01 s, system: 0.00 s, elapsed: 0.01 s
        WAL usage: 244 records, 1 full page images, 67984 bytes
2021-01-30 10:23:33.222 UTC [63]     LOG:  automatic analyze of table "postgres.public.t" system usage: CPU: user: 0.01 s, system: 0.00 s, elapsed: 0.01 s

Observera att autovakuum vanligtvis utlöser en analys efter vakuumet, och detta kommer också att loggas.

Dessa loggar hjälper dig att ta reda på hur du bäst justerar parametrarna för autovakuum och hjälper dig att undersöka om och när autovakuum inte är så effektivt som du trodde det skulle vara.

Loggningskontrollpunkter

Checkpointing är processen att trycka in WAL-loggade ändringar i de faktiska filerna som backar tabellerna. Helst bör kontrollpunkter ske med regelbundna och inte alltför frekventa intervall, eftersom det är en CPU- och diskintensiv process. Av olika anledningar tvingas även kontrollpunkter att ske före nästa schemalagda tidpunkt, och detta resulterar i minskad frågeprestanda.

För att hålla ett öga på kontrollpunkters frekvens och effektivitet, aktivera loggning av kontrollpunkter:

log_checkpoints = on

Detta talar om för PostgreSQL att logga följande när en kontrollpunkt inträffar:

2021-01-30 10:05:57.085 UTC [56]     LOG:  checkpoint starting: immediate force wait
2021-01-30 10:05:57.159 UTC [56]     LOG:  checkpoint complete: wrote 0 buffers (0.0%); 0 WAL file(s) added, 0 removed, 0 recycled; write=0.000 s, sync=0.000 s, total=0.074 s; sync files=0, longest=0.000 s, average=0.000 s; distance=0 kB, estimate=0 kB

Den första raden innehåller flaggorna som backend skickade till checkpointern. Du kan se att "styrkan" orsakade en kontrollpunkt även om det inte fanns några väntande ändringar av kontrollpunkten. Om "omedelbar" inte hade specificerats, skulle kontrollpunkten ha gått upp till checkpoint_completion_target .

Andra inställningar på serversidan

Det finns ett par andra inställningar som du kan aktivera i din PostgreSQL-konfiguration som hjälper dig att diagnostisera problem:

  • track_io_timing - ställ in detta på låter dig se tiden för indisk I/O för varje fråga (i kombination med pg_stat_statements-tillägget som beskrivs nedan). Se dokumentet om en varning för att aktivera detta, men bör vara säkert på nästan alla moderna Linux. Att se en frågas disk I/O-kostnad är omöjligt utan att aktivera detta.
  • track_commit_timestamp - ställ in detta på kan vara användbar vid felsökning av replikeringsfördröjningar och andra replikeringsrelaterade problem.

Frågestatistik via pg_stat_statements

Tillägget pg_stat_statements är ett viktigt tillbehör för alla PostgreSQL-installationer. Den samlar in och registrerar statistik för varje exekverad fråga och presenterar den som en vy som kallas "pg_stat_statements". Detta är ett tillägg, vilket innebär att du måste installera det explicit i varje databas som du vill ha data för, med hjälp av kommandot:

CREATE EXTENSION pg_stat_statements;

Eftersom tillägget är beroende av en .so måste du ladda det med shared_preload_libraries :

shared_preload_libraries = 'pg_stat_statements'

Detta kräver tyvärr en omstart av PostgreSQL-servern; så se till att du gör detta innan du går live.

Om du har uppgraderat från en tidigare version av PostgreSQL, se till att uppgradera ditt pg_stat_statement-tillägg också med:

ALTER EXTENSION pg_stat_statements UPDATE;

Tillägget pg_stat_statements loggar ingenting, det används via querying vyn med samma namn. För mer information, se den officiella dokumentationen.

Frågeexekveringsplaner via auto_explain

auto_explain är en annan tillägg som finns i kärnan PostgreSQL. Det kan logga exekveringsplanerna för långsamma frågor. Det behöver bara läggas till ishared_preload_libraries , och behöver inte installeras som en tillägg. Den har också ett par andra alternativ som vanligtvis måste ställas in på icke-standardvärden:

shared_preload_libraries = 'pg_stat_statements,auto_explain'

auto_explain.log_min_duration = 1s
auto_explain.log_analyze = on
auto_explain.log_buffers = on
auto_explain.log_triggers = on
auto_explain.log_timing = on
auto_explain.log_verbose = on
auto_explain.log_format = json

Ovanstående loggar exekveringsplanen för alla frågor som tar mer än 1 sekund att slutföra. Här är ett exempel på utdata:

2021-01-30 11:28:25.977 UTC [64] psql postgres postgres 172.17.0.1 LOG:  duration: 1.305 ms  plan:
        {
          "Query Text": "SELECT n.nspname as \"Schema\",\n  c.relname as \"Name\",\n  CASE c.relkind WHEN 'r' THEN 'table' WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized view' WHEN 'i' THEN 'index' WHEN 'S' TH
EN 'sequence' WHEN 's' THEN 'special' WHEN 'f' THEN 'foreign table' WHEN 'p' THEN 'table' WHEN 'I' THEN 'index' END as \"Type\",\n  pg_catalog.pg_get_userbyid(c.relowner) as \"Owner\"\nFROM pg_catalog.pg_class c
\n     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\nWHERE c.relkind IN ('r','p','v','m','S','f','')\n      AND n.nspname <> 'pg_catalog'\n      AND n.nspname <> 'information_schema'\n      AND
n.nspname !~ '^pg_toast'\n  AND pg_catalog.pg_table_is_visible(c.oid)\nORDER BY 1,2;",
          "Plan": {
            "Node Type": "Sort",
            "Parallel Aware": false,
            "Startup Cost": 32.93,
            "Total Cost": 33.01,
            "Plan Rows": 32,
            "Plan Width": 224,
            "Actual Startup Time": 1.292,
            "Actual Total Time": 1.298,
            "Actual Rows": 0,
[... lots of text snipped ...]

För att lära dig mer om auto_explain, se de officiella dokumenten.

Tilläggen pg_stat_statements och auto_explain är de enda två brett stödda alternativen som PostgreSQL har för hantering av frågeprestanda och frågeplanshantering. Det lönar sig att lära känna dessa två funktioner och planera framåt för att använda dem i produktionen.

Applikationsnamn

Programnamnet är en parameter på klientsidan och kan vanligtvis ställas in iDSN:er eller libpq-anslutningssträngar som din applikation använder för anslutningsinformation. Många verktyg och verktyg i PostgreSQL eco-systemet förstår programnamnet, och det hjälper till att ställa in detta till ett meningsfullt värde, till exempel:

application_name = weekly-revenue-report

Detta skulle ställas in för varje klientapplikation som ansluter till din PostgreSQLserver.


  1. Övervaka dina databaser med MySQL Enterprise Monitor

  2. Hur man hanterar booleska värden i SQLite med JavaScript-proxies

  3. Hur kör man ett SSIS-paket från .NET?

  4. Installera Apache, MySQL 8 eller MariaDB 10 och PHP 7 på CentOS 7