[POSTGRESQL] PostgreSQL Production Monitoring Queries - fourslickz/notes GitHub Wiki
PostgreSQL Production Monitoring Queries
Kumpulan query untuk monitoring PostgreSQL 15 production.
Server Reference
| Parameter | Value |
|---|---|
| PostgreSQL | 15 |
| RAM | 16 GB |
| Current max_connections | 100 |
| Target max_connections | 200 |
| Swap | 0 |
| Config | /etc/postgresql/15/main/postgresql.conf |
1. Connection Monitoring
1.1 Total Connections by State
SELECT
state,
count(*) AS connections
FROM pg_stat_activity
GROUP BY state
ORDER BY connections DESC;
Status yang perlu diperhatikan:
active— sedang menjalankan queryidle— connection tersedia tetapi sedang tidak menjalankan queryidle in transaction— transaction terbuka tetapi tidak sedang menjalankan queryNULL— biasanya proses background PostgreSQL
2. Connection Usage
2.1 Total Connection vs Max Connection
SELECT
current_setting('max_connections')::int AS max_connections,
count(*) AS current_connections,
round(
100.0 * count(*) /
current_setting('max_connections')::int,
2
) AS usage_percent
FROM pg_stat_activity;
Recommended Threshold
| Usage | Status |
|---|---|
| < 60% | Normal |
| 60–80% | Monitor |
| 80–90% | Warning |
| 90–95% | Critical |
| > 95% | Emergency |
Dengan max_connections = 200:
- 80% = 160 connections
- 90% = 180 connections
- 95% = 190 connections
3. Connections by User
SELECT
usename,
count(*) AS connections
FROM pg_stat_activity
GROUP BY usename
ORDER BY connections DESC;
Berguna untuk mengetahui PostgreSQL user mana yang paling banyak menggunakan connection.
4. Connections by Database
SELECT
datname,
count(*) AS connections
FROM pg_stat_activity
GROUP BY datname
ORDER BY connections DESC;
5. Connections by Application
SELECT
application_name,
count(*) AS connections
FROM pg_stat_activity
GROUP BY application_name
ORDER BY connections DESC;
6. Detailed Connection Distribution
SELECT
usename,
application_name,
client_addr,
state,
count(*) AS connections
FROM pg_stat_activity
GROUP BY
usename,
application_name,
client_addr,
state
ORDER BY connections DESC;
Ini merupakan query utama untuk investigasi TooManyConnections.
7. Active Connections
SELECT
count(*) AS active_connections
FROM pg_stat_activity
WHERE state = 'active';
8. Active Queries
SELECT
pid,
usename,
application_name,
client_addr,
now() - query_start AS duration,
state,
wait_event_type,
wait_event,
LEFT(query, 300) AS query
FROM pg_stat_activity
WHERE state = 'active'
ORDER BY query_start;
9. Long Running Queries
Menampilkan query yang berjalan lebih dari 5 detik.
SELECT
pid,
usename,
application_name,
client_addr,
now() - query_start AS duration,
wait_event_type,
wait_event,
LEFT(query, 500) AS query
FROM pg_stat_activity
WHERE state = 'active'
AND now() - query_start > interval '5 seconds'
ORDER BY query_start;
Recommended thresholds:
-
5 seconds → investigate
-
30 seconds → warning
-
60 seconds → critical
10. Idle in Transaction
SELECT
pid,
usename,
application_name,
client_addr,
now() - xact_start AS transaction_age,
now() - state_change AS idle_duration,
LEFT(query, 300) AS query
FROM pg_stat_activity
WHERE state = 'idle in transaction'
ORDER BY xact_start;
Jika terdapat idle in transaction selama beberapa menit atau lebih, lakukan investigasi.
Potensi dampak:
- lock
- bloat
- VACUUM tertahan
- penggunaan resource meningkat
11. Long Idle Connections
SELECT
pid,
usename,
application_name,
client_addr,
backend_start,
state_change,
now() - state_change AS idle_for
FROM pg_stat_activity
WHERE state = 'idle'
ORDER BY state_change ASC;
12. Connection Age
SELECT
pid,
usename,
application_name,
client_addr,
state,
now() - backend_start AS connection_age
FROM pg_stat_activity
ORDER BY backend_start;
13. Blocking / Lock Monitoring
SELECT
blocked.pid AS blocked_pid,
blocked.usename AS blocked_user,
blocking.pid AS blocking_pid,
blocking.usename AS blocking_user,
now() - blocked.query_start AS blocked_duration,
LEFT(blocked.query, 200) AS blocked_query,
LEFT(blocking.query, 200) AS blocking_query
FROM pg_stat_activity blocked
JOIN pg_stat_activity blocking
ON blocking.pid = ANY(pg_blocking_pids(blocked.pid))
ORDER BY blocked.query_start;
Jika hasilnya 0 rows, tidak ada blocking pada saat query dijalankan.
14. Database Size
SELECT
datname,
pg_size_pretty(pg_database_size(datname)) AS size
FROM pg_database
ORDER BY pg_database_size(datname) DESC;
15. Largest Tables
Jalankan pada database yang ingin diperiksa.
SELECT
schemaname,
relname AS table_name,
pg_size_pretty(pg_total_relation_size(relid)) AS total_size,
pg_size_pretty(pg_relation_size(relid)) AS table_size,
pg_size_pretty(pg_indexes_size(relid)) AS index_size
FROM pg_catalog.pg_statio_user_tables
ORDER BY pg_total_relation_size(relid) DESC
LIMIT 20;
total_size— table + indextable_size— ukuran data tableindex_size— ukuran index
16. Cache Hit Ratio
SELECT
sum(blks_hit) AS cache_hits,
sum(blks_read) AS disk_reads,
round(
100.0 * sum(blks_hit) /
NULLIF(sum(blks_hit) + sum(blks_read), 0),
2
) AS cache_hit_ratio
FROM pg_stat_database;
Untuk workload OLTP, cache hit ratio yang tinggi umumnya diharapkan.
17. Transaction Statistics
SELECT
datname,
xact_commit,
xact_rollback,
tup_inserted,
tup_updated,
tup_deleted,
tup_returned,
tup_fetched
FROM pg_stat_database
WHERE datname IS NOT NULL
ORDER BY xact_commit DESC;
18. Deadlocks
SELECT
datname,
deadlocks,
conflicts,
temp_files,
temp_bytes
FROM pg_stat_database
WHERE datname IS NOT NULL
ORDER BY deadlocks DESC;
Perhatikan terutama jika nilai deadlocks terus bertambah.
19. PostgreSQL Configuration
19.1 Max Connections
SHOW max_connections;
19.2 Important Memory Settings
SELECT
name,
setting,
unit
FROM pg_settings
WHERE name IN (
'max_connections',
'shared_buffers',
'work_mem',
'maintenance_work_mem'
);
20. PostgreSQL Server Configuration
SHOW config_file;
Contoh:
/etc/postgresql/15/main/postgresql.conf
21. Quick Production Health Check
Connection
SELECT
current_setting('max_connections')::int AS max_connections,
count(*) AS current_connections,
round(
100.0 * count(*) /
current_setting('max_connections')::int,
2
) AS usage_percent
FROM pg_stat_activity;
Connection Distribution
SELECT
state,
count(*) AS connections
FROM pg_stat_activity
GROUP BY state
ORDER BY connections DESC;
Connection by User
SELECT
usename,
count(*) AS connections
FROM pg_stat_activity
GROUP BY usename
ORDER BY connections DESC;
Active Query
SELECT
pid,
usename,
application_name,
now() - query_start AS duration,
wait_event_type,
wait_event,
LEFT(query, 300) AS query
FROM pg_stat_activity
WHERE state = 'active'
ORDER BY query_start;
Blocking
SELECT
blocked.pid AS blocked_pid,
blocking.pid AS blocking_pid,
now() - blocked.query_start AS blocked_duration,
LEFT(blocked.query, 200) AS blocked_query,
LEFT(blocking.query, 200) AS blocking_query
FROM pg_stat_activity blocked
JOIN pg_stat_activity blocking
ON blocking.pid = ANY(pg_blocking_pids(blocked.pid))
ORDER BY blocked.query_start;
Idle in Transaction
SELECT
pid,
usename,
application_name,
client_addr,
now() - xact_start AS transaction_age,
LEFT(query, 300) AS query
FROM pg_stat_activity
WHERE state = 'idle in transaction'
ORDER BY xact_start;
22. Recommended Monitoring for This Server
Server reference:
RAM : 16 GB
PostgreSQL : 15
max_connections : 200
Swap : 0
| Priority | Metric | Warning |
|---|---|---|
| High | Connection usage | > 80% |
| High | Idle in transaction | > 1–5 min |
| High | Blocking query | Any |
| Medium | Long query | > 5 sec |
| Medium | Deadlock | Increasing |
| Medium | Cache hit ratio | Decreasing |
| Medium | Database size | Rapid growth |
| Medium | Table/index size | Rapid growth |
23. Connection Budget
Dengan:
max_connections = 200
gunakan prinsip berikut:
| Connections | Status |
|---|---|
| 0–120 | Normal |
| 120–160 | Monitor |
| 160–180 | Warning |
| 180–190 | Critical |
| 190–200 | Emergency |
Jangan menargetkan penggunaan hingga 200.
Sediakan connection reserve untuk:
- PostgreSQL administration
- monitoring
- maintenance
- unexpected traffic spike
- application reconnect
- troubleshooting
24. Useful PostgreSQL Commands
PostgreSQL Status
sudo systemctl status postgresql --no-pager
PostgreSQL Version
sudo -u postgres psql -c "SELECT version();"
PostgreSQL Config
sudo -u postgres psql -c "SHOW config_file;"
Max Connections
sudo -u postgres psql -c "SHOW max_connections;"
Current Connections
sudo -u postgres psql -c \
"SELECT count(*) AS connections FROM pg_stat_activity;"
Memory
free -m
CPU
nproc
Disk
df -h
25. Emergency Connection Check
Jika aplikasi mendapatkan:
P2037
TooManyConnections
remaining connection slots are reserved
jalankan:
SELECT
current_setting('max_connections')::int AS max_connections,
count(*) AS current_connections,
round(
100.0 * count(*) /
current_setting('max_connections')::int,
2
) AS usage_percent
FROM pg_stat_activity;
Kemudian:
SELECT
usename,
application_name,
client_addr,
state,
count(*) AS connections
FROM pg_stat_activity
GROUP BY
usename,
application_name,
client_addr,
state
ORDER BY connections DESC;
Kemudian:
SELECT
pid,
usename,
application_name,
client_addr,
state,
now() - state_change AS idle_for,
LEFT(query, 200) AS query
FROM pg_stat_activity
ORDER BY state_change;
Jangan langsung melakukan pg_terminate_backend() terhadap semua connection. Identifikasi service terlebih dahulu.