From e7cfa261c8fcb0ada57fbbdf66c8d8012d30b1ae Mon Sep 17 00:00:00 2001 From: iwanhae Date: Mon, 31 Aug 2026 22:21:53 +0900 Subject: [PATCH] 010: memory & stability tuning for 1GB e2-micro max_connections 100->30, effective_cache_size 768MB, statement_timeout 30s, idle_in_transaction_session_timeout 60s, temp_file_limit 2GB via conf.d drop-in; restart only when max_connections changes. --- migrations/010-tune-postgres.sh | 100 ++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 migrations/010-tune-postgres.sh diff --git a/migrations/010-tune-postgres.sh b/migrations/010-tune-postgres.sh new file mode 100644 index 0000000..dca711e --- /dev/null +++ b/migrations/010-tune-postgres.sh @@ -0,0 +1,100 @@ +#!/usr/bin/env bash +# 010-tune-postgres - Memory & stability tuning for the 1GB e2-micro host +# (B-tier of the 2026-08 tuning review). Settings land as a conf.d drop-in; +# postgresql.conf itself stays pristine (include_dir = 'conf.d' is stock). +# +# max_connections 100 -> 30 each backend costs MBs; real +# concurrency comes from PgBouncer +# (013). 30 = pool 20 + admin headroom +# effective_cache_size 4GB -> 768MB planner hint; box has 1GB, the 4GB +# default overrates cache -> bad plans +# work_mem 4MB (explicit, equals default; kept for determinism) +# statement_timeout 0 -> 30s runaway-query guard; long migrations: +# SET statement_timeout = 0; in-session +# idle_in_transaction_session_timeout 0 -> 60s leaked transactions block +# vacuum and hold locks; kill them +# temp_file_limit -1 -> 2GB per-backend sort-spill cap so one bad +# query cannot fill the 20G data disk +# up: write drop-in; restart only if max_connections changes, else reload +# down: remove drop-in; restart (restoring max_connections needs it) +set -euo pipefail + +PGBIN=/etc/postgresql/18/main +CONF=$PGBIN/conf.d/010-tune-postgres.conf +CLUSTER=$(pg_lsclusters --no-header | awk 'NR==1{print $1"/"$2}') + +# desired state as "guc value" pairs; SHOW renders exactly these strings +WANT=( + 'max_connections 30' + 'effective_cache_size 768MB' + 'work_mem 4MB' + 'statement_timeout 30s' + 'idle_in_transaction_session_timeout 60s' + 'temp_file_limit 2GB' +) + +pg() { runuser -u postgres -- psql -d postgres -v ON_ERROR_STOP=1 -tAc "$1"; } + +write_conf() { + install -d -m 755 "$PGBIN/conf.d" + cat > "$CONF" <<'EOF' +# managed by sysmig 010-tune-postgres - memory & stability for 1GB e2-micro +max_connections = 30 +effective_cache_size = 768MB +work_mem = 4MB +statement_timeout = 30s +idle_in_transaction_session_timeout = 60s +temp_file_limit = 2GB +EOF + chown root:postgres "$CONF" + chmod 644 "$CONF" +} + +case "${1:-}" in + up) + write_conf + if [[ $(pg 'SHOW max_connections') != 30 ]]; then + pg_ctlcluster "$CLUSTER" restart + pg_isready -q + echo " cluster restarted (max_connections requires it)" + else + pg_ctlcluster "$CLUSTER" reload + echo " cluster reloaded" + fi + for kv in "${WANT[@]}"; do + read -r guc want <<<"$kv" + got=$(pg "SHOW $guc") + [[ $got == "$want" ]] || { echo "FATAL: $guc is '$got', expected '$want'" >&2; exit 1; } + done + echo " ${#WANT[@]} memory/stability settings active" + ;; + status) + if [[ $EUID -eq 0 ]]; then + q() { runuser -u postgres -- psql -d postgres -v ON_ERROR_STOP=1 -tAc "$1"; } + elif psql -d postgres -tAc 'SELECT 1' >/dev/null 2>&1; then + q() { psql -d postgres -v ON_ERROR_STOP=1 -tAc "$1"; } + else + echo "? needs root or peer DB access to verify" + exit 2 + fi + [[ -f $CONF ]] || { echo "DRIFT drop-in $CONF missing"; exit 1; } + bad=() + for kv in "${WANT[@]}"; do + read -r guc want <<<"$kv" + got=$(q "SHOW $guc" 2>/dev/null) + [[ $got == "$want" ]] || bad+=("$guc=$got(want $want)") + done + if ((${#bad[@]})); then echo "DRIFT ${bad[*]}"; exit 1; fi + echo "OK ${#WANT[@]} settings active (max_connections=30, timeouts, temp_file_limit)" + ;; + down) + rm -f "$CONF" + if [[ $(pg 'SHOW max_connections') == 30 ]]; then + pg_ctlcluster "$CLUSTER" restart + echo " drop-in removed, cluster restarted (defaults restored)" + else + pg_ctlcluster "$CLUSTER" reload + echo " drop-in removed, cluster reloaded" + fi + ;; +esac