Incidentu reaģēšana

ClickHouse "Too many simultaneous queries" (kļūda 202): cēloņi un risinājumi

Paneļi sāk krist ar kodu 202, kamēr serveris izskatās noslogots, bet vesels. ClickHouse ir sasniedzis vienu no sešiem vienlaicīguma limitiem. Lūk, kā noteikt, kuru, kā redzēt, kas aizņem vietas, un kā iestatīt limitus, kas aizsargā serveri, neizslēdzot jūs pašus.

· 12 min lasīšanai · AG Data komanda

ClickHouse kļūda "Too many simultaneous queries" (kods 202, TOO_MANY_SIMULTANEOUS_QUERIES) nozīmē, ka serveris atteicās sākt vaicājumu, jo vienlaicīguma limits jau bija sasniegts. Nekas nav salūzis, un dati nav apdraudēti. Taču panelim vai servisam, kas saņēma kļūdu, tas izskatās pēc dīkstāves, un vienkārša limita palielināšana bieži ir nepareizs risinājums. Noderīgie jautājumi ir, kurš limits nostrādāja un kas aizņem vietas.

Ierastā ziņojuma forma:

Code: 202. DB::Exception: Too many simultaneous queries. Maximum: 1000. (TOO_MANY_SIMULTANEOUS_QUERIES)

Seši limiti, viens kļūdas kods

Failā ProcessList.cpp, kur ClickHouse reģistrē katru jaunu vaicājumu, to pašu kļūdas kodu met sešas dažādas pārbaudes. Ziņojuma formulējums pasaka, kuru sasniedzāt:

Too many simultaneous queries. Maximum: N                      -- max_concurrent_queries (server)
Too many simultaneous select queries. Maximum: N, current: M   -- max_concurrent_select_queries
Too many simultaneous insert queries. Maximum: N, current: M   -- max_concurrent_insert_queries
Too many simultaneous queries for all users. Current: M, maximum: N  -- max_concurrent_queries_for_all_users
Too many simultaneous queries for user alice. Current: M, maximum: N -- max_concurrent_queries_for_user
Too many simultaneous waiting queries. Maximum: N, waiting: M        -- max_waiting_queries

Visu augstāk minēto lietotāja līmeņa iestatījumu noklusējums iestatījumu dokumentācijā ir 0 (bez limita).

Noderīgais izņēmums: paskatīties joprojām var

Limiti neattiecas uz visu. ProcessList uzskata KILL QUERY un SELECT, kura pirmā tabula ir system.processes, par neierobežotiem vaicājumiem, tāpat kā iekšējos vaicājumus. Pirmkoda komentārs šo pārbaudi sauc par "ļoti aptuvenu": USE system; SELECT * FROM processes netiek atpazīts, tāpēc vienmēr rakstiet tabulas nosaukumu pilnībā. Tas nozīmē, ka pat tad, kad visas vietas ir aizņemtas, varat redzēt, kas darbojas, un to apturēt:

-- works even when the server is at its limit
SELECT user, query_kind, is_initial_query, count() AS queries,
       round(max(elapsed)) AS longest_s
FROM system.processes
GROUP BY user, query_kind, is_initial_query
ORDER BY queries DESC;

Kolonnas no system.processes, kuras vērts zināt: is_initial_query ir 0 bērnvaicājumiem, ieskaitot tos, kas nosūtīti uz šardiem izkliedētai izpildei; dokumentācija brīdina, ka izkliedētai apstrādei vaicājumi uz attāliem serveriem tiek sūtīti ar default lietotāju, tāpēc user šardā var nebūt tas, kurš vaicājumu sāka; initial_user rāda, kas to izdarīja. Klasterī paneļa vaicājums, kas izplatīts uz vairākiem šardiem, parādās kā darbojošs vaicājums arī katrā serverī, ko tas skar, tāpēc skaitļi šardos var būt lielāki nekā mezglā, ar kuru runā klienti.

Atrodiet garos:

SELECT query_id, user, round(elapsed) AS s,
       formatReadableSize(memory_usage) AS mem, left(query, 120) AS q
FROM system.processes
ORDER BY elapsed DESC
LIMIT 20;

Un nogaliniet to, kam tur nevajadzētu būt:

