Skip to main content

postgresql

Administer PostgreSQL databases. Configure replication, backups, and performance tuning. Use when managing PostgreSQL deployments.

소스 정보

저장소
BagelHole/DevOps-Security-Agent-Skills
최근 소스 활동
2026년 3월 24일 22:02
감지된 SKILL.md 언어
영어
스타
1,162
포크
165

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
postgresql
description
Administer PostgreSQL databases. Configure replication, backups, and performance tuning. Use when managing PostgreSQL deployments.
license
MIT
metadata
{"author":"devops-skills","version":"1.0"}
# PostgreSQL Administer, optimize, and secure PostgreSQL databases in development and production environments. ## When to Use - You need a reliable, ACID-compliant relational database. - Your application requires advanced features such as JSONB, full-text search, or CTEs. - You are setting up streaming replication or point-in-time recovery. - You need to tune an existing PostgreSQL deployment for better throughput. ## Prerequisites - Linux server (Debian/Ubuntu or RHEL-based) or Docker. - Root or sudo access for package installation. - Familiarity with SQL fundamentals. ## Installation and Setup ```bash # Debian / Ubuntu sudo apt update sudo apt install -y postgresql postgresql-contrib # RHEL / Amazon Linux sudo dnf install -y postgresql15-server postgresql15-contrib sudo postgresql-setup --initdb sudo systemctl enable --now postgresql # Verify psql --version sudo systemctl status postgresql ``` ## Initial User and Database Setup ```bash # Switch to the postgres system user sudo -u postgres psql ``` ```sql -- Create an application user CREATE USER myapp WITH PASSWORD 'strong_password_here'; -- Create the database owned by that user CREATE DATABASE mydb OWNER myapp; -- Grant connection privileges GRANT ALL PRIVILEGES ON DATABASE mydb TO myapp; -- Connect to the database and set default privileges \c mydb ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO myapp; ``` ## psql Commands Reference ``` \l -- list databases \dt -- list tables in current database \d+ tablename -- describe table with storage info \du -- list roles \x -- toggle expanded output \timing on -- show query execution time \i file.sql -- execute SQL from file \copy -- fast client-side COPY ``` ## Configuration Tuning Edit `/etc/postgresql/15/main/postgresql.conf` (path varies by OS and version). ```ini # Connection settings listen_addresses = '*' max_connections = 200 # Memory — adjust to ~25% of total RAM for shared_buffers shared_buffers = 4GB effective_cache_size = 12GB work_mem = 16MB maintenance_work_mem = 512MB # WAL / write performance wal_buffers = 64MB checkpoint_completion_target = 0.9 min_wal_size = 1GB max_wal_size = 4GB # Planner random_page_cost = 1.1 # lower for SSD effective_io_concurrency = 200 # for SSD # Logging log_min_duration_statement = 250 # log queries slower than 250 ms log_checkpoints = on log_connections = on log_disconnections = on log_lock_waits = on ``` ```bash # Reload configuration without restart sudo -u postgres psql -c "SELECT pg_reload_conf();" # Some settings (shared_buffers, max_connections) require a full restart sudo systemctl restart postgresql ``` ## pg_hba.conf — Client Authentication ``` # /etc/postgresql/15/main/pg_hba.conf # TYPE DATABASE USER ADDRESS METHOD local all postgres peer host mydb myapp 10.0.0.0/8 scram-sha-256 host all all 0.0.0.0/0 reject ``` ```bash sudo systemctl reload postgresql ``` ## Backup and Restore ### Logical Backups with pg_dump ```bash # Plain SQL backup pg_dump -U myapp -h localhost mydb > /backups/mydb_$(date +%F).sql # Custom compressed format (recommended) pg_dump -U myapp -h localhost -Fc mydb > /backups/mydb_$(date +%F).dump # Backup a single table pg_dump -U myapp -h localhost -t orders -Fc mydb > /backups/orders.dump # Restore from custom format pg_restore -U myapp -h localhost -d mydb --clean --if-exists /backups/mydb_2025-01-15.dump # Restore plain SQL psql -U myapp -h localhost -d mydb < /backups/mydb_2025-01-15.sql ``` ### Physical Backups with pg_basebackup ```bash # Full base backup (used for PITR and replica seeding) pg_basebackup -h localhost -U replicator -D /backups/base_$(date +%F) \ --wal-method=stream --checkpoint=fast --progress --verbose # Verify the backup pg_verifybackup /backups/base_2025-01-15 ``` ## Streaming Replication ### Primary Server ```sql -- Create replication user CREATE USER replicator WITH REPLICATION LOGIN PASSWORD 'repl_secret'; ``` ```ini # postgresql.conf on primary wal_level = replica max_wal_senders = 5 wal_keep_size = 1GB ``` ``` # pg_hba.conf on primary host replication replicator 10.0.0.0/8 scram-sha-256 ``` ### Replica Server ```bash # Stop PostgreSQL on the replica sudo systemctl stop postgresql # Remove existing data directory sudo rm -rf /var/lib/postgresql/15/main/* # Base backup from primary sudo -u postgres pg_basebackup \ -h 10.0.0.1 -U replicator \ -D /var/lib/postgresql/15/main \ --wal-method=stream --checkpoint=fast --progress # Create standby signal file sudo -u postgres touch /var/lib/postgresql/15/main/standby.signal ``` ```ini # postgresql.conf on replica primary_conninfo = 'host=10.0.0.1 port=5432 user=replicator password=repl_secret' hot_standby = on ``` ```bash sudo systemctl start postgresql ``` ### Verify Replication ```sql -- On primary SELECT client_addr, state, sent_lsn, replay_lsn FROM pg_stat_replication; -- On replica SELECT pg_is_in_recovery(); -- should return true SELECT pg_last_wal_receive_lsn(); SELECT pg_last_wal_replay_lsn(); ``` ## Monitoring Queries ```sql -- Active connections by state SELECT state, COUNT(*) FROM pg_stat_activity GROUP BY state; -- Long-running queries (> 30 seconds) SELECT pid, now() - query_start AS duration, query FROM pg_stat_activity WHERE state = 'active' AND now() - query_start > interval '30 seconds' ORDER BY duration DESC; -- Table bloat and dead tuples SELECT relname, n_live_tup, n_dead_tup, ROUND(n_dead_tup::numeric / GREATEST(n_live_tup, 1) * 100, 2) AS dead_pct FROM pg_stat_user_tables ORDER BY n_dead_tup DESC LIMIT 10; -- Index usage statistics SELECT relname, indexrelname, idx_scan, idx_tup_read, idx_tup_fetch FROM pg_stat_user_indexes ORDER BY idx_scan ASC LIMIT 10; -- Cache hit ratio (should be > 99%) SELECT ROUND( 100.0 * sum(blks_hit) / NULLIF(sum(blks_hit) + sum(blks_read), 0), 2 ) AS cache_hit_pct FROM pg_stat_database; -- Database size SELECT pg_database.datname, pg_size_pretty(pg_database_size(pg_database.datname)) AS size FROM pg_database ORDER BY pg_database_size(pg_database.datname) DESC; ``` ## Docker Compose Setup ```yaml # docker-compose.yml version: "3.9" services: postgres: image: postgres:16-alpine restart: unless-stopped ports: - "5432:5432" environment: POSTGRES_USER: myapp POSTGRES_PASSWORD: secret POSTGRES_DB: mydb volumes: - pg_data:/var/lib/postgresql/data - ./init.sql:/docker-entrypoint-initdb.d/init.sql command: > postgres -c shared_buffers=256MB -c work_mem=8MB -c maintenance_work_mem=128MB -c effective_cache_size=768MB -c log_min_duration_statement=250 healthcheck: test: ["CMD-SHELL", "pg_isready -U myapp -d mydb"] interval: 10s timeout: 5s retries: 5 pgbouncer: image: edoburu/pgbouncer:latest restart: unless-stopped ports: - "6432:6432" environment: DATABASE_URL: postgres://myapp:secret@postgres:5432/mydb POOL_MODE: transaction MAX_CLIENT_CONN: 500 DEFAULT_POOL_SIZE: 40 depends_on: postgres: condition: service_healthy volumes: pg_data: ``` ```bash docker compose up -d psql -h 127.0.0.1 -p 6432 -U myapp mydb ``` ## Maintenance Tasks ```bash # Manual VACUUM and ANALYZE sudo -u postgres psql -d mydb -c "VACUUM ANALYZE;" # Reindex a bloated index sudo -u postgres psql -d mydb -c "REINDEX INDEX CONCURRENTLY idx_orders_user_id;" # Check for unused indexes sudo -u postgres psql -d mydb -c " SELECT indexrelname, idx_scan FROM pg_stat_user_indexes WHERE idx_scan = 0 ORDER BY pg_relation_size(indexrelid) DESC;" ``` ## Troubleshooting | Symptom | Likely Cause | Fix | |---|---|---| | `FATAL: too many connections` | Connection limit reached | Increase `max_connections` or add PgBouncer | | Slow SELECT on large table | Missing index or stale statistics | Run `EXPLAIN ANALYZE`; add index; run `ANALYZE` | | High CPU from autovacuum | Large number of dead tuples | Tune `autovacuum_vacuum_cost_delay`; run manual `VACUUM` | | Replication lag increasing | Replica under-provisioned or network bottleneck | Check `pg_stat_replication`; increase `wal_keep_size` | | `could not access file "base/..."` | Disk full or corrupt data directory | Free disk space; restore from `pg_basebackup` | | `FATAL: password authentication failed` | Wrong credentials or pg_hba.conf mismatch | Verify pg_hba.conf entries and reload | ## Related Skills - [mysql](../mysql/) - Alternative relational database - [database-backups](../database-backups/) - Automated backup strategies - [redis](../redis/) - Caching layer to reduce database load - [planetscale](../planetscale/) - Managed MySQL-compatible alternative
GitHub에서 보기