sql >> Databáze >  >> RDS >> PostgreSQL

Konfigurace PostgreSQL pro pozorovatelnost

PostgreSQL přichází s velkým množstvím konfiguračních možností, ale změna výchozího nastavení některých z těchto možností výrazně zlepšuje pozorovatelnost vašeho PostgreSQL serveru. Tyto možnosti budete chtít nastavit a nakonfigurovat dříve, než se v produkci objeví problémy, protože mohou poskytnout informace nezbytné pro pochopení a řešení těchto problémů.

Čtěte dále a zjistěte více o nastaveních a rozšířeních, která odhalují metriky a informace o vnitřním fungování vašeho PostgreSQL serveru.

Předpona řádku protokolu

log_line_prefix konfigurační volba určuje, co PostgreSQL zapíše na začátek každého řádku protokolu. Výchozí nastavení závisí na konkrétní linuxové distribuci nebo spravovaném řešení, které používáte, ale častěji neobsahuje několik položek, které se mohou ukázat jako velmi užitečné při sledování neslušných klientů. Zkuste tento log_line_prefix :

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

Zahrnuje časové razítko (%m ), PID backendového procesu (%p ), název aplikace (%a ) klienta, uživatelské jméno, se kterým se klient připojil (%u ), databáze, ke které se klient připojil (%d ) a název hostitele nebo IP, odkud připojení přichází (%h ). Výsledkem jsou tyto loglines:

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;

které jsou mnohem užitečnější než výchozí. Můžete vidět, že se klient připojil z 172.17.0.1 jako uživatel postgres do databáze bench a aplikace byla psql . Rozhodně zlepšení oproti výchozí možnosti, která zobrazuje pouze toto:

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;

Protokolování pomalých dotazů

PostgreSQL lze nakonfigurovat tak, aby protokoloval dotazy, jejichž provedení trvá déle než stanovený čas. Tyto jdou do stejného souboru protokolu; neexistuje žádný samostatný soubor protokolu pomalého dotazu jako v MySQL.

Chcete-li protokolovat příkazy, jejichž provedení trvá déle než 1 sekundu, použijte log_min_duration_statement možnost takto:

log_min_duration_statement = 1s

Všimněte si, že log_min_duration_statement zváží všechny příkazy (včetně například dlouhotrvajících příkazů správce jako REINDEX TABLE ) a nikoli pouze dotazy (SELECT ). Zde jsou některé položky protokolu vytvořené touto volbou:

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);

Pokud to povede k příliš velkému počtu protokolů podobných prohlášení, můžete Postgres tologu sdělit pouze procento z nich pomocí:

log_min_duration_statement = -1
log_min_duration_sample = 1s
log_statement_sample_rate = 0.25

Tím se zaprotokoluje pouze 25 % příkazů, které lze protokolovat (příkazy, jejichž provedení trvalo déle než 1 sekundu). Výstup protokolu je stejný jako předtím. Neexistuje způsob, jak zjistit, kolik vhodných příkazů nebylo protokolováno.

Chcete-li zaprotokolovat všechny příkazy spolu s časem, který je potřeba k jejich provedení, použijte příkaz_protokol možnost místo toho:

log_statement = mod
log_duration = on

Možnost „mod“ říká Postgresu, aby protokoloval DDL a příkazy upravující data. Výsledkem jsou protokoly jako tyto:

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

Upozorňujeme, že není Pokud je takto povoleno protokolování vzorových příkazů, všechny příkazy se zaprotokolují a vy skončíte se spoustou záznamů v protokolu.

Zámky protokolování a uváznutí

Dotazy mohou na získání zámku čekat příliš dlouho. Obvykle se horní limit doby čekání nastavuje pomocí volby lock_timeout , obvykle na straně klienta. Pokud dotaz na získání zámku čekal tak dlouho, Postgres zruší provádění tohoto dotazu a zaznamená chybu:

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;

Řekněme, že chcete nastavit časový limit zámku na 1 minutu, ale protokolujte dotazy, které čekají na uzamčení déle než, řekněme 30 sekund. Můžete to udělat pomocí:

log_lock_waits = on
deadlock_timeout = 30s

Tím se vytvoří protokoly jako tento:

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;

Použití deadlock_timeout není překlep:je to hodnota, kterou používá mechanismus čekání na zámek. V ideálním případě by tam mělo být něco jako log_min_duration_lock_wait ,ale bohužel tomu tak není.

V případě skutečných uváznutí Postgres přeruší uvázlé transakce po deadlock_timeout trvání a zaprotokoluje problematické výroky. Je nutná neexplicitní konfigurace.

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;

Protokolování automatických vakuů

Proces autovakuování se spustí, když Postgres zjistí, že data v tabulce se dostatečně změnila, aby zaručila vakuum a analýzu. Chcete-li tento proces sledovat, povolte protokolování běhů automatického vakua:

log_autovacuum_min_duration = 250ms

Zde je ukázkový záznam, který byl způsoben nadměrnými změnami jedné tabulky:

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

