Skip to content
ZERONE
Nazaj na vpoglede
Debugging2026-04-18 · 5 min branjaIz Case 01

Simptom ≠ Vzrok: kako je auto-healer postal pravi problem

PostgreSQL primary na 91 % CPU. Auto-healer pobije najglasnejši query. Uro kasneje: spet 91 %. Lekcija: hitri popravki se lahko zaklenejo v neskončno zanko, če nihče ne vpraša, kateri vzorec se ponavlja.

PostgreSQL primary na 91 % CPU. Auto-healer teče vsakih 5 minut, najde najglasnejši query, pošlje pg_cancel_backend(), in load pade na 35 %. Uro kasneje: spet 91 %. Healer pobije naslednji query. Spet 35 %. Spet ura. Spet 91 %.

Lahko bi razglasili, da »sistem deluje«. Ne deluje. Žge CPU cikle v boju s simptomom, ki ga nikoli ne razume.

Trenutek iskrenosti

Po treh ciklih smo prenehali. Namesto agresivnejšega tuninga healerja smo si zastavili vprašanje, ki bi ga morali postaviti že od začetka: Kaj vrača load?

Odgovor, po 20 minutah audita: 14 različnih backend endpointov kliče isto agregacijo prek 1,4 milijona vrstic — COUNT(*) FILTER (...) — brez cache locka. Pri vsakem cache missu osem paralelnih uvicorn workerjev istočasno sproži isti drag query. Thundering herd.

Healer je imel prav, da obstajajo queryji, ki ne bi smeli biti aktivni. Healer je imel narobe, da jih ubijanje reši. Problem je bil, da je 14 klientov istočasno zgrabilo isto kravo za vime.

Kaj je bilo namesto tega potrebno

  • Na cache ključ natanko en lock. Uporabili smo Redis SET NX EX kot distributed lock plus asyncio.Lock na workerja za lokalni short-circuit.
  • Najdenih 14 endpointov, trije kritični takoj popravljeni, preostalih enajst dokumentiranih z roki v tiketu.
  • Healerja nismo tunirali. Healer sploh ni bil problem.

Po fixu: CPU load stabilno na 53 %. Nič več eskalacij. Noben healer cikel ni potreben.

Meta-lekcija

Vsak sistem ima točko, kjer simptom deluje zanimivejši od vzroka. Simptom je glasen, viden in se ga »reši« s kratkim skriptom. Vzrok sedi tri sloje abstrakcije globlje, nima imena in zahteva, da nekdo res razume podsistem.

Pravilo, ki si ga postavljamo pri vsakem ponovljenem incidentu:

»Če zdaj zaženemo ta fix — kaj preprečuje, da bi v eni uri spet stali tu?«

Če odgovor ni jasen, načrtovani fix ni fix. Je dušilec simptomov, in sistem bo našel drug, glasnejši način, da signalizira isti vzrok.

Velja daleč onkraj baz

Vsak senior inženir pozna ta vzorec:

  • Flaky test? Slepi retry v CI je dušenje simptomov. Test razkriva resnično race condition.
  • Memory leak? Pod restart vsakih 6 h je dušenje simptomov. Leak medtem žveka uporabniške podatke.
  • Bounce rate na buttonu? A/B test z novo barvo je dušenje simptomov. Feature ne reši uporabnikovega problema.

Pri vsakem ponovljenem problemu: identificiraj pet potrošnikov prizadetega podsistema in preveri vzorec tam — ne le na mestu, kjer je bil alert glasen.

Podoben izziv tudi pri vas?

Verjetno smo že videli kaj podobnega. Pogovorimo se.

Začnimo pogovor