- Q1. Har PG förmågan att cache/värma en relation?
- Q2. Är det möjligt att återgå till tidigare cacheminne där det lämnades innan databasservern stängdes av på grund av underhåll?
I tidigare utgåvor av PostgreSQL finns det ingen chans att värma en relation eller lagra ett cachetillstånd, men från PostgreSQL 9.4 och framåt adresseras var och en av ovanstående frågor (Q1,Q2) med två bidragsmoduler pg_prewarm och pg_hibernator . Trots det faktum att de är särskiljande i praktiken verkar kombinationen vara extremt lönsam och användbar i framtiden för DBA:s. Kort sagt om bidrag:
pg_prewarm contrib (Författare:Robert Haas), ger möjlighet att ladda en relationsdata till OS-buffertcache eller PG-buffertcache. Den har funktionen som första eller sista blocknummer för att förvärma. (Obs:Den har inget speciellt skydd på förvärmda data från cacheavkastning och även om databasinstansen startas om så behövs återuppvärmning på relationerna).
pg_hibernator contrib (Författare:Gurjeet Singh), ger möjligheten att automatiskt spara listan med delad buffertinnehåll på disk när databasen stängs av, och automatiskt återställer buffertarna vid databasens start, ungefär på samma sätt som att spara/återställa en ögonblicksbild av shared_buffers. Den använder PG 9.3-modulen för att registrera "bakgrundsarbetarprocess" och skapar två processer "Buffertsparare", "Buffertläsare" för att spara/återställa. Intressant nog, med ett litet hack kan pg_hibernator också tillåta standby-slaven att börja betjäna frågor med full hastighet med samma innehåll som master, kommer att se det om en minut :).
Slutligen behöver vipg_buffercache modul för att titta in i det aktuella innehållet i PostgreSQL shared_buffers. Den här modulen hjälper till att förstå vilken procentandel buffert som upptas av en relation.
Låt oss sätta alla dessa bidrag i spel och se hur de tjänar syftet med två frågor (Q1, Q2). Jag kommer att använda en tabell "foo" av storleken 885 MB på min lokala virtuella dator, tillsammans med en standardfråga 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;
Användning av pg_prewarm contrib och värmande 'foo'-tabell.
postgres=# create extension pg_prewarm;
CREATE EXTENSION
postgres=# dt+
List of relations
Schema | Name | Type | Owner | Size | Description
--------+------+-------+----------+--------+-------------
public | foo | table | postgres | 885 MB |
(1 row)
postgres=# select pg_prewarm('foo');
pg_prewarm
------------
113278
(1 row)
--pg_buffercache query output
relname | buffers
---------+---------
foo | 113278
(1 row)
Mycket enkel och okomplicerad användning av pg_prewarm med en utmatning av block uppvärmda i shared_buffers för relation 'foo'. Från pg_buffercache frågeutgång kan vi utvärdera att det finns 113278 (113278 * 8 / 1024 =884MB ) buffertar på 8KB blockstorlek av relationen 'foo' som matchar med pg_prewarm-utgång. Här, om Postgres-servern startar om på grund av någon anledning, är shared_buffers tomma och DBA:s behov av att värmas upp igen för att komma tillbaka till tidigare varma stadium. För ett enskilt bord är det alltid enkelt att värma om, förutom för en grupp bord.
Vid det här laget kan vi använda pg_hibernator contrib, eftersom det har flexibiliteten att spara shared_bufferns innehåll och återställa det vid start. Låt oss aktivera pg_hibernator/pg_prewarm tillsammans och köra en liknande övning genom att helt enkelt inkludera ett steg för omstart och se om cachetillståndet återgår som det är eller inte. Jag tänker inte täcka installationen av pg_hibernator, för på git är det mycket väl beskrivet, men jag skulle direkt hoppa till implementeringsdelen och starta servern med 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 0 02:06 ? 00:00:00 postgres: logger process
postgres 24631 24623 0 02:06 ? 00:00:00 postgres: checkpointer process
postgres 24632 24623 0 02:06 ? 00:00:00 postgres: writer process
postgres 24633 24623 0 02:06 ? 00:00:00 postgres: wal writer process
postgres 24634 24623 0 02:06 ? 00:00:00 postgres: autovacuum launcher process
postgres 24635 24623 0 02:06 ? 00:00:00 postgres: archiver process
postgres 24636 24623 0 02:06 ? 00:00:00 postgres: stats collector process
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
In database server logs at startup time:
-bash-4.1$ more postgresql-2014-06-02_083033.log
LOG: database system was shut down at 2014-06-02 08:13:00 PDT
LOG: starting background worker process "Buffer Saver"
LOG: database system is ready to accept connections
LOG: autovacuum launcher started
Sedan dess första gången pg_hibernator är igång, kan du se två processer och även loggar med viss information om start av "Buffer Saver". Låt oss nu förvärma relationen 'foo' och starta om servern, senare kontrollera buffertstatusen om pg_hibernator fyllde bufferten tillbaka där den lämnades.
-bash-4.1$ psql -p 10407
psql (9.4beta1)
Type "help" for help.
postgres=# select pg_prewarm('foo');
pg_prewarm
------------
113278
(1 row)
--pg_buffercache query output
relname | buffers
---------+---------
foo | 113278
(1 row)
postgres=# q
-bash-4.1$ /usr/local/pgpatch/pg/bin/pg_ctl -D /usr/local/pgpatch/pg/data_10407 stop
waiting for server to shut down.... done
server stopped
-bash-4.1$ ls -l $PGDATA/pg_hibernator/
total 12
-rw------- 1 postgres postgres 160 Jun 3 01:41 1.global.save
-rw------- 1 postgres postgres 915 Jun 3 01:41 2.postgres.save
-bash-4.1$ /usr/local/pgpatch/pg/bin/pg_ctl -D /usr/local/pgpatch/pg/data_10407 start
server starting
Vi har startat om databasservern, låt oss undersöka loggarna
-bash-4.1$ more postgresql-2014-06-03_020601.log
LOG: database system was shut down at 2014-06-03 02:05:57 PDT
LOG: starting background worker process "Buffer Saver"
LOG: database system is ready to accept connections
LOG: autovacuum launcher started
LOG: registering background worker "Block Reader 2"
LOG: starting background worker process "Block Reader 2"
LOG: Block Reader 2: restored 113433 blocks
LOG: Block Reader 2: all blocks read successfully
LOG: worker process: Block Reader 2 (PID 24638) exited with exit code 1
LOG: unregistering background worker "Block Reader 2"
LOG: registering background worker "Block Reader 1"
LOG: starting background worker process "Block Reader 1"
LOG: Block Reader 1: restored 20 blocks
LOG: Block Reader 1: all blocks read successfully
LOG: worker process: Block Reader 1 (PID 24664) exited with exit code 1
LOG: unregistering background worker "Block Reader 1"
Så, "Buffer Reader" har återställt block på 113433 + 20, av vilka 113278 tillhör relationen 'foo'. Bra, låt oss ansluta och se.
-bash-4.1$ psql -p 10407
psql (9.4beta1)
Type "help" for help.
--pg_buffercache query output
relname | buffers
---------+---------
foo | 113278
(1 row)
Coolt... pg_hibernator har återställt det cacheuppvärmda tillståndet utan DBA:s störningar.
En annan bra sak med pg_hibernator, en nyskapad standby kan ha samma delade buffertinnehåll som mastern, så att standby kan börja betjäna frågor i full hastighet. För att göra denna övning, medan jag tog en säkerhetskopia av $PGDATA-katalogen, har jag skickat SIGTERM till "Buffer Saver"-processen så att den skriver det aktuella tillståndet shared_buffers-innehåll till disken ($PGDATA/pg_hibernator-katalogen) och sedan följt av standby-inställning.
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 process streaming 1/6A000A10
postgres 24654 24623 0 02:06 ? 00:00:00 postgres: wal sender process postgres ::1(65011) streaming 1/6A000A10
Efter installationen började min slav med samma innehåll som primär
-bash-4.1$ psql -p 10477
psql (9.4beta1)
Type "help" for help.
postgres=# select pg_is_in_recovery();
pg_is_in_recovery
-------------------
t
(1 row)
--pg_buffercache query output
relname | buffers
---------+---------
foo | 113278
(1 row)
Tack till båda författarna för en underbar förlängning av cachelagring.