PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Utilisation de la mise en cache pg_prewarm et pg_hibernator de contrib dans PostgreSQL 9.4.

De nombreux administrateurs de bases de données (moi compris) posent tout le temps des questions aux hackers/développeurs/architectes PostgreSQL sur la liste de diffusion :

  • Q1. PG a-t-il la capacité de mettre en cache/préchauffer une relation ?
  • Q2. Est-il possible de revenir à l'état antérieur du cache où il était avant d'arrêter le serveur de base de données pour cause de maintenance ?

Dans les versions antérieures de PostgreSQL, il n'y avait aucune chance de réchauffer une relation ou de stocker un état de cache, mais à partir de PostgreSQL 9.4, chacune des requêtes ci-dessus (Q1, Q2) est adressée avec deux modules contrib pg_prewarm et pg_hibernator . Malgré le fait même qu'ils se distinguent par leur aspect pratique, la combinaison semble cependant être extrêmement viable et utile à l'avenir pour les administrateurs de base de données. En bref sur les contrib's :

pg_prewarm contrib (Auteur :Robert Haas), permet de charger des données de relation dans le cache de tampon du système d'exploitation ou le cache de tampon du PG. Il a la fonctionnalité du premier ou du dernier numéro de bloc à préchauffer. (Remarque :il n'a pas de protection spéciale sur les données préchauffées contre l'éviction du cache et également si l'instance de base de données est redémarrée, puis le réchauffement est nécessaire sur les relations).

pg_hibernator contrib (Auteur :Gurjeet Singh), offre la possibilité d'enregistrer automatiquement la liste du contenu des tampons partagés sur le disque lors de l'arrêt de la base de données, et de restaurer automatiquement les tampons au démarrage de la base de données, de la même manière que de sauvegarder/restaurer un instantané de shared_buffers. Il utilise le module PG 9.3 pour enregistrer le "processus de travail en arrière-plan" et génère deux processus "Buffer Saver", "Buffer Reader" pour la sauvegarde/restauration. Fait intéressant, avec un petit hack, pg_hibernator peut également permettre à l'esclave de secours de commencer à traiter les requêtes à pleine vitesse avec le même contenu que le maître, verra cela dans une minute :).

Enfin, nous avons besoin de pg_buffercache module pour regarder à l'intérieur du contenu actuel de Shared_buffers de PostgreSQL. Ce module aide à comprendre quel pourcentage de tampon est occupé par une relation.

Mettons toutes ces contributions en jeu et voyons comment elles servent l'objectif de deux questions (Q1, Q2). Je vais utiliser une table "foo" d'une taille de 885 Mo sur ma machine virtuelle locale, avec une requête pg_buffercache standard.

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;

Utilisation de pg_prewarm contrib et réchauffement de la table ‘foo’.

postgres=# create extension pg_prewarm;
CRÉER UNE EXTENSION
postgres=# dt+
Liste des relations
Schéma | Nom | Taper | Propriétaire | Taille | Descriptif
--------+------+-------+----------+--------+- ------------
public | foo | tableau | postgres | 885 Mo |
(1 ligne)
postgres=# select pg_prewarm('foo');
pg_prewarm
------------
113278
(1 ligne)
--pg_buffercache query output
relname | tampons
---------+---------
foo | 113278
(1 rangée)

Utilisation très simple et directe de pg_prewarm avec une sortie de blocs réchauffés dans shared_buffers pour la relation 'foo'. Depuis pg_buffercache la sortie de la requête, nous pouvons évaluer qu'il y a 113278 (113278 * 8 / 1024 =884 Mo ) tampons de taille de bloc de 8 Ko de relation 'foo' qui correspond à la sortie pg_prewarm. Ici, si le serveur Postgres redémarre pour une raison quelconque, les buffers_partagés sont vides et les DBA doivent se réchauffer à nouveau pour revenir à l'étape de réchauffement passée. Pour une seule table, le réchauffage est toujours simple sauf pour un groupe de tables c'est l'agonie.

À ce stade, nous pouvons utiliser la contribution pg_hibernator, car elle a la possibilité de sauvegarder le contenu du shared_buffer et de le restaurer au démarrage. Activons pg_hibernator/pg_prewarm ensemble et exécutons un exercice similaire en incluant simplement une étape de redémarrage et voyons si l'état du cache revient tel quel ou non. Je ne vais pas couvrir l'installation de pg_hibernator, car sur git c'est très bien décrit, cependant je passerais directement à la partie implémentation et démarrerais le serveur avec 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 02h06 ? 00:00:00 postgres :processus d'enregistrement
postgres 24631 24623 0 02:06 ? 00:00:00 postgres :processus de point de contrôle
postgres 24632 24623 0 02:06 ? 00:00:00 postgres :processus d'écriture
postgres 24633 24623 0 02:06 ? 00:00:00 postgres :processus d'écriture wal
postgres 24634 24623 0 02:06 ? 00:00:00 postgres :processus de lancement automatique
postgres 24635 24623 0 02:06 ? 00:00:00 postgres :processus d'archivage
postgres 24636 24623 0 02:06 ? 00:00:00 postgres :processus de collecte des statistiques
postgres 24637 24623 0 02:06 ? 00:00:00 postgres :bgworker :économiseur de tampon
postgres 24638 24623 11 02:06 ? 00:00:01 postgres :bgworker :Block Reader 2

