KEMBAR78
あなたの知らないPostgreSQL監視の世界 | PDF
あなたの知らない
PostgreSQL 監視の世界
中西 剛紀
2
自己紹介
•  氏名 : 中西 剛紀 (なかにし よしのり)
•  所属 : TIS株式会社 OSS推進室
•  お仕事 : OSSのサポート, 技術支援
•  主な活動領域 : PostgreSQL全般
–  日本PostgreSQLユーザ会(JPUG)でたまに講演
http://www.slideshare.net/naka24nori/pg-monzpostgre-sql
–  PostgreSQLエンタープライズコンソーシアム
(PGECons)で技術検証活動
http://itpro.nikkeibp.co.jp/atcl/column/15/052800134/052900004/?
ST=oss&a
•  pg_monzの開発メンバー
3
AGENDA
•  PostgreSQLの監視に使える情報
•  PostgreSQLの監視に使えるツール
•  PostgreSQLの監視パターン
•  PostgreSQLのログについて考える
4
PostgreSQLの運用でやるべきこと
•  データベース運用の目的
– DBの状態を把握して健全な状態に保つ
•  データベース運用の種類
– 死活監視
– リソース監視
– 性能分析/チューニング
– バックアップ/リストア
•  監視が運用管理の基本
– 正しく現状を把握しなければ何もできない
5
PostgreSQLの運用でやるべきこと
•  データベース運用の目的
– DBの状態を把握して健全な状態に保つ
•  データベース運用の種類
– 死活監視
– リソース監視
– 性能分析/チューニング
– バックアップ/リストア
•  監視が運用管理の基本
– 正しく現状を把握しなければ何もできない
今回お話する範囲
6
PostgreSQLの監視に使える情報
7
PostgreSQLの監視に使える情報
•  PostgreSQLの標準機能
– コマンド
– 関数
– 稼働統計情報
– ログ
8
PostgreSQLの監視に使える情報
•  コマンド
•  関数
参考:PostgreSQL	
  9.4.4	
  マニュアル 第9章関数と演算子	
  
h0ps://www.postgresql.jp/document/9.4/html/func>ons-­‐info.html	
コマンド名 説明
pg_isready PostgreSQLサーバの接続状態を検査する。(9.3以降)
参考:PostgreSQL	
  9.4.4	
  マニュアル II.	
  PostgreSQLクライアントアプリケーション	
  
h0ps://www.postgresql.jp/document/9.4/html/reference-­‐client.html	
  
関数名 説明
pg_is_in_recovery() リカバリ実施中であれば真を返す。
pg_database_size() データベースで使用されるディスク容量を返す。
pg_table_size() テーブルで使用されるディスク容量を返す。
(インデックスは除外)
9
PostgreSQLの監視に使える情報
•  稼働統計情報
ビュー名 説明
pg_stat_activity 接続中のサーバプロセスに関連する情報
pg_stat_archiver アーカイバプロセスに関する情報 (9.4以降)
pg_stat_bgwriter バックグラウンドライタプロセスの活動状況
pg_stat_database DB単位のアクティビティ状況
pg_stat_**_tables テーブル単位のアクティビティ状況
pg_stat_**_indexes インデックス単位のアクティビティ状況
pg_statio_**_tables テーブル単位のI/Oに関する情報
pg_statio_**_indexes インデックス単位のI/Oに関する情報
pg_statio_**_sequences シーケンス単位のI/Oに関する情報
pg_stat_user_functions 関数の実行に関する情報
pg_stat_replication レプリケーションのアクティビティ状況
参考:PostgreSQL	
  9.4.4	
  マニュアル 第27章データベース活動状況の監視	
  
h0ps://www.postgresql.jp/document/9.4/html/monitoring-­‐stats.html	
  
10
PostgreSQLの監視に使える情報
•  ログ
– 何らかの事象が発生したことを出力
•  深刻なレベル(PANIC,FATAL,ERROR)から、
特に影響ないレベル(INFO)まで
– 処理されたSQL
•  設定時間を超過したSQL(スロークエリ)
•  監査目的で全てのSQLを出力することも可能
– チェックポイント、自動VACUUMの実行
– デッドロックの発生
– 出力形式
•  テキスト(プレーン、CSV)
•  syslog
•  イベントログ
11
PostgreSQLの監視に使えるツール
12
PostgreSQLの監視に使えるツール
•  contrib
– pg_stat_statements
– file_fdw
•  サードパーティ
– pg_statsinfo
– pg_monz
– pgBadger
– Fluentd
13
pg_stat_statements
•  PostgreSQLサーバで実行された
クエリの情報を収集する共有ライブラリ
– 8.4からcontribとして配布されている。
– クエリ種別、実行回数、総実行時間を収集
– 稼働統計情報と同様のビューを提供
– 永安さんの資料が詳しい
•  「今そこにある危機」を捉える ∼
pg_stat_statements revisited
http://www.slideshare.net/uptimejp/pgstatstatements-revisited
14
pg_statsinfo
•  PostgreSQLサーバの稼働統計情報(+α)
を定期的に収集・蓄積するツール
–  http://pgstatsinfo.sourceforge.net/pg_statsinfo-ja.html
•  pg_stats_reporterで蓄積した統計情報
からグラフィカルなレポートを出力可能
•  NTTさんが開発しているOSS
•  PostgreSQLの性能管理ツールとしては
一番知名度が高い。
15
pg_monz(ぴーじーもんず)
•  ZabbixにPostgreSQLの監視機能を  
追加するテンプレート&スクリプト
–  http://pg-monz.github.io/pg_monz/
•  TISとSRA OSS, Inc.日本支社で共同開発
•  Apache License Version 2.0で公開
•  2015年 4月 Version 2.0 リリース
16
Zabbixについて少々
•  オープンソースの統合監視ソフトウェア
•  監視ツールに必要な機能を網羅
– いろんな機器(NW,サーバ,MW,アプリ)に対応
– 対応プラットフォーム(OS)も多い
– 収集データの蓄積、傾向分析
– メール等での障害通知
– WebインタフェースによるGUIで操作可
•  ラトビアのZabbix SIAが開発元
– 国内の導入事例が増加しています。
– クラウドでの引き合い多数(¥的な面で)
17
PostgreSQLの監視パターン
18
救急患者レベル
•  事象を検知したら即座に対応しよう。
•  死活監視
•  ログ監視
•  レプリケーション監視
19
死活監視(標準機能)
•  psコマンドでプロセスを確認
•  SQL実行の可否を確認
-bash-4.1$	 ps	 auxwf|egrep	 "^postgres|^USER"

