db.dobo.sk

Postgres – vsetko, co si chtel vediet, ale bal sa spytat svojho seniora, aby si nevypadal ako jelito 04. Wal logy.

bez komentára

Wal logy su REDO logy, alebo inak boli nazyvane aj Xlogy, a su to vlastne transakcne logy :). Takze teraz poporiadku – co su v Oracle REDO logy, su v Postgrese WAL logy. Do verzie 10 v tom bol naming chaos, nakolko sa nazyvali Xlogy.

Princip

Princip WAL logov je zalozeny na myslienke, ze ked databaza zbuchne, tak transakcie, ktore nie su zapisane do datafilov (su zatial v shared buffer pool), su zachranene, lebo su zapisane do redo logov a preto sa po zbuchnuti daju obnovit. Podobne, ak pride k chybe pri zapise do datafilov a tie su corrupted, tak sa da vratit k poslednemu checkpointu a dohrat to WAL logmi. WAL znamena Write Ahead Log. Otazka – no a aky je rozdiel medzi zapisom do datafilov a do wal logov? V podstate ziadny, okrem rychlosti. Takze wal logy garantuju urcitu bezpecnost dat bez znizenia performance:

  1. wal segmenty sa zapisuju do binarneho suboru logu sekvencne (za sebou) a nie random I/O, ako v pripade zapisu na disk (checkpointu), preto je to hrozne rychle.
  2. zapisuju sa tu len delty dat, jednotlive transakcie a nie cely blok dat ako v pripade datafilu, preto je to tak rychle. Checkpoint prepise cele bloky dat v datafilu, walwriter len transakcnu zmenu.
  3. zapis do wal logu sa vykonava okamzite po nejakej zmene – ovsem pred potvrdenim transakcie. To preto, aby boli zmeny neakceptovane v pripade padu databaze (= commit sa “odohraje” az ked je zmena zapisana do wal logu)
  4. wal record sa uklada do wal logu pomocou systemoveho fsync
  5. statistiky WAL zurnalu je dobre cekovat viewom SELECT * FROM pg_stat_wal;

vztah commitu a wal logu

Postupnost zapisu a vztah ku commitu je klucovy pre durabilitu dat a konzistenciu udajov (= klientovi nie je potvrdeny commit pokial to nie je bezpecne ulozene do wal logu):

  1. spusti sa transakcia, nieco robi (napr. INSERT), je viditelna len pre tento proces. Wal writer urobi zaznam do wal logu “tu bolo insertnute toto”
  2. postgresql proces to zapise, ale fakticky to nie je commitnute, pokial wal writer nepotvrdi, ze je to ulozene vo wal logu (synchronous_commit = on —> default nastavenie, ale da sa zrusit!)
  3. ked to wal writer potvrdi, postgres oznaci transakciu za commitnutu (viditelnu pre inych uzivatelov) a klientovi povrdi uspesny COMMIT

WAL a LSN

Log Sequence Number (LSN) je číselná hodnota, ktorá označuje určitú pozíciu v WAL logu. Vlastnosti:

  1. LSN predstavuje byte offset od začiatku WAL logu a používa sa na označovanie jednotlivých záznamov. Ukazuje na presnu poziciu v ramci WAL logu (napr 0/162C1D28 ukazuje, ze ide o segment 0000001 a hexa poziciu 162C1D28)
  2. Záznamy v WAL logu sú ukladané sekvenčne, takže každý záznam má unikátne LSN.
  3. Kazda commit transakcie ma vlastne LSN
  4. LSN ma velky vyznam pre replikacie, kde si procesy na jeho zaklade overuju, co bolo a co nie odreplikovane.
  5. LSN sa uklada aj do checkpointu a podla toho DB pri obnove vie, odkial ma dohrat udaje z WALu.

Jak zistit aktualny LSN: SELECT pg_current_wal_lsn();
Jak zistit posledny LSN checkpointu: SELECT checkpoint_lsn FROM pg_control_checkpoint();

Jak zistit, o kolko je replika za masterom:

SELECT pg_wal_lsn_diff(
pg_current_wal_lsn(),
replay_location
) FROM pg_stat_replication;

 

Ako citat obsah WALu

No, je to kvoli efektivite binarny zapis, takze priamociaro to nejde. V zasade poznam 3 postupy:

  1. pomocou utility pg_waldump. Priklad: co bolo zmenene transakciou 123456:  pg_waldump | grep "tx: 123456"
  2. pomocou pg_walinspect
  3. pomocou logical decoding, funkciou pg_logical_slot_get_changes. Cely postup:
  • je nutne vytvorit replikacny slot: SELECT pg_create_logical_replication_slot('test_slot', 'test_decoding');
  • je mozne citat priamo SQL zaznamy na pozicii slotu: SELECT * FROM pg_logical_slot_get_changes('test_slot', NULL, NULL);

Struktura WAL logu

Najdolezitejsi part wal logu je tzv. XLOG record – de facto zmenovy datovy udaj, sparovany s LSN. Wal logy obsahuju aj udaj o checkpointe (kedy a kde), t.j. kedy bol naposledy zapisany do datovych fajlov REDO point.

