sql >> Database >  >> RDS >> PostgreSQL

Gebruikmakend van caching contrib's pg_prewarm en pg_hibernator in PostgreSQL 9.4.

Talloze DBA's (ik meegerekend), stellen voortdurend vragen aan PostgreSQL-hackers/ontwikkelaars/architecten op de mailinglijst:

  • Q1. Heeft PG de mogelijkheid om een ​​relatie te cachen/op te warmen?
  • Q2. Is het mogelijk om terug te keren naar de eerdere staat van de cache waar deze was achtergelaten voordat de databaseserver werd afgesloten vanwege onderhoud?

In eerdere releases van PostgreSQL was er geen kans om een ​​relatie op te warmen of een cachestatus op te slaan, maar vanaf PostgreSQL 9.4 en verder worden elk van de bovenstaande queries (Q1,Q2) geadresseerd met twee contrib-modules pg_prewarm en pg_hibernator . Ondanks het feit dat ze onderscheidend zijn in bruikbaarheid, lijkt de combinatie echter uiterst levensvatbaar en nuttig in de toekomst voor DBA's. In het kort over bijdragen:

pg_prewarm contrib (Auteur:Robert Haas), biedt de mogelijkheid om relatiegegevens in de OS-buffercache of PG-buffercache te laden. Het heeft de functionaliteit van het eerste of laatste bloknummer om voor te verwarmen. (Opmerking:het heeft geen speciale bescherming op voorverwarmde gegevens van cache-uitzetting en ook als de database-instantie opnieuw is opgestart en vervolgens opnieuw moet worden opgewarmd voor de relaties).

pg_hibernator contrib (Auteur:Gurjeet Singh), biedt de mogelijkheid om de lijst met gedeelde bufferinhoud automatisch op schijf op te slaan bij het afsluiten van de database, en herstelt automatisch de buffers bij het opstarten van de database, ongeveer hetzelfde als het opslaan/herstellen van een momentopname van gedeelde_buffers. Het maakt gebruik van de PG 9.3-module om het "achtergrondwerkproces" te registreren en spawnt twee processen "Buffer Saver", "Buffer Reader" voor opslaan / herstellen. Interessant is dat met een kleine hack pg_hibernator de standby-slave ook kan toestaan ​​om op volle snelheid vragen te beantwoorden met dezelfde inhoud van de master, dat zal zo zijn :).

Ten slotte hebben we pg_buffercache . nodig module om in de huidige inhoud van PostgreSQL shared_buffers te kijken. Deze module helpt om te begrijpen welk percentage buffer wordt ingenomen door een relatie.

Laten we al deze bijdragen in het spel brengen en zien hoe ze het doel van twee vragen dienen (Q1,Q2). Ik ga een tabel 'foo' van 885 MB gebruiken op mijn lokale VM, samen met een standaard pg_buffercache-query.

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;

Gebruik van pg_prewarm contrib en opwarmende 'foo'-tabel.

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)

Zeer eenvoudig en duidelijk gebruik van pg_prewarm met een output van blokken opgewarmd in shared_buffers voor relatie 'foo'. Van pg_buffercache query-uitvoer kunnen we evalueren dat er 113278 (113278 * 8 / 1024 =884 MB) buffers zijn van 8 KB blokgrootte van relatie 'foo' die overeenkomt met pg_prewarm-uitvoer. Hier, als de Postgres-server om de een of andere reden opnieuw wordt opgestart, zijn de gedeelde_buffers leeg en moeten DBA's opnieuw worden opgewarmd om terug te keren naar het warme stadium. Voor een enkele tafel is het opwarmen altijd eenvoudig, behalve voor een groep tafels is het een kwelling.

Op dit punt kunnen we gebruik maken van pg_hibernator contrib, omdat het de flexibiliteit heeft om de inhoud van de shared_buffer op te slaan en terug te zetten bij het opstarten. Laten we pg_hibernator/pg_prewarm samen inschakelen en een vergelijkbare oefening uitvoeren door simpelweg een herstartstap op te nemen en te kijken of de cachestatus terugkeert zoals deze is of niet. Ik ga de installatie van pg_hibernator niet behandelen, want op git is het heel goed beschreven, maar ik zou direct naar het implementatiegedeelte springen en de server starten met 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

Sinds de eerste keer dat pg_hibernator in het spel is, kun je twee processen zien en ook logs met wat informatie over het starten van "Buffer Saver". Laten we nu de relatie 'foo' voorverwarmen en de server opnieuw opstarten, later de bufferstatus controleren of pg_hibernator de buffer weer heeft gevuld waar deze was achtergelaten.

-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

We hebben de databaseserver opnieuw opgestart, laten we de logs bekijken

-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"

Dus, "Buffer Reader" heeft blokken van 113433 + 20 hersteld, waarvan 113278 tot relatie 'foo' behoort. Geweldig, laten we verbinding maken en kijken.

-bash-4.1$ psql -p 10407
psql (9.4beta1)
Type "help" for help.

--pg_buffercache query output
relname | buffers
---------+---------
foo | 113278
(1 row)

Cool ... pg_hibernator heeft de cache-verwarmde staat teruggebracht zonder tussenkomst van DBA.

Een ander voordeel van pg_hibernator is dat een nieuw gemaakte stand-by dezelfde gedeelde bufferinhoud kan hebben als de master, zodat de stand-by op volle snelheid query's kan gaan uitvoeren. Om deze oefening te doen, heb ik, terwijl ik een back-up van de $PGDATA-directory heb gemaakt, SIGTERM doorgegeven aan het "Buffer Saver"-proces, zodat het de huidige status shared_buffers-inhoud naar schijf schrijft ($ PGDATA/pg_hibernator-directory) en gevolgd door de standby-configuratie.

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

Na het instellen begon mijn slaaf met dezelfde inhoud van de primaire

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

Dank aan beide auteurs voor een geweldige uitbreiding op caching.


  1. Hoe splits ik de uitvoer van mysqldump in kleinere bestanden?

  2. NULL in MySQL (prestaties en opslag)

  3. Wat is het verschil tussen =null en IS NULL?

  4. PostgreSQL versus Linux-kernelversies