USER	 	 	 	 	 	 	 PID	 %CPU	 %MEM	 	 	 	 VSZ	 	 	 RSS	 TTY	 	 	 	 	 	 STAT	 START	 	 	 TIME	 COMMAND

postgres	 13470	 	 0.0	 	 3.0	 324640	 15068	 pts/0	 	 	 	 S	 	 	 	 05:55	 	 	 0:00	 /usr/pgsql-9.4/bin/postgres

postgres	 13471	 	 0.0	 	 0.3	 179792	 	 1520	 ?	 	 	 	 	 	 	 	 Ss	 	 	 05:55	 	 	 0:00	 	 _	 postgres:	 logger	 process	 	 	 

postgres	 13473	 	 0.0	 	 0.6	 324748	 	 3152	 ?	 	 	 	 	 	 	 	 Ss	 	 	 05:55	 	 	 0:00	 	 _	 postgres:	 checkpointer	 process	 	 	 

postgres	 13474	 	 0.0	 	 0.5	 324776	 	 2900	 ?	 	 	 	 	 	 	 	 Ss	 	 	 05:55	 	 	 0:00	 	 _	 postgres:	 writer	 process	 	 	 

postgres	 13475	 	 0.0	 	 1.1	 324640	 	 5860	 ?	 	 	 	 	 	 	 	 Ss	 	 	 05:55	 	 	 0:00	 	 _	 postgres:	 wal	 writer	 process	 	 	 

postgres	 13476	 	 0.0	 	 0.5	 325044	 	 2552	 ?	 	 	 	 	 	 	 	 Ss	 	 	 05:55	 	 	 0:00	 	 _	 postgres:	 autovacuum	 launcher	 process	 	 	 

postgres	 13477	 	 0.0	 	 0.2	 179784	 	 1464	 ?	 	 	 	 	 	 	 	 Ss	 	 	 05:55	 	 	 0:00	 	 _	 postgres:	 archiver	 process	 	 	 

postgres	 13478	 	 0.0	 	 0.3	 179916	 	 1728	 ?	 	 	 	 	 	 	 	 Ss	 	 	 05:55	 	 	 0:00	 	 _	 postgres:	 stats	 collector	 process	 

-bash-4.1$	 psql	 -t	 -c	 "SELECT	 1"

	 	 	 	 	 	 	 	 1

-bash-4.1$	 echo	 $?

0

-bash-4.1$	 pg_ctl	 stop

-bash-4.1$	 psql	 –t	 -c	 "SELECT	 1"

psql:	 could	 not	 connect	 to	 server:	 No	 such	 file	 or	 directory



Is	 the	 server	 running	 locally	 and	 accepting



connections	 on	 Unix	 domain	 socket	 "/tmp/.s.PGSQL.5432"?

-bash-4.1$	 echo	 $?

2
20
死活監視(標準機能)
•  pg_ctl statusコマンドで確認
•  pg_isreadyコマンドで確認(9.3以降)
-bash-4.1$	 pg_ctl	 status

pg_ctl:	 server	 is	 running	 (PID:	 13616)

/usr/pgsql-9.4/bin/postgres

-bash-4.1$	 echo	 $?

0

-bash-4.1$	 pg_ctl	 stop

-bash-4.1$	 pg_ctl	 status

pg_ctl:	 no	 server	 running

-bash-4.1$	 echo	 $?

3

-bash-4.1$	 pg_isready

/tmp:5432	 -	 accepting	 connections

-bash-4.1$	 echo	 $?

0

-bash-4.1$	 pg_ctl	 stop

-bash-4.1$	 pg_isready

/tmp:5432	 -	 no	 response

-bash-4.1$	 echo	 $?

2
21
死活監視(ツール活用)
•  pg_monz で死活監視
– SQL(SELECT 1)を定期的に実行して確認
– 実行に失敗したらZabbixのトリガーで検知
– Zabbixのアクションを定義することで、
トリガー検知時のメール通知等が可能
22
ログ監視(標準機能)
•  ログに出力されるメッセージを確認
– PANIC/FATAL/ERRORが監視候補
深刻度 説明
PANIC データベースインスタンス全体に影響する致命的な問題
FATAL 接続エラー、強制切断といったセッションレベルに影響する問題
LOG 管理者向けの情報。チェックポイント、VACUUM、スロークエリ等
ERROR SQLを中断させる原因となったエラー。シンタックスエラー等
WARNING ユーザへの警告。トランザクションブロック外でのCOMMIT等
NOTICE ユーザの補助となる情報。長い識別子の切り詰めに関する注意等
INFO ユーザが明示的に出力する補助情報。VACUUM VERBOSEの出力等
DEBUG1..5 開発者向けの詳細情報。運用時には出力しない。
23
ログ監視(ツール活用)
•  pg_monzでログ監視
– ログファイルの内容を定期的に確認
– PANIC/FATAL/ERRORを含むメッセージを
検出したらZabbixのトリガーで検知
– Zabbixのアクションを定義することで、
トリガー検知時のメール通知等が可能
24
レプリケーション監視(標準機能)
•  スレーブがつながっているか?
– マスタのpg_stat_replicationビューで確認
postgres=#	 select	 client_addr,	 state,	 sent_location,	 replay_location,



 

 

