sql >> Database teknologi >  >> RDS >> PostgreSQL

Brug af caching contribs pg_prewarm og pg_hibernator i PostgreSQL 9.4.

Talrige DBA'er (tæller mig), stiller hele tiden spørgsmål til PostgreSQL hackere/udviklere/arkitekter på mailinglisten:

  • Q1. Har PG mulighed for at cache/varme en relation?
  • Q2. Er det muligt at vende tilbage til tidligere cachetilstand, hvor den blev efterladt, før databaseserveren blev lukket ned på grund af vedligeholdelse?

I tidligere udgivelser af PostgreSQL er der ingen chance for at opvarme en relation eller gemme en cachetilstand, men fra PostgreSQL 9.4 og fremefter adresseres hver af ovenstående forespørgsler (Q1,Q2) med to bidragsmoduler pg_prewarm og pg_hibernator . På trods af selve det faktum, at de er karakteristiske i praksis, ser kombinationen dog ud til at være yderst levedygtig og nyttig i fremtiden for DBA'er. Kort sagt om bidrag:

pg_prewarm contrib (forfatter:Robert Haas), giver mulighed for at indlæse en relationsdata i OS buffer cache eller PG buffer cache. Den har funktionaliteten som første eller sidste bloknummer til forvarmning. (Bemærk:Den har ingen speciel beskyttelse på forvarmede data fra cache-eviction, og også hvis databaseforekomsten genstartes, skal der opvarmes igen på relationerne).

pg_hibernator contrib (Forfatter:Gurjeet Singh), giver mulighed for automatisk at gemme listen over delt bufferindhold på disk ved nedlukning af database, og gendanner automatisk bufferne ved databasestart, meget det samme som at gemme/gendanne et øjebliksbillede af shared_buffers. Det bruger PG 9.3-modulet til at registrere "baggrundsarbejderproces" og afføder to processer "Buffer Saver", "Buffer Reader" til lagring/gendannelse. Interessant nok, med et lille hack, kan pg_hibernator også tillade standby-slave at begynde at betjene forespørgsler med fuld hastighed med samme indhold af master, vil se det om et minut :).

Til sidst har vi brug for pg_buffercache modul for at se inde i det aktuelle indhold af PostgreSQL shared_buffers. Dette modul hjælper med at forstå, hvor stor en procentdel buffer der er optaget af en relation.

Lad os sætte alle disse bidrag i spil og se, hvordan de tjener formålet med to spørgsmål (Q1, Q2). Jeg vil bruge en tabel 'foo' på størrelse 885 MB på min lokale VM, sammen med en standard pg_buffercache-forespørgsel.

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;

Brug af pg_prewarm bidrag og opvarmning '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)

Meget enkel og ligetil brug af pg_prewarm med et output af blokke opvarmet i shared_buffers for relation 'foo'. Fra pg_buffercache forespørgselsoutput kan vi vurdere, at der er 113278 (113278 * 8 / 1024 =884MB ) buffere på 8KB blokstørrelse af relationen 'foo', som matcher med pg_prewarm output. Her, hvis Postgres-serveren genstarter på grund af en eller anden grund, er shared_buffers tomme, og DBA's behov for at genopvarme igen for at komme tilbage til tidligere varme stadier. For et enkelt bord er genopvarmning altid enkel, bortset fra en gruppe borde, det er smertefuldt.

På dette tidspunkt kan vi gøre brug af pg_hibernator contrib, fordi det har fleksibiliteten til at gemme shared_bufferens indhold og gendanne det igen ved opstart. Lad os aktivere pg_hibernator/pg_prewarm sammen og køre en lignende øvelse ved blot at inkludere et genstartstrin og se, om cachetilstanden vender tilbage som den er eller ej. Jeg vil ikke dække installationen af ​​pg_hibernator, for på git er det meget godt beskrevet, men jeg ville direkte springe til implementeringsdelen og starte serveren 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

Siden dens første gang pg_hibernator i spil, kan du se to processer og også logfiler med nogle oplysninger om start af "Buffer Saver". Lad os nu forvarme forholdet 'foo' og genstarte serveren, senere kontrollere bufferstatus om pg_hibernator fyldte bufferen tilbage, hvor den blev efterladt.

-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 genstartet databaseserveren, lad os undersøge logfilerne

-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 gendannet blokke på 113433 + 20, hvoraf 113278 tilhører relationen 'foo'. Fantastisk, lad os oprette forbindelse og se.

-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 har bragt cache-opvarmet tilstand tilbage uden DBA's indblanding.

En anden god ting ved pg_hibernator, en nyoprettet standby kan have det samme delte bufferindhold som masteren, så standbyen kan begynde at betjene forespørgsler med fuld hastighed. For at udføre denne øvelse, mens jeg tager en backup af $PGDATA-biblioteket, har jeg videregivet SIGTERM til "Buffer Saver"-processen, så den skriver den aktuelle tilstand shared_buffers-indhold til disken ($PGDATA/pg_hibernator-mappen) og derefter fulgt med standby-opsætning.

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 opsætningen startede min slave med samme indhold af 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)

Tak til begge forfattere for en vidunderlig udvidelse til caching.


  1. Effektiv strategi til at efterlade et revisionsspor/ændringshistorik for DB-applikationer?

  2. Kaldnotation for PL/SQL-underrutiner i Oracle-databasen

  3. Slå en advarsel fra i sqlalchemy

  4. SQL Server-isolationsniveauer:A-serie