PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

Verwendung von pg_prewarm und pg_hibernator von Caching Contrib in PostgreSQL 9.4.

Zahlreiche DBAs (mich mitgezählt) stellen ständig Fragen an PostgreSQL-Hacker/Entwickler/Architekten auf der Mailingliste:

  • Q1. Hat PG die Fähigkeit, eine Beziehung zwischenzuspeichern/aufzuwärmen?
  • Q2. Ist es möglich, zum vorherigen Zustand des Caches zurückzukehren, wo er vor dem Herunterfahren des Datenbankservers wegen Wartungsarbeiten gelassen wurde?

In früheren Versionen von PostgreSQL gab es keine Möglichkeit, eine Relation zu erwärmen oder einen Cache-Zustand zu speichern, aber ab PostgreSQL 9.4 wird jede der obigen Abfragen (Q1, Q2) mit zwei contrib-Modulen pg_prewarm adressiert und pg_hibernator . Trotz der Tatsache, dass sie sich in ihrer Praktikabilität unterscheiden, scheint die Kombination für DBAs in Zukunft äußerst praktikabel und nützlich zu sein. Kurz zu Beiträgen:

pg_prewarm contrib (Autor:Robert Haas) bietet die Möglichkeit, Beziehungsdaten in den OS-Buffer-Cache oder den PG-Buffer-Cache zu laden. Es hat die Funktionalität der ersten oder letzten Blocknummer zum Vorwärmen. (Anmerkung:Es hat keinen besonderen Schutz für vorgewärmte Daten vor Cache-Räumung und auch, wenn die Datenbankinstanz neu gestartet wird, dann ist ein erneutes Aufwärmen für die Beziehungen erforderlich).

pg_hibernator contrib (Autor:Gurjeet Singh) bietet die Möglichkeit, die Liste der gemeinsam genutzten Pufferinhalte beim Herunterfahren der Datenbank automatisch auf der Festplatte zu speichern, und stellt die Puffer beim Datenbankstart automatisch wieder her, ähnlich wie das Speichern/Wiederherstellen eines Snapshots von shared_buffers. Es verwendet das PG 9.3-Modul, um den „Hintergrund-Worker-Prozess“ zu registrieren, und erzeugt zwei Prozesse „Buffer Saver“, „Buffer Reader“ zum Speichern/Wiederherstellen. Interessanterweise kann pg_hibernator mit einem kleinen Hack auch dem Standby-Slave erlauben, Abfragen mit voller Geschwindigkeit mit den gleichen Inhalten wie der Master zu bedienen, wir werden das gleich sehen :).

Als letztes brauchen wir pg_buffercache -Modul, um in den aktuellen Inhalt von PostgreSQL shared_buffers zu schauen. Dieses Modul hilft zu verstehen, wie viel Prozent des Puffers von einer Beziehung belegt ist.

Lassen Sie uns all diese Beiträge ins Spiel bringen und sehen, wie sie den Zweck von zwei Fragen (Q1, Q2) erfüllen. Ich werde eine Tabelle „foo“ mit einer Größe von 885 MB auf meiner lokalen VM zusammen mit einer Standard-pg_buffercache-Abfrage verwenden.

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;

Verwendung von pg_prewarm contrib und wärmender 'foo'-Tabelle.

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)

Sehr einfache und unkomplizierte Verwendung von pg_prewarm mit einer Ausgabe von Blöcken, die in shared_buffers für die Relation „foo“ aufgewärmt wurden. Von pg_buffercache Abfrageausgabe können wir auswerten, dass es 113278 (113278 * 8 / 1024 =884 MB ) Puffer mit einer Blockgröße von 8 KB der Relation „foo“ gibt, die mit der Ausgabe von pg_prewarm übereinstimmen. Wenn hier der Postgres-Server aus irgendeinem Grund neu gestartet wird, sind shared_buffers leer und DBAs müssen sich erneut aufwärmen, um zur vergangenen warmen Phase zurückzukehren. Für einen einzelnen Tisch ist das Wiederaufwärmen immer einfach, außer für eine Gruppe von Tischen, seine Qual.

An dieser Stelle können wir pg_hibernator contrib verwenden, da es die Flexibilität bietet, den Inhalt von shared_buffer zu speichern und beim Start wiederherzustellen. Lassen Sie uns gemeinsam pg_hibernator/pg_prewarm aktivieren und eine ähnliche Übung ausführen, indem wir einfach einen Schritt des Neustarts einfügen und sehen, ob der Cache-Status unverändert zurückkehrt oder nicht. Ich werde die Installation von pg_hibernator nicht behandeln, da es auf git sehr gut beschrieben ist, aber ich würde direkt zum Implementierungsteil springen und den Server mit pg_hibernator starten.

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

Da pg_hibernator zum ersten Mal im Spiel ist, können Sie zwei Prozesse und auch Protokolle mit einigen Informationen zum Start von „Buffer Saver“ sehen. Lassen Sie uns nun die Relation „foo“ vorwärmen und den Server neu starten, später den Pufferstatus überprüfen, ob pg_hibernator den Puffer wieder dort gefüllt hat, wo er gelassen wurde.

-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

Wir haben den Datenbankserver neu gestartet, sehen wir uns die Protokolle an

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

„Buffer Reader“ hat also Blöcke von 113433 + 20 wiederhergestellt, von denen 113278 zur Relation „foo“ gehört. Großartig, verbinden und sehen.

-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 hat den aufgewärmten Cache-Zustand ohne Eingreifen des DBA zurückgebracht.

Eine weitere gute Sache an pg_hibernator ist, dass ein neu erstellter Standby-Server denselben gemeinsam genutzten Pufferinhalt wie der Master haben kann, sodass der Standby-Server mit voller Geschwindigkeit Abfragen bedienen kann. Um diese Übung durchzuführen, während ich eine Sicherung des Verzeichnisses $PGDATA erstellt habe, habe ich SIGTERM an den Prozess „Buffer Saver“ übergeben, damit dieser den aktuellen Inhalt von shared_buffers auf die Festplatte (Verzeichnis $PGDATA/pg_hibernator) schreibt, und dann folgte die Standby-Einrichtung.

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

Nach der Einrichtung startete mein Slave mit dem gleichen Inhalt von primary

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

Danke an die beiden Autoren für eine wunderbare Erweiterung zum Caching.