- Q1。 PGにはリレーションをキャッシュ/ウォームする機能がありますか?
- Q2。メンテナンスのためにデータベースサーバーをシャットダウンする前にキャッシュが残っていた以前の状態に戻すことは可能ですか?
PostgreSQLの以前のリリースでは、リレーションをウォームアップしたり、キャッシュ状態を保存したりする可能性はありませんが、PostgreSQL 9.4以降では、2つのcontribモジュール pg_prewarm でアドレス指定された上記の各クエリ(Q1、Q2) およびpg_hibernator 。それらは実用性において独特であるという事実にもかかわらず、この組み合わせはDBAにとって将来的に非常に実行可能で有用であるように思われます。貢献者について簡単に言うと:
pg_prewarm contrib(作成者:Robert Haas)は、関係データをOSバッファーキャッシュまたはPGバッファーキャッシュにロードする機能を提供します。予熱する最初または最後のブロック番号の機能があります。 (注:事前にウォームアップされたデータをキャッシュエビクションから特別に保護することはできません。また、データベースインスタンスが再起動した場合は、リレーションで再度ウォームアップする必要があります)。
pg_hibernator contrib(作成者:Gurjeet Singh)は、shared_buffersのスナップショットを保存/復元するのとほぼ同じように、データベースのシャットダウン時に共有バッファーの内容のリストをディスクに自動的に保存し、データベースの起動時にバッファーを自動的に復元する機能を提供します。 PG 9.3モジュールを使用して「バックグラウンドワーカープロセス」を登録し、保存/復元用に2つのプロセス「バッファセーバー」と「バッファリーダー」を生成します。興味深いことに、少しハックするだけで、pg_hibernatorはスタンバイスレーブがマスターの同じ内容でフルスピードでクエリの提供を開始できるようにすることもできます。これはすぐにわかります:)
最後に、 pg_buffercacheが必要です PostgreSQLshared_buffersの現在のコンテンツの内部を調べるモジュール。このモジュールは、リレーションによって占有されているバッファの割合を理解するのに役立ちます。
これらすべての貢献を活用して、2つの質問(Q1、Q2)の目的にどのように役立つかを見てみましょう。ローカルVMでサイズ885MBのテーブル「foo」を標準の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;
pg_prewarmcontribとウォーミング「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)
pg_prewarmの非常にシンプルでわかりやすい使用法 リレーション「foo」のshared_buffersでウォームアップされたブロックの出力を使用します。 pg_buffercacheから クエリ出力は、pg_prewarm出力と一致するリレーション「foo」の8KBブロックサイズの113278(113278 * 8/1024 =884MB)バッファがあることを評価できます。ここで、何らかの理由でPostgresサーバーが再起動した場合、shared_buffersは空であり、DBAは、過去のウォームステージに戻るために再度ウォームアップする必要があります。単一のテーブルの場合、テーブルのグループが苦痛を伴うことを除いて、再ウォームは常に簡単です。
この時点で、pg_hibernator contribを利用できます。これは、shared_bufferの内容を保存し、起動時に復元できる柔軟性があるためです。 pg_hibernator / pg_prewarmを一緒に有効にして、再起動の1つのステップを含めるだけで同様の演習を実行し、キャッシュ状態が元に戻るかどうかを確認しましょう。 pg_hibernatorのインストールについては説明しません。これは、gitで非常によく説明されているためですが、実装部分に直接ジャンプして、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
初めてpg_hibernatorがプレイされて以来、2つのプロセスを確認でき、「バッファセーバー」の開始に関する情報もログに記録されます。次に、リレーション「foo」を事前にウォームアップしてサーバーを再起動し、後でpg_hibernatorがバッファを元の場所に戻したかどうかをバッファステータスで確認します。
-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
データベースサーバーを再起動しました。ログを調べてみましょう
-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」は、113433 + 20のブロックを復元し、そのうち113278はリレーション「foo」に属しています。よし、接続して見てみましょう。
-bash-4.1$ psql -p 10407
psql (9.4beta1)
Type "help" for help.
--pg_buffercache query output
relname | buffers
---------+---------
foo | 113278
(1 row)
かっこいい…pg_hibernatorは、DBAの干渉なしにキャッシュウォーム状態を戻しました。
pg_hibernatorのもう1つの優れた点は、新しく作成されたスタンバイがマスターと同じ共有バッファーの内容を持つことができるため、スタンバイがクエリの処理をフルスピードで開始できることです。この演習を行うために、$ PGDATAディレクトリのバックアップを取りながら、SIGTERMを「バッファセーバー」プロセスに渡して、現在の状態のshared_buffersコンテンツをディスク($ PGDATA / pg_hibernatorディレクトリ)に書き込み、スタンバイセットアップを実行しました。
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
セットアップ後、私のスレーブはプライマリの同じコンテンツで開始しました
-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)
キャッシングに関するすばらしい拡張機能を提供してくれた両方の作成者に感謝します。