sync_priority,sync_state	 from	 pg_stat_replication;



	 client_addr	 	 |	 	 	 state	 	 	 |	 sent_location	 |	 replay_location	 |	 sync_priority	 |	 sync_state	 

--------------+-----------+---------------+-----------------+---------------+------------

	 192.168.1.14	 |	 streaming	 |	 0/5F02FAB8	 	 	 	 |	 0/5F02FAB8	 	 	 	 	 	 |	 	 	 	 	 	 	 	 	 	 	 	 	 1	 |	 sync

	 192.168.1.15	 |	 streaming	 |	 0/5F02FAB8	 	 	 	 |	 0/5F02FAB8	 	 	 	 	 	 |	 	 	 	 	 	 	 	 	 	 	 	 	 2	 |	 potential
25
レプリケーション監視(ツール活用)
•  pg_monzでレプリケーション監視
– どのサーバがPrimary/Standbyか確認可能
– マスタのpg_stat_replicationビューの情報を
定期的に取得し、以下情報を確認可能
•  Standbyへのデータ伝搬の遅延状況
•  同期レプリケーションのプライオリティ
26
レプリケーション監視 その2
•  マスタが2つあったらヤバい。
•  違うデータベースとして不整合が広がる。
PostgreSQL	
  
(スレーブ)	
  
PostgreSQL	
  
(スレーブ)	
  
PostgreSQL	
  
(マスタ)	
  
更新	
 同期	
同期	
PostgreSQL	
  
(スレーブ)	
  
PostgreSQL	
  
(新マスタ)	
  
PostgreSQL	
  
(旧マスタ)	
  
更新	
 同期	
あれ??	
更新
27
レプリケーション監視(標準機能)
•  pg_is_in_recovery関数で確認
•  pg_stat_replicationビューで確認
postgres=#	 SELECT	 pg_is_in_recovery(); ★マスタで実行

	 pg_is_in_recovery	 

-------------------

	 f

postgres=#	 SELECT	 pg_is_in_recovery(); ★スレーブで実行

	 pg_is_in_recovery	 

-------------------

	 t

postgres=#	 SELECT	 COUNT(*)	 FROM	 pg_stat_replication; ★マスタで実行

	 count	 

-------

	 	 	 	 	 2

postgres=#	 SELECT	 COUNT(*)	 FROM	 pg_stat_replication; ★スレーブで実行

	 count	 

-------

	 	 	 	 	 0
28
レプリケーション監視(ツール活用)
•  pg_monzでマスタの数を監視
– クラスタ内のマスタ、スレーブ数をチェック
– 本来の数(1つ)じゃなかったらトリガーで検知
29
レプリケーション監視 その3
•  同期スレーブがいなくなるとヤバい。
•  マスタ更新不可により実質サービス停止
PostgreSQL	
  
(非同期
スレーブ)	
  
PostgreSQL	
  
(同期
スレーブ)	
  
PostgreSQL	
  
(マスタ)	
  
更新	
 同期	
同期	
PostgreSQL	
  
(potential)	
  
PostgreSQL	
  
(sync)	
  
PostgreSQL	
  
(マスタ)	
  
更新NG	
  
あれ??	
参照OK	
  
参照	
  
30
レプリケーション監視(標準機能)
•  pg_stat_replicationビューで確認
postgres=#	 SELECT	 COUNT(*)	 FROM	 pg_stat_replication; ★マスタで実行

	 count	 

-------

	 	 	 	 	 2 ⇒	 問題なし

postgres=#	 SELECT	 COUNT(*)	 FROM	 pg_stat_replication; ★マスタで実行

	 count	 

-------

	 	 	 	 	 0 ⇒	 スレーブが1つもいないので問題あり
31
レプリケーション監視(ツール活用)
•  pg_monzで同期スレーブの数を監視
– 同期レプリケーションを設定している場合、
スレーブがいなくなったらトリガーで検知
32
レントゲンに怪しい影が、、レベル
•  事態が深刻化する前に手を打とう。
•  データベース容量
•  WALアーカイブ
•  デッドロック
•  長時間かかっている処理
33
データベース容量(標準機能)
•  データベースクラスタのディレクトリを
duコマンドで確認
•  関数で確認
[postgres@pgsql01	 9.4]$	 du	 -sh	 data

611M

data

postgres=#	 select	 pg_size_pretty(pg_database_size(‘testdb’));	 ★データベース 

	 pg_size_pretty	 

----------------

	 171	 MB

testdb=#	 select	 pg_size_pretty(pg_table_size(‘pgbench_accounts’));	 ★テーブル

	 pg_size_pretty	 

----------------

	 130	 MB
