From 9e5868b8398deacfec0a1062d7400ae17ca4bfc7 Mon Sep 17 00:00:00 2001 From: rouggy Date: Tue, 21 Jul 2026 16:50:48 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20raise=20MySQL=20pool=208->16=20=E2=80=94?= =?UTF-8?q?=208=20starved=20the=20instance's=20own=20live-sync=20polling?= =?UTF-8?q?=20(revision=20+=20grid=20refresh=20+=20live=5Fstatus=20+=20cha?= =?UTF-8?q?t),=20so=20the=20grid=20stopped=20showing=20other=20operators'?= =?UTF-8?q?=20QSOs;=2016=20avoids=20the=20stall=20and=20still=20fits=20~15?= =?UTF-8?q?=20ops=20under=20max=5Fconnections=3D300?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- internal/db/mysql.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/internal/db/mysql.go b/internal/db/mysql.go index 36592c3..85755c0 100644 --- a/internal/db/mysql.go +++ b/internal/db/mysql.go @@ -129,19 +129,21 @@ func translateTextColumns(s string) string { // OpenMySQL opens the shared MySQL logbook, creating the database if needed, // then applies the (translated) embedded migrations. multiStatements is enabled // so multi-statement migration files run in a single Exec. -// tuneMySQLPool sizes the connection pool for a SHARED server. A multi-operator -// special event runs many OpsLog instances against ONE MySQL, whose max_connections -// is a hard global limit (often 100–151). A big per-instance pool (we used 50) let -// a handful of ops exhaust the server — "Error 1040: Too many connections" — after -// which queries (the on-air widget, award_refs, the grid) fail silently and the UI -// looks frozen. A modest cap with brisk idle reaping keeps each instance's server -// footprint small so ~10+ ops fit, while still absorbing the UI's concurrent -// logbook queries. No max lifetime: a slow first migration can run for minutes on a -// single connection and reaping it mid-migration drops the selected database. +// tuneMySQLPool sizes the connection pool for a SHARED server. Two opposing needs: +// - A big per-instance pool (we shipped 50) let a handful of ops exhaust the +// server's global max_connections — "Error 1040: Too many connections". +// - Too SMALL a pool starves this instance's OWN concurrent UI queries — the live +// multi-op sync (revision poll every 2s + a 3-query grid refresh), live_status, +// chat, stats, cluster — so the grid stops showing other operators' QSOs. (8 was +// too tight and reintroduced this "deadlock-like stall".) +// 16 is the balance: plenty for the UI's bursts, and ~15 ops still fit under a +// raised max_connections=300 (advise operators to raise it for a big multi-op). +// Brisk idle reaping returns slots to the server; no max lifetime so a slow first +// migration on one connection isn't reaped mid-run (drops the selected database). func tuneMySQLPool(conn *sql.DB) { - conn.SetMaxOpenConns(8) - conn.SetMaxIdleConns(3) - conn.SetConnMaxIdleTime(30 * time.Second) // return idle connections to the server promptly + conn.SetMaxOpenConns(16) + conn.SetMaxIdleConns(6) + conn.SetConnMaxIdleTime(30 * time.Second) conn.SetConnMaxLifetime(0) }