Všimněte si, že autovakuum obvykle spustí analýzu po vakuu a to bude také zaznamenáno.

Tyto protokoly vám pomohou zjistit, jak nejlépe vyladit parametry autovakua, a pomohou vám zjistit, zda a kdy automatické vakuování není tak účinné, jak jste si mysleli.

Kontrolní body protokolování

Kontrolní bod je proces protlačování změn zaznamenaných WAL do skutečných souborů, které jsou v tabulce. V ideálním případě by se kontrolní body měly vyskytovat v pravidelných a nepříliš častých intervalech, protože jde o proces náročný na CPU a disk. Z různých důvodů jsou kontrolní body také nuceny nastat před dalším naplánovaným časem, což má za následek snížený výkon dotazů.

Chcete-li sledovat frekvenci a efektivitu kontrolních bodů, povolte protokolování kontrolních bodů:

log_checkpoints = on

To říká PostgreSQL, aby při každém kontrolním bodu zaprotokolovalo následující:

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

První řádek obsahuje příznaky, které backend předal kontrolnímu ukazateli. Můžete vidět, že „síla“ způsobila kontrolní bod, i když v kontrolním bodu nebyly žádné čekající změny. Pokud by nebylo zadáno „okamžité“, kontrolní bod by směřoval až k checkpoint_completion_target .

Další nastavení na straně serveru

Existuje několik dalších nastavení, která můžete zapnout v konfiguraci PostgreSQL a která vám pomohou s diagnostikou problémů:

  • track_io_timing - nastavte toto na zapnuto umožňuje zobrazit čas strávený indisk I/O pro každý dotaz (v kombinaci s rozšířením pg_stat_statements popsaným níže). Viz docs o upozornění na toto zapnutí, ale mělo by být bezpečné na téměř každém moderním Linuxu. Bez tohoto zapnutí není možné zobrazit vstupní/výstupní náklady na disku.
  • track_commit_timestamp - nastavte toto na zapnuto může být užitečné při ladění zpoždění replikace a dalších problémech souvisejících s replikací.

Statistiky dotazů prostřednictvím pg_stat_statements

Rozšíření pg_stat_statements je nezbytným příslušenstvím pro jakékoli nasazení PostgreSQL. Shromažďuje a zaznamenává statistické údaje pro každý provedený dotaz a prezentuje je jako pohled nazvaný „pg_stat_statements“. Toto je rozšíření, což znamená, že jej musíte explicitně nainstalovat do každé databáze, pro kterou chcete data, pomocí příkazu:

CREATE EXTENSION pg_stat_statements;

Protože rozšíření závisí na .so , budete je muset načíst pomocíshared_preload_libraries :

shared_preload_libraries = 'pg_stat_statements'

To bohužel vyžaduje restart PostgreSQL serveru; tak se ujistěte, že to uděláte před spuštěním.

Pokud jste provedli upgrade z předchozí verze PostgreSQL, nezapomeňte také upgradovat své rozšíření pg_stat_statement pomocí:

ALTER EXTENSION pg_stat_statements UPDATE;

Rozšíření pg_stat_statements nic neloguje, používá se prostřednictvím dotazování na stejnojmenný pohled. Další podrobnosti naleznete v oficiální dokumentaci.

Plány provádění dotazů prostřednictvím auto_explain

auto_explain je další rozšíření přítomné v základním PostgreSQL. Může zaznamenávat plány provádění pomalých dotazů. Stačí jej přidat doshared_preload_libraries , a není třeba jej instalovat jako rozšíření. Má také několik dalších možností, které je obvykle nutné nastavit na jiné než výchozí hodnoty:

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

Výše uvedené protokoluje plán provádění pro jakýkoli dotaz, jehož dokončení trvá déle než 1 sekundu. Zde je ukázkový výstup:

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 ...]

Další informace o funkci auto_explain naleznete v oficiálních dokumentech.

Rozšíření pg_stat_statements a auto_explain jsou jediné dvě široce podporované možnosti, které má PostgreSQL pro správu výkonu dotazů a správu plánu dotazů. Vyplatí se seznámit se s těmito dvěma funkcemi a předem si naplánovat jejich použití ve výrobě.

Název aplikace

Název aplikace je parametr na straně klienta a obvykle lze nastavit připojovací řetězce ve stylu inDSN nebo libpq, které vaše aplikace používá pro informace o připojení. Mnoho nástrojů a pomůcek v eko systému PostgreSQL rozumí názvu aplikace a pomáhá to nastavit na smysluplnou hodnotu, například:

application_name = weekly-revenue-report

Toto by bylo nastaveno pro každou klientskou aplikaci, která se připojuje k vašemu PostgreSQLserveru.


  1. Jak mohu použít dotaz se zástupným symbolem uvnitř uvozovek? (perl / postgresql)

  2. Prohledejte všechny sloupce tabulky pomocí jediné podmínky where s jedním klíčovým slovem v mysql

  3. Jak získat den v roce z data v PostgreSQL

  4. Jak FIND_IN_SET() funguje v MariaDB