34
データベース容量(ツール活用)
•  pg_monzでデータベース容量を確認
– DB単位にグラフを表示可能
– 閾値を超過したらZabbixのトリガーで検知
35
WALアーカイブ(標準機能)
•  PITRでの復旧にWALアーカイブが必要
•  WALアーカイブに失敗したログを確認
– 深刻度がLOG,WARNINGなので注意
cp:	 cannot	 create	 regular	 file	 `/var/lib/pgsql/9.4/archive_bad/
000000010000000000000008':	 No	 such	 file	 or	 directory

<	 2015-11-11	 10:04:50.609	 UTC	 >LOG:	 	 archive	 command	 failed	 with	 exit	 code	 1

<	 2015-11-11	 10:04:50.609	 UTC	 >DETAIL:	 	 The	 failed	 archive	 command	 was:	 cp	 pg_xlog/
000000010000000000000008	 /var/lib/pgsql/9.4/archive_bad/000000010000000000000008

cp:	 cannot	 create	 regular	 file	 `/var/lib/pgsql/9.4/archive_bad/
000000010000000000000008':	 No	 such	 file	 or	 directory

<	 2015-11-11	 10:04:51.614	 UTC	 >LOG:	 	 archive	 command	 failed	 with	 exit	 code	 1

<	 2015-11-11	 10:04:51.614	 UTC	 >DETAIL:	 	 The	 failed	 archive	 command	 was:	 cp	 pg_xlog/
000000010000000000000008	 /var/lib/pgsql/9.4/archive_bad/000000010000000000000008

