PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Korzystanie z buforowania pg_prewarm i pg_hibernator contrib w PostgreSQL 9.4.

Wielu DBA (licząc mnie), cały czas zadaje pytania hakerom/programistom/architektom PostgreSQL na liście dyskusyjnej:

  • P1. Czy PG ma możliwość buforowania/ogrzewania relacji?
  • P2. Czy jest możliwy powrót do poprzedniego stanu pamięci podręcznej, w którym był pozostawiony przed wyłączeniem serwera bazy danych z powodu konserwacji?

We wcześniejszych wersjach PostgreSQL nie było szans na ocieplenie relacji lub przechowywanie stanów pamięci podręcznej, ale od PostgreSQL 9.4 wzwyż każde z powyższych zapytań (Q1,Q2) było adresowane za pomocą dwóch modułów contrib pg_prewarm i pg_hibernator . Pomimo tego, że wyróżniają się praktycznością, połączenie wydaje się być niezwykle opłacalne i przydatne w przyszłości dla DBA. W skrócie o wkładach:

pg_prewarm contrib (Autor:Robert Haas), zapewnia możliwość załadowania danych relacji do bufora bufora systemu operacyjnego lub bufora bufora PG. Posiada funkcję wstępnego lub ostatniego numeru bloku do wstępnego podgrzania. (Uwaga:nie ma specjalnej ochrony dla wstępnie ogrzanych danych przed wyrzuceniem pamięci podręcznej, a także, jeśli instancja bazy danych została zrestartowana, konieczne jest ponowne rozgrzanie relacji).

pg_hibernator contrib (autor:Gurjeet Singh), zapewnia możliwość automatycznego zapisywania listy zawartości współdzielonego bufora na dysku podczas zamykania bazy danych i automatycznie przywraca bufory podczas uruchamiania bazy danych, podobnie jak zapisywanie/przywracanie migawki shared_buffers. Wykorzystuje moduł PG 9.3 do rejestracji „procesu pracownika w tle” i odradza dwa procesy „Buffer Saver”, „Buffer Reader” do zapisywania/przywracania. Co ciekawe, przy odrobinie hacka pg_hibernator może również zezwolić w trybie gotowości slave na rozpoczęcie obsługi zapytań z pełną prędkością z taką samą zawartością mastera, zobaczy to za minutę :).

Na koniec potrzebujemypg_buffercache aby zajrzeć do aktualnej zawartości shared_buffers PostgreSQL. Ten moduł pomaga zrozumieć, jaki procent bufora zajmuje relacja.

Włączmy wszystkie te wkłady i zobaczmy, jak służą celom dwóch pytań (Q1,Q2). Zamierzam użyć tabeli „foo” o rozmiarze 885 MB na mojej lokalnej maszynie wirtualnej wraz ze standardowym zapytaniem 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;

Wykorzystanie pg_prewarm contrib i rozgrzewającej tabeli „foo”.

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)

Bardzo proste i proste użycie pg_prewarm z wyjściem bloków rozgrzanych w shared_buffers dla relacji „foo”. Z pg_buffercache wyjście zapytania możemy oszacować, że istnieje 113278 (113278 * 8 / 1024 =884MB ) buforów o rozmiarze bloku 8KB w relacji „foo”, która pasuje do wyjścia pg_prewarm. W tym przypadku, jeśli serwer Postgres zrestartuje się z jakiegoś powodu, shared_buffers są puste i DBA musi ponownie się rozgrzać, aby wrócić do poprzedniego ciepłego etapu. W przypadku pojedynczego stołu ponowne rozgrzanie jest zawsze proste, z wyjątkiem grupy stołów, która jest jej agonią.

W tym momencie możemy skorzystać z contrib pg_hibernator, ponieważ ma on elastyczność zapisywania zawartości shared_buffer i przywracania jej z powrotem podczas uruchamiania. Włączmy razem pg_hibernator/pg_prewarm i wykonajmy podobne ćwiczenie, po prostu włączając jeden krok ponownego uruchomienia i sprawdźmy, czy stan pamięci podręcznej powróci do stanu pierwotnego, czy nie. Nie będę omawiał instalacji pg_hibernator, ponieważ w git jest to bardzo dobrze opisane, jednak bezpośrednio przeskoczyłbym do części implementacyjnej i uruchomił serwer z pg_hibernatorem.

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

Ponieważ po raz pierwszy pg_hibernator jest w grze, możesz zobaczyć dwa procesy, a także logi z informacjami dotyczącymi uruchomienia „Oszczędzania bufora”. Teraz podgrzejmy wstępnie relację „foo” i zrestartuj serwer, później sprawdź stan bufora, czy pg_hibernator wypełnił bufor z powrotem tam, gdzie został.

-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

Zrestartowaliśmy serwer bazy danych, sprawdźmy logi

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

Tak więc „Czytnik bufora” przywrócił bloki 113433 + 20, z których 113278 należy do relacji „foo”. Świetnie, połączmy się i zobaczmy.

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

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

Fajnie… pg_hibernator przywrócił stan rozgrzania pamięci podręcznej bez ingerencji DBA.

Kolejną zaletą pg_hibernator jest to, że nowo utworzona rezerwa może mieć taką samą zawartość współdzielonego bufora jak master, dzięki czemu rezerwa może zacząć obsługiwać zapytania z pełną prędkością. Aby wykonać to ćwiczenie, wykonując kopię zapasową katalogu $PGDATA, przekazałem SIGTERM proces „Buffer Saver”, aby zapisywał zawartość shared_buffers w bieżącym stanie na dysk (katalog $PGDATA/pg_hibernator), a następnie kontynuowałem konfigurację trybu gotowości.

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

Po konfiguracji mój slave zaczął z tą samą zawartością podstawowego

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

Dziękuję obu autorom za wspaniałe rozszerzenie dotyczące buforowania.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Utwórz kopię zapasową/przywróć zadokowaną bazę danych PostgreSQL

  2. Jak naprawić BŁĄD:kolumna c.relhasoids nie istnieje w Postgresie?

  3. Przegląd replikacji logicznej w PostgreSQL

  4. O indeksie klastrowym w postgres

  5. Nie można połączyć się z postgresem za pomocą jdbc w powłoce pyspark