Dans les journaux du serveur de base de données au démarrage :

-bash-4.1$ more postgresql-2014-06-02_083033. log
LOG :le système de base de données a été arrêté le 2014-06-02 08:13:00 PDT
LOG :démarrage du processus de travail en arrière-plan "Buffer Saver"
LOG :le système de base de données est prêt à accepter connexions
LOG :lancement du vide automatique démarré

Depuis sa première utilisation de pg_hibernator, vous pouvez voir deux processus et également des journaux avec des informations concernant le démarrage de "Buffer Saver". Maintenant, préchauffons la relation 'foo' et redémarrons le serveur, vérifions plus tard l'état du tampon si pg_hibernator a rempli le tampon là où il était laissé.

-bash-4.1$ psql -p 10407
psql (9.4beta1)
Tapez "help" pour obtenir de l'aide.

postgres=# select pg_prewarm('foo');
pg_prewarm
------------
113278
(1 ligne)

--pg_buffercache résultat de la requête
relname | tampons
---------+---------
foo | 113278
(1 ligne)
postgres=# q

-bash-4.1$ /usr/local/pgpatch/pg/bin/pg_ctl -D /usr/local/pgpatch /pg/data_10407 stop
attente de l'arrêt du serveur... terminé
serveur arrêté

-bash-4.1$ ls -l $PGDATA/pg_hibernator/
total 12
-rw------- 1 postgres postgres 160 3 juin 01:41 1.global.save
-rw------- 1 postgres postgres 915 3 juin 01 :41 2.postgres.save

-bash-4.1$ /usr/local/pgpatch/pg/bin/pg_ctl -D /usr/local/pgpatch/pg/data_10407 start
server démarrage

Nous avons redémarré le serveur de base de données, examinons les journaux

-bash-4.1$ plus postgresql-2014-06-03_020601.log
LOG :le système de base de données a été arrêté le 2014-06-03 02:05:57 PDT
LOG :démarrage du travailleur en arrière-plan processus "Buffer Saver"
LOG :le système de base de données est prêt à accepter les connexions
LOG :le lanceur d'autovacuum a démarré
LOG :enregistrement de l'agent d'arrière-plan "Block Reader 2"
LOG :démarrage de l'agent d'arrière-plan processus "Block Reader 2"
LOG :Block Reader 2 : 113 433 blocs restaurés
LOG :Block Reader 2 :tous les blocs lus avec succès
LOG :processus de travail :Block Reader 2 (PID 24638) terminé avec le code de sortie 1
LOG :désenregistrement du background worker "Block Reader 2"
LOG :enregistrement du background worker "Block Reader 1"
LOG :démarrage du processus background worker "Block Reader 1"
LOG :Lecteur de bloc 1 : 20 blocs restaurés
LOG :Lecteur de bloc 1 :tous les blocs ont été lus avec succès
LOG :Processus de travail :Lecteur de bloc 1 (PID 24664) terminé avec le code de sortie 1
LOG :désinscription du travailleur d'arrière-plan "Bloc Lire er 1"

Ainsi, "Buffer Reader" a restauré des blocs de 113433 + 20, dont 113278 appartiennent à la relation "foo". Génial, connectons-nous et voyons.

-bash-4.1$ psql -p 10407
psql (9.4beta1)
Tapez "help" pour obtenir de l'aide.

--pg_buffercache query output
relname | tampons
---------+---------
foo | 113278
(1 rangée)

Cool… pg_hibernator a ramené l'état réchauffé du cache sans l'interférence de DBA.

Une autre bonne chose à propos de pg_hibernator, un standby nouvellement créé peut avoir le même contenu de tampon partagé que le maître, de sorte que le standby puisse commencer à servir les requêtes à pleine vitesse. Pour faire cet exercice, tout en faisant une sauvegarde du répertoire $PGDATA, j'ai passé SIGTERM au processus "Buffer Saver" afin qu'il écrive l'état actuel du contenu de shared_buffers sur le disque (répertoire $PGDATA/pg_hibernator), puis suivi de la configuration de secours.

postgres 24637 24623 0 02:06 ? 00:00:00 postgres :bgworker :économiseur de tampon
postgres 24653 15179 0 02:06 ? 00:00:01 postgres :traitement du récepteur wal en continu 1/6A000A10
postgres 24654 24623 0 02:06 ? 00:00:00 postgres :wal sender process postgres ::1(65011) streaming 1/6A000A10

Après la configuration, mon esclave a démarré avec le même contenu que le primaire

-bash-4.1$ psql -p 10477
psql (9.4beta1)
Tapez "help" pour obtenir de l'aide.

postgres=# select pg_is_in_recovery();
pg_is_in_recovery
-------------------
t
(1 ligne)

--pg_buffercache résultat de la requête
relname | tampons
---------+---------
foo | 113278
(1 rangée)

Merci aux deux auteurs pour une merveilleuse extension sur la mise en cache.