cp:	 cannot	 create	 regular	 file	 `/var/lib/pgsql/9.4/archive_bad/
000000010000000000000008':	 No	 such	 file	 or	 directory

<	 2015-11-11	 10:04:52.618	 UTC	 >LOG:	 	 archive	 command	 failed	 with	 exit	 code	 1

<	 2015-11-11	 10:04:52.618	 UTC	 >DETAIL:	 	 The	 failed	 archive	 command	 was:	 cp	 pg_xlog/
000000010000000000000008	 /var/lib/pgsql/9.4/archive_bad/000000010000000000000008

<	 2015-11-11	 10:04:52.619	 UTC	 >WARNING:	 	 archiving	 transaction	 log	 file	 
"000000010000000000000008"	 failed	 too	 many	 times,	 will	 try	 again	 later
36
WALアーカイブ(標準機能)
•  pg_stat_archiverビューで確認(9.4以降)
postgres=#	 select	 *	 from	 pg_stat_archiver;

-[	 RECORD	 1	 ]------+------------------------------

archived_count	 	 	 	 	 |	 12

last_archived_wal	 	 |	 00000001000000000000000E

last_archived_time	 |	 2015-11-11	 10:10:50.629021+00

failed_count	 	 	 	 	 	 	 |	 6

last_failed_wal	 	 	 	 |	 000000010000000000000008

last_failed_time	 	 	 |	 2015-11-11	 10:05:52.719825+00

stats_reset	 	 	 	 	 	 	 	 |	 2015-11-06	 08:10:16.027035+00
37
デッドロック(標準機能)
•  デッドロック発生をログで確認
– log_lock_waitsパラメータを設定して出力
•  pg_stat_databaseビューで確認
2015-11-12	 14:52:07	 JST	 [10382]	 LOG:	 	 process	 10382	 detected	 deadlock	 while	 waiting	 for	 
AccessExclusiveLock	 on	 relation	 16420	 of	 database	 16400	 after	 1000.088	 ms

postgres=#	 SELECT	 datname,deadlocks	 FROM	 pg_stat_database	 where	 datname	 =	 'testdb';

	 datname	 |	 deadlocks	 

---------+-----------

	 testdb	 	 |	 	 	 	 	 	 	 	 	 2
38
デッドロック(ツール活用)
•  pg_monzでデッドロック監視
– DB単位のデッドロック発生数を定期的に確認
– 一定時間内の発生数が閾値を超過したら
Zabbixのトリガーで検知
•  pg_statsinfoでデッドロック監視
– DB単位のデッドロック発生数を収集
39
長時間かかっている処理
•  ロングクエリ
– 開始されてから長時間終了していないクエリ
•  ロングトランザクション
– BEGIN∼COMMITまでが長時間の処理
– VACUUMやHOTによるガベージ回収処理を
妨げ、DBの肥大化を起こす要因
40
長時間かかっている処理(標準機能)
•  pg_stat_activityビューで確認
– xact_start: トランザクション開始時刻
– query_start: 現在のクエリ開始時刻
postgres=#	 SELECT	 pid,	 state,	 waiting,	 



 

 

(now()	 -	 xact_start)::interval(3)	 AS	 tx_duration,	 



 

 

(now()	 -	 query_start)::interval(3)	 AS	 sql_duration,	 query	 



 

 

FROM	 pg_stat_activity	 WHERE	 pid	 <>	 pg_backend_pid();

	 	 pid	 	 |	 state	 	 |	 waiting	 |	 tx_duration	 	 |	 sql_duration	 |	 	 	 	 	 	 	 	 query	 	 	 	 	 	 	 	 	 

-------+--------+---------+--------------+--------------+----------------------

	 10266	 |	 active	 |	 f	 	 	 	 	 	 	 |	 00:02:00.303	 |	 00:00:14.175	 |	 SELECT	 pg_sleep(60);
41
長時間かかっている処理(ツール活用)
•  pg_monzでロングクエリを確認
– 一定時間以上かかっているクエリの数を
定期的に確認
– 閾値を超過したらZabbixのトリガーで検知
42
体力測定レベル
•  データベースの稼働状況を把握しよう。
•  データベースのスループット
•  データベースの接続数
•  キャッシュヒット率
•  チェックポイント、VACUUMの実行状況
•  一時ファイルの書き出し
•  実行されたSQLの実行時間
43
データベースのスループット
•  日頃の処理量を知っておこう。
– 平常時、ピーク時のトランザクション量
– 性能問題の原因切り分けの基礎情報
44
データベースのスループット(標準機能)
•  pg_stat_databaseビューで確認
– 取得できるのは累積値
– 実際に利用するには単位秒あたりの
差分値を計算する等の工夫が必要
postgres=#	 select	 datname,xact_commit,xact_rollback	 



 

 

from	 pg_stat_database	 where	 datname	 =	 'testdb';

-[	 RECORD	 1	 ]-+-------

datname	 	 	 	 	 	 	 |	 testdb

xact_commit	 	 	 |	 17727

xact_rollback	 |	 4
45
データベースのスループット(ツール活用)
•  pg_monzでスループットを確認
– DB単位にグラフを表示可能
– pg_statsinfoも同様のグラフ表示が可能
46
データベースの接続数(標準機能)
•  pg_stat_activityビューで確認
postgres=#	 SELECT	 datname,pid,state,SUBSTRING(query,1,45)	 FROM	 pg_stat_activity;

	 datname	 	 |	 	 pid	 	 |	 	 	 	 	 	 	 	 state	 	 	 	 	 	 	 	 |	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 substring	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 

----------+-------+---------------------+-----------------------------------------------

	 postgres	 |	 10162	 |	 active	 	 	 	 	 	 	 	 	 	 	 	 	 	 |	 SELECT	 datname,pid,state,SUBSTRING(query,1,45

	 testdb	 	 	 |	 10179	 |	 active	 	 	 	 	 	 	 	 	 	 	 	 	 	 |	 UPDATE	 pgbench_accounts	 SET	 abalance	 =	 abalan

	 testdb	 	 	 |	 10180	 |	 active	 	 	 	 	 	 	 	 	 	 	 	 	 	 |	 END;

	 testdb	 	 	 |	 10181	 |	 idle	 in	 transaction	 |	 UPDATE	 pgbench_tellers	 SET	 tbalance	 =	 tbalanc

	 testdb	 	 	 |	 10182	 |	 active	 	 	 	 	 	 	 	 	 	 	 	 	 	 |	 UPDATE	 pgbench_branches	 SET	 bbalance	 =	 bbalan

	 testdb	 	 	 |	 10183	 |	 active	 	 	 	 	 	 	 	 	 	 	 	 	 	 |	 END;



testdb=#	 select	 count(*)	 AS	 connections	 from	 pg_stat_activity;

	 connections	 

-------------

	 	 	 	 	 	 	 	 	 	 	 6
47
データベースの接続数(ツール活用)
•  pg_monzで接続数を確認
– インスタンス、DB単位にグラフを表示可能
– 閾値を超過したらZabbixのトリガーで検知
48
データベースの接続数(ツール活用)
•  pg_statsinfoで接続数を確認
– インスタンス単位の情報、グラフを表示可能
49
キャッシュヒット率
•  DBはディスクにアクセスしない方が速い。
– どれだけメモリだけで処理できたか?
= キャッシュヒット率
– 一般的に90%以上を維持するのが目標
50
キャッシュヒット率(標準機能)
•  pg_stat_databaseビューで確認
•  pg_statio_user_tablesビューで確認
postgres=#	 SELECT	 datname,round(blks_hit*100/(blks_hit+blks_read),	 2)	 AS	 cache_hit_ratio	 



 

 

FROM	 pg_stat_database	 WHERE	 blks_read	 >	 0;

	 datname	 	 |	 cache_hit_ratio	 

----------+-----------------

	 postgres	 |	 	 	 	 	 	 	 	 	 	 	 99.00

	 testdb	 	 	 |	 	 	 	 	 	 	 	 	 	 	 97.00

testdb=#	 SELECT	 relname,round(heap_blks_hit*100/(heap_blks_hit+heap_blks_read),	 2)	 



 

AS	 cache_hit_ratio	 FROM	 pg_statio_user_tables	 



 

WHERE	 heap_blks_read	 >	 0	 ORDER	 BY	 cache_hit_ratio;

	 	 	 	 	 relname	 	 	 	 	 	 |	 cache_hit_ratio	 

------------------+-----------------

	 pgbench_accounts	 |	 	 	 	 	 	 	 	 	 	 	 36.00

	 pgbench_branches	 |	 	 	 	 	 	 	 	 	 	 	 99.00

	 pgbench_tellers	 	 |	 	 	 	 	 	 	 	 	 	 	 99.00

	 pgbench_history	 	 |	 	 	 	 	 	 	 	 	 	 	 99.00
51
キャッシュヒット率(ツール活用)
•  pg_monzでキャッシュヒット率を確認
– DB単位にグラフを表示可能
– 閾値を下回ったらZabbixのトリガーで検知
– テーブル単位のキャッシュヒット率も収集
•  pg_statsinfoでキャッシュヒット率を確認
– DB単位に表示可能
52
チェックポイント
•  更新されたメモリ上のページをディスク
に書き出す処理
•  チェックポイント実行中に行われている
処理の性能に影響をおよぼすことがある。
– チェックポイントを頻繁に実行している?
– サーバ負荷が高い時間帯にチェックポイント
が行われている?
53
チェックポイント(標準機能)
•  ログを確認
– log_checkpointsパラメータを設定して出力
•  pg_stat_bgwriterビューで確認
testdb=#	 SELECT	 checkpoints_timed,checkpoints_req,checkpoint_write_time,



 

checkpoint_sync_time,buffers_checkpoint	 from	 pg_stat_bgwriter;

-[	 RECORD	 1	 ]---------+--------

checkpoints_timed	 	 	 	 	 |	 568

checkpoints_req	 	 	 	 	 	 	 |	 0

checkpoint_write_time	 |	 1343894

checkpoint_sync_time	 	 |	 2062

buffers_checkpoint	 	 	 	 |	 38659

2015-11-12	 13:37:53	 JST	 [7602]	 LOG:	 	 checkpoint	 starting:	 time

2015-11-12	 13:42:23	 JST	 [7602]	 LOG:	 	 checkpoint	 complete:	 wrote	 7418	 buffers	 (45.3%);	 

0	 transaction	 log	 file(s)	 added,	 0	 removed,	 0	 recycled;	 

write=269.201	 s,	 sync=0.421	 s,	 total=269.685	 s;	 sync	 files=17,	 longest=0.418	 s,	 
average=0.024	 s

2015-11-12	 17:49:22	 JST	 [10679]	 LOG:	 	 checkpoints	 are	 occurring	 too	 frequently	 (25	 
seconds	 apart)
54
チェックポイント(ツール活用)
•  pg_monzでチェックポイントを確認
– checkpoint_timeouts/segments契機で
実行されたチェックポイント実行回数を収集
– 一定期間のチェックポイント発生回数が
閾値を超過したらZabbixのトリガーで検知
•  pg_statsinfoでチェックポイントを確認
– checkpoint_timeouts/segments契機で
実行されたチェックポイント実行回数を収集
– 平均および最大の処理時間を表示可能
– チェックポイントが走った時間帯をレポート
の各種グラフに重ね合わせることも可能
55
VACUUM
•  不要なレコードを回収する処理
– ちゃんと実行されないとDBが肥大化する。
56
VACUUM(標準機能)
•  ログを確認
– log_autovacuum_min_durationパラメータ
を設定して出力
•  pg_stat_user_tablesビューで確認
2015-11-12	 13:36:30	 JST	 [10188]	 LOG:	 	 automatic	 vacuum	 of	 table	 
"testdb.public.pgbench_tellers":	 index	 scans:	 0	 pages:	 0	 removed,	 25	 remain

	 	 	 	 	 	 	 	 tuples:	 533	 removed,	 100	 remain,	 0	 are	 dead	 but	 not	 yet	 removable

	 	 	 	 	 	 	 	 buffer	 usage:	 86	 hits,	 0	 misses,	 0	 dirtied

	 	 	 	 	 	 	 	 avg	 read	 rate:	 0.000	 MB/s,	 avg	 write	 rate:	 0.000	 MB/s

	 	 	 	 	 	 	 	 system	 usage:	 CPU	 0.00s/0.00u	 sec	 elapsed	 0.00	 sec

testdb=#	 SELECT	 relname,n_live_tup,n_dead_tup,last_autovacuum,autovacuum_count	 



 

FROM	 pg_stat_user_tables	 where	 relname	 =	 'pgbench_accounts';

-[	 RECORD	 1	 ]----+------------------------------

relname	 	 	 	 	 	 	 	 	 	 |	 pgbench_accounts

n_live_tup	 	 	 	 	 	 	 |	 1002477

n_dead_tup	 	 	 	 	 	 	 |	 0

last_autovacuum	 	 |	 2015-11-12	 17:50:26.224429+09

autovacuum_count	 |	 1
57
VACUUM(ツール活用)
•  pg_monzでVACUUMを確認
– テーブル単位にVACUUMが実行された回数、
不要領域の割合を収集
•  pg_statsinfoでVACUUMを確認
– テーブル単位にVACUUMが実行された回数、
不要領域の割合を収集
– 平均および最大の処理時間を表示可能
58
一時ファイルの書き出し
•  大きなデータを処理しようとすると
ディスクに一時ファイルを作成する。
– ソートやテーブル結合時のハッシュ生成
– work_memパラメータの大きさに依存
7
4
9
2
DISK
•  対象データを全てメモリに保持
•  メモリ上でクイックソートを実行
7
4
9
2
2
4
7
9
2
4
7
9
8
1
3
5
1
3
5
8
DISK DISK
・・・
【対象データ < 作業メモリ】
作業メモリ
【対象データ > 作業メモリ】
作業メモリ
•  データの一部をメモリに保持
•  メモリ上でソート実行
•  ソート結果をDISKに戻す
繰り返し
59
一時ファイルの書き出し(標準機能)
•  ログを確認
– log_temp_filesパラメータを設定して出力
•  pg_stat_databaseビューで確認
2015-11-11	 20:52:33	 JST	 [7801]	 LOG:	 	 temporary	 file:	 path	 "base/pgsql_tmp/
pgsql_tmp7801.1",	 size	 53157

2015-11-11	 20:52:33	 JST	 [7801]	 STATEMENT:	 	 select	 *	 from	 pg_settings	 where	 
name	 =	 'log_temp_files';

postgres=#	 select	 datname,temp_files,temp_bytes	 from	 pg_stat_database	 



 

 

where	 datname	 =	 'testdb';

-[	 RECORD	 1	 ]--------

datname	 	 	 	 |	 testdb

temp_files	 |	 1

temp_bytes	 |	 14016512
60
一時ファイルの書き出し(ツール活用)
•  pg_monzで一時ファイル書き出しを確認
– DB単位に書きだされたデータ量を収集
– 閾値を超過したらZabbixのトリガーで検知
•  pg_statsinfoで一時ファイル書き出しを
確認
– DB単位に書きだされたファイル数、
データ量を収集
61
腐ったミカンは除去しよう
•  一握りの悪者が全体の足を引っ張る。
•  遅いSQLは早く見つけて撲滅しよう。
62
遅いSQL(標準機能)
•  スロークエリをログで確認
2015-11-11	 19:47:48	 JST	 [7619]	 LOG:	 	 duration:	 145.893	 ms	 	 statement:	 
select	 count(*)	 from	 pgbench_accounts;
63
遅いSQL(ツール活用)
•  auto_explainで遅いSQLの実行計画を
自動でログ記録
2015-11-11	 19:47:48	 JST	 [7619]	 LOG:	 	 duration:	 92.204	 ms	 	 plan:

	 	 	 	 	 	 	 	 Query	 Text:	 select	 count(*)	 from	 pgbench_accounts;

	 	 	 	 	 	 	 	 Aggregate	 	 (cost=29182.66..29182.67	 rows=1	 width=0)

	 	 	 	 	 	 	 	 	 	 ->	 	 Seq	 Scan	 on	 pgbench_accounts	 	 (cost=0.00..26681.53	 
rows=1000453	 width=0)
64
遅いSQL(ツール活用)
•  pg_stat_statementsでデータベース全体
への影響が大きいSQLを確認
– トータルの実行時間が長いSQL
– 実行回数が多いSQL
postgres=#	 SELECT	 datname,SUBSTRING(query,1,40)	 AS	 query,calls,



 

 

TRUNC(total_time::numeric,3)	 AS	 total_time	 



 

FROM	 pg_stat_statements	 LEFT	 OUTER	 JOIN	 pg_database	 



 

ON	 pg_stat_statements.dbid	 =	 pg_database.oid	 



 

WHERE	 datname	 =	 'testdb'	 ORDER	 BY	 total_time	 DESC	 LIMIT	 5;



	 datname	 |	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 query	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 |	 calls	 |	 total_time	 

---------+-------------------------------------------------+-------+------------

	 testdb	 	 |	 UPDATE	 pgbench_accounts	 SET	 abalance	 =	 a	 	 	 	 	 	 	 	 |	 12755	 |	 	 14088.258

	 testdb	 	 |	 select	 count(*)	 from	 pgbench_accounts;	 	 	 	 	 	 	 	 	 	 |	 	 	 	 	 3	 |	 	 	 5740.594

	 testdb	 	 |	 SELECT	 	 c.oid	 AS	 relid,	 	 	 	 	 	 	 	 	 c.relnamespace,	 |	 	 	 	 53	 |	 	 	 	 642.248

	 testdb	 	 |	 UPDATE	 pgbench_tellers	 SET	 tbalance	 =	 tb	 	 	 	 	 	 	 	 |	 12755	 |	 	 	 	 386.210

	 testdb	 	 |	 UPDATE	 pgbench_branches	 SET	 bbalance	 =	 b	 	 	 	 	 	 	 	 |	 12755	 |	 	 	 	 248.036
65
遅いSQL(ツール活用)
•  サーバログをpgBadgerで集計
– Perlスクリプトとして実装
– サーバログを指定して実行すると、ログを
分析したレポートをHTMLファイルで作成
– 永安さんの資料が詳しい。
•  pgBadgerでSQLログを分析する
http://pgsqldeepdive.blogspot.jp/2012/12/pgbadgersql.html
66
PostgreSQLのログについて考える
67
なぜそのままではダメか?
•  ログをルーティングする機能がない。
– なんでも1つのログファイルに吐き出す。
– PostgreSQLサーバが起動できないような
深刻なエラーメッセージとスロークエリログ
が混在する。
•  深刻度/使い道が異なるものがごちゃまぜ。
– エラーレベルやカテゴリで分けられないので、
ログから見たい情報を探すのが面倒
– grepするのが関の山。。。
68
file_fdw
•  FDW: 外部データラッパ
– DB外部のデータへ通常の表と同様にアクセス
– 花田さんの資料が詳しい。
•  外部データラッパによるPostgreSQLの拡張
http://www.slideshare.net/babystarmonja/postgre-sql-11764943
•  file_fdw: 外部ファイルをテーブル化
– サーバのファイルシステムにある
データファイルにアクセス
– COPY FROMで読み込み可能なフォーマット
に対応(CSV、タブ区切り等)
– 9.1からcontribとして配布されている。
69
file_fdwでログを外部テーブル化
•  CSVログを外部テーブル化してアクセス
testdb=#	 CREATE	 EXTENSION	 file_fdw;

testdb=#	 CREATE	 SERVER	 pglog	 FOREIGN	 DATA	 WRAPPER	 file_fdw;

testdb=#	 CREATE	 FOREIGN	 TABLE	 pglog	 (log_time	 timestamp(3)	 with	 time	 zone,	 

testdb(#	 	 	 user_name	 text,	 database_name	 text,	 process_id	 integer,	 

testdb(#	 	 	 connection_from	 text,	 session_id	 text,	 session_line_num	 bigint,	 

testdb(#	 	 	 command_tag	 text,	 session_start_time	 timestamp	 with	 time	 zone,

testdb(#	 	 	 virtual_transaction_id	 text,	 transaction_id	 bigint,	 error_severity	 text,	 
testdb(#	 	 	 sql_state_code	 text,	 message	 text,detail	 text,	 hint	 text,	 

testdb(#	 	 	 internal_query	 text,	 internal_query_pos	 integer,	 context	 text,

testdb(#	 	 	 query	 text,query_pos	 integer,	 location	 text,application_name	 text

testdb(#	 )	 SERVER	 pglog

testdb-#	 OPTIONS	 (filename	 '/var/lib/pgsql/9.4/data/pg_log/postgresql-Fri.csv',	 
format	 'csv');

testdb=#	 select	 log_time,user_name,database_name,process_id,error_severity,



 

message,application_name	 from	 pglog	 where	 message	 like	 'duration%';

-[	 RECORD	 1	 ]-------+------------------------------------------------------

log_time 

 

 

|	 2015-11-06	 08:33:31.528+00

user_name

 

 

|	 postgres

database_name 

 

|	 testdb

process_id

 

 

|	 8962

error_severity 

 

|	 LOG

message 

 

 

|	 duration:	 5006.931	 ms	 	 statement:	 select	 pg_sleep(5);

application_name 

|	 psql
70
file_fdwでログを外部テーブル化
•  サーバログをSQL文で検索
– 絞込みや並べ替えが可能
•  深刻度,発生時刻,データベース,プロセスNo etc
– テーブルへのロード不要
•  最新のログデータにアクセスが可能
•  データベースのサイズが膨らむ心配なし
•  複数ログファイルの検索は工夫が必要
– ローテーションによるログファイルの切替
– ファイル名を固定化(例:曜日単位)
•  postgresql-Sun.csv,postgresql-Mon.csv ...
– 9.5から外部テーブルの継承をサポート
•  複数ログテーブルのパーティション化も可能に
71
Fluentdで加工したログを収集
•  file_fdwで検索するにはこんな点が不足
– ログの種別を持っていない
•  スロークエリ,チェックポイント,デッドロックetc
– ログファイル毎に1テーブル
•  複数サーバのログをまとめたい
•  種別が違うログは分けて管理したい
– ログメッセージに含まれる値を使いたい
•  スロークエリのduration、statement
•  Fluentdで検索しやすい形にログを加工
– 詳しくはOSC 2015 Hokkaidoの資料を参照
http://www.ospn.jp/osc2015-do/pdf/OSC2015_do_tis.pdf
72
Fluentd
•  Fluentdとは
–  http://www.fluentd.org/
– 軽量でプラガブルなログ収集ツール
– Apache License Version 2.0
•  Fluentdの特徴
– ログ管理を3つの層に分けて管理
•  インプット、バッファ、アウトプット
– 各層がプラガブルなアーキテクチャ
•  用途に応じたプラグインを追加するだけで使える
73
Fluentdでログを収集する
PostgreSQL
Fluentd
(td-agent)
DBサーバ
PostgreSQL
サーバプロセス
PostgreSQLサーバログ
(postgresql.csv)
PostgreSQL
接続ライブラリ
DBサーバ
PostgreSQL
DBサーバ
Fluentd
PostgreSQL Fluentd
ログ集約サーバ
Fluentd
(td-agent)
PostgreSQL
fluentdテーブル
tag::Text (me::Times
tampz
record::Jsonb
・・・ ・・・ ・・・
74
収集したログをSQLで検索する
•  スロークエリを検索(時間が長い10件)
testdb=##SELECT	 time,	 record#>>'{hostname}'	 as	 host,	 record#>>'{duration}'	 as	 duration,	  



 

record#>>'{statement}'	 as	 statement	 



 

FROM	 fluentd	 WHERE	 tag	 =	 'pgsql.slow_query'	 

	 	 	 	 

 

ORDER	 BY	 (record#>'{duration}')	 desc	 LIMIT	 10;



	 	 	 	 	 	 	 	 	 time	 	 	 	 	 	 	 	 	 	 	 |	 	 host	 	 	 |	 duration	 |	 	 	 	 	 	 statement	 	 	 	 	 	 

------------------------+---------+----------+---------------------

	 2015-06-07	 08:33:48+00	 |	 pgsql02	 |	 2004.107	 |	 select	 pg_sleep(2);

	 2015-06-07	 02:25:08+00	 |	 pgsql01	 |	 2003.866	 |	 select	 pg_sleep(2);

	 2015-06-07	 08:45:48+00	 |	 pgsql03	 |	 2003.767	 |	 select	 pg_sleep(2);

	 2015-06-07	 02:25:10+00	 |	 pgsql01	 |	 2003.621	 |	 select	 pg_sleep(2);

	 2015-06-07	 08:45:51+00	 |	 pgsql03	 |	 2003.461	 |	 select	 pg_sleep(2);

	 2015-06-07	 08:33:51+00	 |	 pgsql02	 |	 2003.376	 |	 select	 pg_sleep(2);

	 2015-06-07	 02:25:02+00	 |	 pgsql01	 |	 2003.374	 |	 select	 pg_sleep(2);

	 2015-06-07	 08:33:54+00	 |	 pgsql02	 |	 2003.247	 |	 select	 pg_sleep(2);

	 2015-06-07	 08:45:46+00	 |	 pgsql03	 |	 2002.880	 |	 select	 pg_sleep(2);

	 2015-06-07	 02:25:05+00	 |	 pgsql01	 |	 2002.092	 |	 select	 pg_sleep(2);
75
pg_monzでスロークエリを監視
pg_monzをカスタマイズすれば、
スロークエリの発生回数も監視できる
76
まとめ
77
監視の観点を理解しよう
•  救急患者レベル
•  レントゲンに怪しい影が、、レベル
•  体力測定レベル
•  腐ったミカン = 遅いSQL
78
ツールをうまく組み合わせよう
•  pg_monzは「監視」ツール
– 発生した問題に即座にアクションを起こす。
– 性能分析に使う情報「も」集められる。
•  pg_statsinfoは「性能分析」ツール
– 過去時点の情報をひとまず保管しておき、
後でゆっくりと問題を分析する。
– 発生した問題に対するアクションは、
別の監視ツールに任せる。
•  PostgreSQLのサーバログ
– 障害メッセージは監視ツールで素早く検出
– 後で分析するログはFluentdで収集
79
pg_monz をよろしくおねがいします
•  入手先や使い方
http://pg-monz.github.io/pg_monz/
•  問い合わせ
– pg_monz ユーザーグループ
pg_monz@googlegroups.com
•  試行環境を自動構築するAnsible
Playbook等をGitHubから入手できます。
https://github.com/tech-sketch/pg_monz-trial
•  フィードバックをお待ちしています。

あなたの知らないPostgreSQL監視の世界