- Q1. Má PG schopnost ukládat do mezipaměti/ohřívat vztah?
- Q2. Je možné vrátit se do předchozího stavu mezipaměti, kde byla ponechána před vypnutím databázového serveru z důvodu údržby?
V dřívějších verzích PostgreSQL neexistovala žádná šance na zahřátí vztahu nebo uložení stavů mezipaměti, ale od PostgreSQL 9.4 a výše byly všechny výše uvedené dotazy (Q1,Q2) adresovány dvěma moduly contrib pg_prewarm a pg_hibernator . Navzdory samotnému faktu, že se vyznačují praktičností, tato kombinace se zdá být pro DBA v budoucnu extrémně životaschopná a užitečná. Stručně o příspěvku:
pg_prewarm contrib (Autor:Robert Haas), poskytuje možnost načíst relační data do mezipaměti vyrovnávací paměti operačního systému nebo vyrovnávací paměti PG. Má funkci prvního nebo posledního čísla bloku pro předehřátí. (Poznámka:Nemá žádnou speciální ochranu na předem zahřátá data před vyřazením mezipaměti a také pokud je instance databáze restartována a pak je potřeba znovu zahřát na vztahy).
pg_hibernator contrib (Autor:Gurjeet Singh), poskytuje schopnost automaticky uložit seznam obsahu sdílené vyrovnávací paměti na disk při vypnutí databáze a automaticky obnovovat vyrovnávací paměti při spuštění databáze, podobně jako ukládání/obnovení snímku sdílených_bufferů. Využívá modul PG 9.3 k registraci „pracovního procesu na pozadí“ a vytvoří dva procesy „Buffer Saver“, „Buffer Reader“ pro uložení/obnovu. Zajímavé je, že s trochou hacku může pg_hibernator také umožnit pohotovostnímu slave začít obsluhovat dotazy plnou rychlostí se stejným obsahem master, uvidí to za minutu :).
Nakonec potřebujeme pg_buffercache modulu pro nahlédnutí do aktuálního obsahu sdílených_bufferů PostgreSQL. Tento modul pomáhá pochopit, jaké procento vyrovnávací paměti zabírá vztah.
Zapojme všechny tyto příspěvky do hry a podívejme se, jak slouží účelu dvou otázek (Q1,Q2). Na svém místním virtuálním počítači použiji tabulku „foo“ o velikosti 885 MB spolu se standardním dotazem pg_buffercache.
SELECT c.relname,
count(*) AS buffers
FROM pg_class c
INNER JOIN pg_buffercache b ON b.relfilenode=c.relfilenode AND c.relname='foo'
INNER JOIN pg_database d ON (b.reldatabase=d.oid AND d.datname=current_database())
GROUP BY c.relname
ORDER BY 2 DESC LIMIT 10;
Použití pg_prewarm contrib a warming ‘foo’ table.
postgres=# vytvořit rozšíření pg_prewarm;
VYTVOŘIT ROZŠÍŘENÍ
postgres=# dt+
Seznam vztahů
Schéma | Jméno | Typ | Majitel | Velikost | Popis
--------+------+-------+----------+--------+- ------------
veřejné | foo | stůl | postgres | 885 MB |
(1 řádek)
postgres=# select pg_prewarm('foo');
pg_prewarm
-------------
113278
(1 řádek)
--pg_buffercache výstup dotazu
relname | nárazníky
---------+---------
foo | 113278
(1 řádek)Velmi jednoduché a přímočaré použití pg_prewarm s výstupem bloků zahřátých ve sdílených_bufferech pro vztah „foo“. Z pg_buffercache výstup dotazu můžeme vyhodnotit, že existuje 113278 (113278 * 8 / 1024 =884 MB ) vyrovnávacích pamětí o velikosti 8KB bloku relace ‚foo‘, která se shoduje s výstupem pg_prewarm. Pokud se server Postgres z nějakého důvodu restartuje, sdílené vyrovnávací paměti jsou prázdné a DBA se musí znovu zahřát, aby se vrátil do předchozí teplé fáze. U jednoho stolu je opětovné zahřátí vždy jednoduché, kromě agónie skupiny stolů.
V tomto okamžiku můžeme využít pg_hibernator contrib, protože má flexibilitu uložit obsah sdíleného_bufferu a obnovit jej při spuštění. Pojďme společně povolit pg_hibernator/pg_prewarm a spustit podobné cvičení jednoduchým zahrnutím jednoho kroku restartu a zjistit, zda se stav mezipaměti vrátí tak, jak je, nebo ne. Nebudu se zabývat instalací pg_hibernator, protože na gitu je to velmi dobře popsáno, ale skočil bych přímo do implementační části a spustil server s pg_hibernator.
postgres 24623 1 0 02:06 pts/4 00:00:00 /usr/local/pgpatch/pg/bin/postgres -D /usr/local/pgpatch/pg/data_10407
postgres 24627 24623 02:06? 00:00:00 postgres:logger process
postgres 24631 24623 0 02:06 ? 00:00:00 postgres:proces kontrolního ukazatele
postgres 24632 24623 0 02:06 ? 00:00:00 postgres:proces spisovatele
postgres 24633 24623 0 02:06 ? 00:00:00 postgres:proces wal spisovatel
postgres 24634 24623 0 02:06 ? 00:00:00 postgres:proces autovakuového spouštěče
postgres 24635 24623 0 02:06 ? 00:00:00 postgres:proces archivace
postgres 24636 24623 0 02:06 ? 00:00:00 postgres:proces sběru statistik
postgres 24637 24623 0 02:06 ? 00:00:00 postgres:bgworker:Buffer Saver
postgres 24638 24623 11 02:06 ? 00:00:01 postgres:bgworker:Block Reader 2
V protokolech databázového serveru při spuštění:
-bash-4.1$ více postgresql-2014-06-02_083033. log
LOG:databázový systém byl vypnut 2014-06-02 08:13:00 PDT
LOG:spouštění pracovního procesu na pozadí "Buffer Saver"
LOG:databázový systém je připraven přijmout připojení
LOG:Autovakuový spouštěč spuštěnVzhledem k tomu, že je pg_hibernator poprvé ve hře, můžete vidět dva procesy a také protokoly s některými informacemi o spuštění „Buffer Saver“. Nyní předehřejeme vztah ‚foo‘ a restartujeme server, později zkontrolujeme stav vyrovnávací paměti, zda pg_hibernator zaplnil vyrovnávací paměť zpět tam, kde zůstal.
-bash-4.1$ psql -p 10407
psql (9.4beta1)
Nápovědu získáte zadáním "help".
postgres=# select pg_prewarm('foo');
pg_prewarm
------------
113278
(1 řádek)
--pg_buffercache výstup dotazu
přejmenovat | nárazníky
---------+---------
foo | 113278
(1 řádek)
postgres=# q
-bash-4.1$ /usr/local/pgpatch/pg/bin/pg_ctl -D /usr/local/pgpatch /pg/data_10407 stop
čekání na vypnutí serveru.... hotovo
server zastaven
-bash-4.1$ ls -l $PGDATA/pg_hibernator/
celkem 12
-rw------- 1 postgres postgres 160 3. června 01:41 1.global.save
-rw------- 1 postgres postgres 915 3. června 01 :41 2.postgres.save
-bash-4.1$ /usr/local/pgpatch/pg/bin/pg_ctl -D /usr/local/pgpatch/pg/data_10407 start
server začínáRestartovali jsme databázový server, prozkoumáme protokoly
-bash-4.1$ více postgresql-2014-06-03_020601.log
LOG:databázový systém byl vypnut 3. 6. 2014 02:05:57 PDT
LOG:spouštění pracovníka na pozadí proces "Buffer Saver"
LOG:databázový systém je připraven přijímat připojení
LOG:spouštěč automatického vakua spuštěn
LOG:registrace pracovníka na pozadí "Block Reader 2"
LOG:spouštění pracovníka na pozadí proces "Block Reader 2"
LOG:Block Reader 2:obnoveno 113433 bloků
LOG:Block Reader 2:všechny bloky byly úspěšně přečteny
LOG:pracovní proces:Block Reader 2 (PID 24638) ukončeno s návratovým kódem 1
LOG:zrušení registrace pracovníka na pozadí "Blokovat čtečku 2"
LOG:registrace pracovníka na pozadí "Blokovat čtečku 1"
LOG:spuštění procesu pracovníka na pozadí "Blokovat čtečku 1"
LOG:Čtečka bloku 1:obnoveno 20 bloků
LOG:Čtečka bloku 1:všechny bloky byly úspěšně přečteny
LOG:pracovní proces:Čtečka bloku 1 (PID 24664) ukončena s návratovým kódem 1
LOG :zrušení registrace pracovníka na pozadí "Blokovat čtení er 1"Takže „Buffer Reader“ obnovil bloky 113433 + 20, z nichž 113278 patří do vztahu „foo“. Skvělé, pojďme se připojit a uvidíme.
-bash-4.1$ psql -p 10407
psql (9.4beta1)
Nápovědu zobrazíte zadáním "help".
--pg_buffercache výstup dotazu
relname | nárazníky
---------+---------
foo | 113278
(1 řádek)Skvělé… pg_hibernator obnovil stav zahřátí mezipaměti bez zásahu DBA.
Další dobrá věc na pg_hibernator je, že nově vytvořený pohotovostní režim může mít stejný sdílený obsah vyrovnávací paměti jako hlavní, takže pohotovostní režim může začít obsluhovat dotazy plnou rychlostí. Abych provedl toto cvičení, při zálohování adresáře $PGDATA jsem předal SIGTERM procesu „Buffer Saver“, aby zapsal aktuální stav share_buffers obsahu na disk (adresář $PGDATA/pg_hibernator) a poté následoval pohotovostní nastavení.
postgres 24637 24623 0 02:06 ? 00:00:00 postgres:bgworker:Buffer Saver
postgres 24653 15179 0 02:06 ? 00:00:01 postgres:wal receiver proces streaming 1/6A000A10
postgres 24654 24623 0 02:06 ? 00:00:00 postgres:proces odesílatele wal postgres ::1(65011) streamování 1/6A000A10Po nastavení můj slave začal se stejným obsahem primárního
-bash-4.1$ psql -p 10477
psql (9.4beta1)
Nápovědu získáte zadáním „nápovědy“.
postgres=# select pg_is_in_recovery();
pg_is_in_recovery
-------------------
t
(1 řádek)
--pg_buffercache výstup dotazu
relname | nárazníky
---------+---------
foo | 113278
(1 řádek)Děkuji oběma autorům za skvělé rozšíření o ukládání do mezipaměti.