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
max_concurrent_queriesir servera mēroga stingrais limits, ko iestata servera konfigurācijā. Iebūvētais noklusējums failā ServerSettings.cpp ir 0 (bez limita), bet kopā ar serveri piegādātais config.xml to iestata uz 1000. Tāpēc "Maximum: 1000" ir skaitlis, ko redz lielākā daļa.max_concurrent_select_queriesunmax_concurrent_insert_queriesir atsevišķi servera līmeņa ierobežojumi katram vaicājumu veidam. Abu noklusējums ir 0, t.i., atsevišķa limita nav.max_concurrent_queries_for_all_usersir lietotāja līmeņa iestatījums, ko salīdzina ar kopējo servera darbojošos vaicājumu skaitu. Tas ir mīkstais limits, kas var atšķirties katram profilam vai lietotājam.max_concurrent_queries_for_userierobežo viena lietotāja vaicājumus.max_waiting_queriesatšķiras no pārējiem: tas ierobežo vaicājumus, kas gaida asinhronu starta darbu, piemēram, tabulu, kas pēc restarta vēl ielādējas. Ja "waiting queries" redzat uzreiz pēc restarta, serveris vēl startē; tā nav slodzes problēma.
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
- Lēni vaicājumi, kas krājas. Ja vaicājums, kas parasti aizņem 200 ms, pēkšņi aizņem 20 sekundes, tam pašam pieprasījumu tempam vajag simtreiz vairāk vietu. Vienlaicīguma limits ir vieta, kur to pamanāt; cēlonis ir tas, kas padarīja vaicājumus lēnus: smaga atskaite, apvienošanu vētra, atmiņas spiediens. Mūsu raksts par "Memory limit exceeded" ClickHouse vidē aplūko atmiņas pusi.
- Klienti, kas padodas, bet atstāj vaicājumus darbojamies. BI rīks vai HTTP klients pēc 30 sekundēm pārtrauc gaidīšanu un mēģina vēlreiz, kamēr sākotnējais vaicājums serverī turpina darboties. Iestatījums
cancel_http_readonly_queries_on_client_closeatceļ tikai lasīšanas HTTP vaicājumus, kad klients atvienojas; pēc noklusējuma tas irfalse(dokumentācija norāda, ka Cloud noklusējums ir 1). Apvienojiet to ar reālistiskumax_execution_timepaneļu lietotājiem; pēc noklusējuma tas ir 0, bez limita. - Daudz sīku ievietojumu. Katrs
INSERTir vaicājums. Tūkstošiem vienas rindas ievietojumu sekundē apēd vietas un, vēl ļaunāk, rada daļas (parts); skatiet mūsu ceļvedi par "Too many parts", lai uzzinātu par grupēšanu un asinhroniem ievietojumiem. - Izplatīšana klasterī. Izkliedēti vaicājumi atver bērnvaicājumus šardos, tāpēc neliels klientu vaicājumu skaits katrā mezglā var izskatīties pēc daudz lielāka.
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.
Kā novērst nākamo reizi
- Monitorējiet darbojošos vaicājumu skaitu (metrika
Querytabulāsystem.metrics) pret savu limitu un iestatiet brīdinājumu krietni pirms tā sasniegšanas. - Skaitiet kodu 202 tabulā
query_logkatram lietotājam. Daži gadījumi dienā pīķu laikā ir signāls; nepārtraukta plūsma nozīmē, ka limitiem vai slodzei vajag uzmanību. - Piešķiriet katram klientu veidam savu lietotāju ar saviem limitiem un
max_execution_time, lai viens panelis nevarētu nonāvēt datu ielādi vai citus servisus. - Salabojiet lēnos vaicājumus. Vienlaicīguma problēmas ClickHouse vidē parasti ir pārģērbtas latentuma problēmas.
Galvenās atziņas
- Kļūda 202 nāk no sešiem dažādiem limitiem; ziņojuma formulējums pasaka, no kura.
- "Maximum: 1000" ir
max_concurrent_queriesvērtība no noklusējuma config.xml; iebūvētais noklusējums ir bez limita. SELECT ... FROM system.processesunKILL QUERYapiet limitus, tāpēc vienmēr varat paskatīties un satīrīt.- Izmantojiet
max_concurrent_queries_for_all_usersnedaudz zem stingrā limita, ar 0 administratoriem, lai saglabātu rezervi. - Lielākā daļa sastrēgumu ir lēni vaicājumi vai pamesti klientu pieprasījumi; tikai limita palielināšana reti palīdz.