KILL QUERY WHERE query_id = '6e3c1d8a-...';
KILL QUERY WHERE user = 'bi_dashboard' AND elapsed BETWEEN 300 AND 1e9;

Kas parasti aizpilda vietas

Lai redzētu, kad atteikumi notika un kam, vaicājiet system.query_log. Vaicājumi, kas neizdevās pirms starta, tiek reģistrēti ar tipu ExceptionBeforeStart:

SELECT toStartOfMinute(event_time) AS minute, user, count() AS rejected
FROM system.query_log
WHERE type = 'ExceptionBeforeStart' AND exception_code = 202
  AND event_time BETWEEN now() - INTERVAL 1 DAY AND now()
GROUP BY minute, user
ORDER BY minute DESC, rejected DESC
LIMIT 50;

Pareiza limitu iestatīšana

Servera mēroga limits atrodas servera konfigurācijā, piemēram, failā direktorijā config.d:

# /etc/clickhouse-server/config.d/concurrency.yaml
max_concurrent_queries: 1000
max_concurrent_select_queries: 0   # 0 = no separate limit
max_concurrent_insert_queries: 0

Pašreizējā servera kodā šīs vērtības tiek atkārtoti piemērotas, kad konfigurācija tiek pārlādēta, tāpēc to maiņai restarts nav vajadzīgs. max_concurrent_queries palielināšana ir pieņemama, ja serverim ir brīvs CPU un atmiņa un vaicājumi ir īsi. Ja vietas ir pilnas, jo vaicājumi ir lēni, augstāks limits tikai ļauj vairāk lēniem vaicājumiem cīnīties par to pašu CPU.

Noderīgāks rīks ir mīkstais limits. Pirmkoda komentārs pie max_concurrent_queries_for_all_users apraksta tieši šo pieeju: iestatiet to nedaudz zem stingrā limita noklusējuma profilā un uz 0 (bez limita) administratoriem un kontiem, kas ir būtiski darbībai, piemēram, metriku eksportētājiem. Tad, kad serveris ir pārslogots, vispirms tiek atteikti parastie lietotāji, un jūs joprojām varat pieslēgties un izmeklēt. Zemāk redzamā SQL forma darbojas ar profiliem un lietotājiem, kas pārvaldīti ar SQL; ja jūsu profili definēti users.xml vai users.d, iestatiet tās pašas vērtības tur:

-- atstājiet rezervi: parastie lietotāji apstājas pie 950 vienlaicīgiem vaicājumiem serverī
ALTER SETTINGS PROFILE default SETTINGS max_concurrent_queries_for_all_users = 950;

-- viens trokšņains panelis nevar aizņemt visu
ALTER USER bi_dashboard SETTINGS max_concurrent_queries_for_user = 50;

-- administratorus un metriku eksportētāju mīkstais limits neaptur
ALTER USER dba SETTINGS max_concurrent_queries_for_all_users = 0;

queue_max_wait_ms ir vēl viena iespēja: kad sasniegts servera mēroga limits, vaicājums līdz tik milisekundēm gaida brīvu vietu, nevis uzreiz neizdodas (noklusējums 0, bez gaidīšanas). Īsa gaidīšana izlīdzina pīķus; gara tikai noslēpj problēmu un tur atvērtus klientu savienojumus.

Nelabojiet 202, iestatot visu uz 0. Neierobežots vienlaicīgums nepadara serveri ātrāku. Pēc noteikta punkta vairāk paralēlu vaicājumu nozīmē lielāku atmiņas spiedienu, vairāk konteksta pārslēgšanu un lēnākas atbildes visiem, kas parasti beidzas ar "Memory limit exceeded". Paturiet stingro limitu un ar lietotāja un visu lietotāju limitiem izlemiet, kuru atteikt vispirms.

Kā novērst nākamo reizi

Galvenās atziņas

ClickHouse Vienlaicīgums Veiktspēja Problēmu novēršana
Sadarbība ar mums

ClickHouse zem slodzes atsaka vaicājumus?

Mēs regulējam ClickHouse klasterus reālam vienlaicīgumam: limitus, slodzes un vaicājumus, kas izraisa sastrēgumu. Pastāstiet, ko redzat, un palīdzēsim atrast vājo vietu.

Sazināties Vairāk no emuāra