Wal logy su 16 MB subory, ich nazov sa vytvara pomocou tejto kuzelnej formulky:

WAL segment file name=timelineId+(uint32)LSN/116M∗256+(uint32)(LSN/116M)%256

postgres_wal

Procesy

Wal writer – zapisovac XLOG zaznamov do wal logov. Defaultne kazdych 200 milisekund a neda sa disablovat (len zmenit interval v konfiguraku)

Checkpoint proces zapisuje checkpointy z wal logov a to defaultne kazdych x sekund (premenna checkpoint_timeout), alebo ked stupne velkost wal logov nad x GB  (premenna max_wal_size). Okrem toho, ze zapise REDO point do storage, zapise ho aj do pg_control filu, ktory je klucovy v pripade restoru. Pozor, pg_control je binarny subor, cita sa utilitou pg_controldata

checkpoint

Checkpoint je zapis spinavych pamatovych bufferov (shared buffers) do datafilov. Je to metoda, jak urobit data persistent (napr. pri vypadku prudu; aj ked to nie je uplne pravda, pretoze data su uz zapisane vo WAL logoch) a hlavne urobit bod, z ktoreho sa bude pripadne databaza recoverovat. Z zasade existuju 2 druhy checkpointov:

  • timed checkpoint = zapisuje sa pravidelne v intervale definovanom v postgresql.conf
  • requested checkpoint = zapisuje, pokial sa naplni (a switchne) WAL log, alebo pokial sa checkpoint vynuti prikazom CHECKPOINT; requested checkpointov by malo byt radovo mensi pocet, nez timed

Ako prebieha zapis checkpointu:

  • robi ho proces checkpointer, ktory bude zapisovat len tie buffery, ktore su oznacene ako zmenene
  • samotny checkpoint je rozlozeny v case (checkpoint_completion_target) a postupne zapisuje.
  • start checkpointu je zapisany do WAL logu a do kontrolneho suboru (/global/pg_control) – bude tvorit bod, od ktoreho sa bude obnovovat po pripadnom pade
  • start aj dokoncenie checkpointu moze byt logovane (log_checkpoints = on)

WAL switching a archivacia

WAL logy sa switchuju (nieco ako logrotate), a to ked sa a) zaplni, b) ked sa zavola funkcia pg_switch_xlog, alebo c) alebo sa vyvola archivacia wal logu. Vzhladom na to, aku dolezitu ulohu maju WAL logy (je to zurnal vsetkych dat), tak je zahodno ich priebezne niekam archivovat a v pripade potreby (restore) opat nahrat do DB a tym sa dostat k ziadanemu bodu stavu DB. Odlievaniu logov sa odborne hovori wal archiving, ale v principe je to vlastne inkrementalny backup :). V pripade real-timoveho odlievania logov je to replikacia.

V okamihu, ked dojde ku switchu wal logu, alebo je evokovany komand archivovania, dojde k odlietiu wal logu na miesto zalohy. Je to konfigovane v hlavnom konfiguraku postgresql.conf a pouzivaju sa na to normalne unixove utility (e.g. archive_command = 'cp %p /home/postgres/wal_archives/%f'). Dobrou praxou je archivovat na nejaky bezpecny nfs share a tak.

Priklady:

# Copy the file to a safe location (like a mounted NFS volume)
archive_command = 'cp %p /mnt/nfs/%f'

# Not overwriting files is a good practice
archive_command = 'test ! -f /mnt/nfs/%f && cp %p /mnt/nfs/%f'

# Copy to S3 bucket
archive_command = 's3cmd put %p s3://BUCKET/path/%f'

# Copy to Google Cloud bucket
archive_command = 'gsutil cp %p gs://BUCKET/path/%f'

# An external script
archive_command = '/opt/scripts/archive_wal %p'

Ine dolezite parametre wal archivovania (v postgresql.conf):

  • v pripade externeho skriptu pouziteho pre archiving je dolezite, aby ho mohol spustit user postgres
  • wal log bude oznaceny ku zmazaniu, ak bol sprocesovany (odarchivovany) skriptom. Nie je tam nijaka pokrocila logika – skript musi vratit 0 a pokial nie, tak je znova  a znova spustany s nadejou, ze dobehne s 0
  • do skriptu je velmi uzitocne zapracovat podmienku proti prepisu wal logov s rovnakym menom
  • min_wal_size a max_wal_size – tymto obmedzenim je mozne udrziavat wal logy v rozumnej velkosti a vynucovat ich switchovanie v rozumnom case.

WAL level

wal_level  (v postgresql.conf) oznacuje typ struktury wal logu (minimal, replica, or logical), resp mnozstvo udajov, ktore je do logu zapisovane. Minimal poskytuje len zakladne datove udaje a staci pre obnovenie z crashu databaze, ale neumoznuje archiving (pokial je archive_mode = on, tak wal_level musi byt aspon replica). Replica je pre fyzicku replikaciu a PITR, logical level je vyzadovany pre logicku replikaciu:

 

píše: ďobo

August 5th, 2018 o 11:21 am

chlievik: postgresql

okomentuj