INSERT DELAYED
Šodien, pateicoties tam, ka viens no XML-RPC servisiem sāka mums gāzt nenormālu kaudzi pieprasījumu (kaut ko līdzīgu piegādes atskaitēm), webserveris līka ciet. Gan jau ka kāds pamanīja.
Sāku ar bēdāšanos un nervozu pīpēšanu. Man tas palīdz ģenerēt idejas - pīpēšana, vai jebkura cita darbība, kura nav saistīta ar piedomāšanu. Tas vēl nav viss. Šīs darbības laikā es galvā imitēju sarunu par šo problēmu. Vai arī provēju vienkārši pa punktiem izklāstīt problēmu, iedomājoties, ka to daru cilvēkam, kurš ir mazāk kvalificēts (nav IT zinātājs). Palīdz.
Bet ne par to stāsts, kā viegli nojaust pēc ieraksta nosaukuma. Tad, lūk. Manā galā apstrādes skripts ievieto saņemto atskaiti tabulā. Šobrīd attiecīgā MySQL tabula satur 12 398 374 ierakstus. Sakarā ar to, ka no šī lēruma informācijas ir nepieciešamas šādas tādas atskaites, lai procesu vienkāršotu, tabulai tika izveidoti lērums ar indeksiem. Tai laikā ierakstu skaits bija daždesmit tūkstoši. Arī pie dažiem miljoniem viss strādāja un slikti nevienam nebija.
Un tad nāca vakardiena. Nekādi nespēju saprast, aiz kam web serveris liecas ciet. Ja līdz šim noslodze bija minimāla, tad tagad momentāni tiek paķerti visi apache procesi, tiek izveidotas milzums konekcijas uz DB serveri un nekas nenotiek.
Izrādās, ka beidzot MySQLs ir sapratis, ka nu ir grūti atjaunot indeksus tādam milzumam datu. Un uz katru INSERT
patērēja gana lielu laika sprīdi. Ja līdz šim tā pussekunde nebija pamanāms lielums, tad tagad šī aizkavēšanās maksāja pastarpināto serveru resursus. DB serveris sevišķi nespringa, bet webserveris gan. Sen nebiju redzējis noslodzes vidējās vērtības aizejam otrajā simtā...
Tā kā situācija prasīja momentānu risinājumu, sāku cīņu. Provēju ar trafika ierobežošanu (mod_bandwidth, piemēram). Nekas labs no tā neiznāca. Tad vienkārši nogriezu (izņemot no atļautajiem hostiem attiecīgo IP), līdz izdomāšu, kā problēmu risināt (otrā galā pieprasījumi tā vai tā krājas rindā).
Un tad nāca apskaidrība. Atminējos par INSERT DELAYED
. Tas bija tieši tas, kas man nepieciešams. Sakarā ar to, ka DB serveris nekādas satraukuma pazīmes neizrādīja, bet WEB serveris nespēja celt tādu vienlaicīgu un relatīvi ilgstošu savienojumu skaitu, šis ir ideāls risinājums.
INSERT DELAYED
dara vienkāršu lietu - visus ar šo komandu izsauktos insertus krāj rindā un, atkarībā no konfigurācijas, ik pa laikam sastumj datubāzē. Labums - komandas izsaucējam nav jāgaida, kamēr reāli tā izpildīsies (tas ir labi tikai tai gadījumā, kad nav nepieciešamas nekādas post factum pārbaudes). Bet lielākais ieguvums - ātrdarbība. Tiek izveidots atsevišķs process, kurš nodarbojas ar to, ka pako, gaida un izpilda šos pieprasījumus. Process tos ievieto pa paciņām, t.i. - sakrājot konkrētu skaitu, ievieto tos datubāzē vienā rāvienā, kas ir stipri ātrāk, nekā, ja to dara pa vienam un nodažādām konekcijām. Kā arī, ja tabula tiek biežo lokota, tad ievietojošajam klientam nav jāgaida, līdz loks atbrīvosies.
P.S. Atgādiniet man kaut kad uzrakstīt par LIKE
versus INSTR
, INSERT INTO table SET ...
, CONVERT
ļaunumu, NULL
superļaunumu, kā arī citiem sīkumiem.
Krišs
2006. gada 28. decembrī, plkst. 09:52
Ierakstu skaits nav saistīts ar RAM izmēriem? Atceros, ka watt kaut kad minēja, ka cibas serveri sāk bremzēt brīdī, kad db vairs nesalien ram-ā
laacz Autors
2006. gada 28. decembrī, plkst. 09:54
Kriš, viss ir saistīts ij ar RAM apjomu, ij ar disku ātrumu, ij ar procesoru. Bet nebija pamata tādam pēkšņam lēcienam.
e-remit
2006. gada 28. decembrī, plkst. 12:18
par "NULL superļaunumu" - tas uz MySQL tiešām ir ļoti liels ļaunums, jo MySQListi uzskata par normālu (un pat foršu), kad NOT NULL tabulā var ievietot NULL vērtības... Patiesībā no MySQL nosaukuma vajadzētu izņemt "SQL", un pārsaukt to par kaut kādu MyWebDb.
Gonzalez
2006. gada 30. decembrī, plkst. 16:33
NULL nav veertiiba, NULL ir staavoklis.
Kāds
2007. gada 1. janvārī, plkst. 14:40
Muļķīgs posts, imho.