Every connection slot is taken INC-2537

OpenDatabases · Medium · Fix · about 30 min ·Linux

Lab machine

A private Linux machine with the problem already set up. Sessions last up to 60 minutes.
Sal Brennan opened INC-2537 at 07:50SEV-2

The Ledger settlement batch has failed every run since 02:10. The database is up and idle, yet it refuses Ledger with "remaining connection slots are reserved".

Ledger books what Northstar owes each carrier. If the batch does not run, carriers are paid late and invoice Northstar for it.

"Postgres has 20 connections and that box has 2 GB of RAM, so no, we are not raising max_connections to 500 again." (Mara)

Each PostgreSQL connection is a server process with its own memory. The server keeps a few slots for superusers, which is how you can still get in.

Your task

Get the Ledger batch booking again, and make sure the client that caused this cannot take the whole server down the next time it restarts. Keep max_connections at 20 and keep the reconciler running.

On the machine

  • bin/hostlog -u ledger-settle, var/log/postgresql.log
  • psql -c "SELECT usename, state, xact_start, query FROM pg_stat_activity"
  • opt/reconciler/reconciler.py, bin/hostctl list-units

Timeline

01:45Docklight reconciler 3.2.1 deployed.
02:10Ledger batch: "remaining connection slots are reserved". Every run since.
07:30"We are not raising max_connections to 500 again." (Mara)
07:50INC-2537 lands with you. Carriers invoice on Monday.

Done when

  1. The Ledger batch connects and books settlements.
  2. A restarted reconciler cannot use up the server's connections again.
  3. max_connections stays at 20, and the reconciler keeps running.

Hints

Hint 1

You connect as a superuser, so you get a reserved slot. Use it to look at pg_stat_activity.

Hint 2

Group the sessions by user and state. "idle in transaction" is a session holding a transaction open.

Hint 3

Terminating the sessions frees slots for about as long as the reconciler takes to open new ones.

Hint 4

PostgreSQL can limit connections per role, and can end sessions that sit idle in a transaction.

Show the solution

As `postgres`, run `ALTER ROLE reconciler CONNECTION LIMIT 5;` (and ideally `ALTER ROLE reconciler SET idle_in_transaction_session_timeout = '30s';`), then end its existing sessions with `SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE usename = 'reconciler';`. Ledger connects again, and file a bug for the missing COMMIT.