Incidentu reaģēšana

"MySQL server has gone away" (kļūda 2006): cēloņi un labojumi, kas tiešām strādā

Kļūda 2006 ir simptoms, nevis diagnoze. Savienojumu aizvēra serveris, tīkls, starpniekserveris vai jūsu pašu kods, un katram gadījumam vajag citu labojumu. Lūk, kā saprast, kurš tas ir, pirms sākat palielināt taimautus.

· 15 min lasīšanai · AG Data komanda

"MySQL server has gone away" ir klienta kļūda 2006. Tā nozīmē, ka klients mēģināja izmantot savienojumu, kas vairs nedarbojas. Kļūda neko nepasaka par to, kāpēc savienojuma vairs nav. MySQL dokumentācijā uzskaitīti vairāk nekā desmit iespējamie cēloņi, sākot ar dīkstāves taimautu un beidzot ar servera avāriju, un viena cēloņa labojums otram neder. Tāpēc pirmais uzdevums nav mainīt iestatījumu, bet noskaidrot, kas savienojumu aizvēra.

2006, 2013 un 4031: vienas problēmas trīs sejas

ERROR 2006 (HY000): MySQL server has gone away
ERROR 2013 (HY000): Lost connection to MySQL server during query
ERROR 4031 (HY000): The client was disconnected by the server because of inactivity.
                    See wait_timeout and interactive_timeout for configuring this behavior.

Ja redzat 4031, lielāko daļu šī raksta varat izlaist: savienojums bija pārāk ilgi dīkstāvē. Ja redzat 2006 vai 2013, lasiet tālāk.

1. solis: savāciet četrus faktus

Pirms kaut ko maināt, izpildiet serverī:

SHOW GLOBAL VARIABLES WHERE Variable_name IN
  ('wait_timeout', 'interactive_timeout', 'max_allowed_packet',
   'net_read_timeout', 'net_write_timeout', 'connect_timeout');

SHOW GLOBAL STATUS WHERE Variable_name IN
  ('Uptime', 'Aborted_clients', 'Aborted_connects');

Pēc tam atbildiet uz četriem jautājumiem:

  1. Vai serveris restartējās? Salīdziniet Uptime ar kļūdu laiku. Dokumentācija iesaka tieši šo pārbaudi: ja savienojums pārtrūka, jo mysqld avarēja un restartējās, kļūda ir mazākā problēma, un jāizmeklē avārija. Pārbaudiet kļūdu žurnālu.
  2. Cik ilgi savienojums bija dīkstāvē? Ja neveiksmīgais pieprasījums ir pirmais pēc klusa perioda (nakts darbi, process, kas pamostas reizi stundā, savienojumu pūls pēc nedēļas nogales) un pārtraukums ir garāks par sesijas wait_timeout, cēlonis atrasts.
  3. Cik liels bija pieprasījums? Milzīgs INSERT, liels BLOB vai garš ģenerēts vaicājums norāda uz max_allowed_packet.
  4. Vai kāds vai kas sesiju pārtrauca? DBA izpildīts KILL, monitoringa skripts, kas pārtrauc ilgus vaicājumus, vai pārslēgšanās rīks no klienta puses izskatās vienādi.

Dokumentācija arī iesaka palaist mysqld ar log_error_verbosity vērtību 3, lai kļūdu žurnālā tiktu ierakstīti daži atvienošanās ziņojumi. Tas palīdz, ja klienta puse neko nepasaka.

1. cēlonis: savienojums bija dīkstāvē ilgāk par wait_timeout

Šo cēloni dokumentācija sauc par biežāko. Pēc noklusējuma serveris aizver savienojumu pēc astoņām stundām bez aktivitātes: wait_timeout un interactive_timeout noklusējuma vērtība abiem ir 28800 sekundes.

To mijiedarbībā ir slazds. Saskaņā ar servera mainīgo aprakstu, kad sesija sākas, tās wait_timeout tiek inicializēts no globālā wait_timeout vai no globālā interactive_timeout atkarībā no tā, vai klients pieslēdzās ar opciju CLIENT_INTERACTIVE. Tāpēc, mainot tikai vienu no abiem globālajiem mainīgajiem, jums svarīgie savienojumi var netikt ietekmēti. Pārbaudiet, ko sesija patiešām saņēma:

-- ko saņēma TIEŠI ŠĪ sesija (var atšķirties no globālās vērtības)
SELECT @@SESSION.wait_timeout, @@GLOBAL.wait_timeout, @@GLOBAL.interactive_timeout;

Komandas, kas samazināja wait_timeout, lai iztīrītu dīkstāves savienojumus (to apsvērt iesaka mūsu raksts par "Too many connections"), dažreiz aizmirst par lietotnes pusi. Ja savienojumu pūls tur savienojumus ilgāk nekā serveris, pūls agri vai vēlu izsniegs mirušu savienojumu.

Labojums pieder lietotnei, nevis lielākam taimautam:

Neaizmirstiet, kas atrodas starp lietotni un MySQL. Slodzes balansētājiem, starpniekserveriem, NAT vārtejām un ugunsmūriem var būt savi dīkstāves taimauti, un tie var klusi pārtraukt TCP savienojumus, ko MySQL joprojām uzskata par atvērtiem. Ja wait_timeout ir astoņas stundas, bet savienojumi mirst pēc dažām klusuma minūtēm, skatieties tīkla ceļu.

2. cēlonis: pakete bija pārāk liela

No lapas "Packet Too Large": kad MySQL klients vai mysqld serveris saņem paketi, kas lielāka par max_allowed_packet baitiem, tas izdod kļūdu ER_NET_PACKET_TOO_LARGE (1153, "Got a packet bigger than 'max_allowed_packet' bytes") un aizver savienojumu. Daži klienti parāda tikai aizvērto savienojumu, tāpēc tas bieži izskatās kā 2006 vai 2013.

Galvenie skaitļi no dokumentācijas:

Abām pusēm ir savs mainīgais, tāpēc lielam importam iestatījums var būt jāpalielina gan klientā, gan serverī:

[mysqld]
max_allowed_packet = 128M

# un klienta pusē, piemēram:
# mysql --max_allowed_packet=128M

Pirms palielināt, pārbaudiet, vai tas ir vajadzīgs. Dokumentācijā norādīts, ka INSERT vai REPLACE ar ļoti daudzām rindām tiek nosūtīts kā viens pieprasījums, un kļūdu bieži var novērst, sūtot mazāk rindu vienā vaicājumā. Mazākas partijas parasti ir vieglākas serverim, replikācijai un jūsu atkārtošanas loģikai nekā viens milzīgs vaicājums.

3. cēlonis: vaicājums vai rezultāts tīklā aizņēma pārāk ilgu laiku

Lapa par zaudētu savienojumu aplūko 2013 variantu. Ja ziņojumā ir "during query", dokumentācija saka, ka visticamākais cēlonis ir tīkla problēmas. Tajā aprakstīts arī gadījums, kad tiek sūtīti miljoniem rindu, un ieteikts palielināt net_read_timeout no noklusējuma 30 sekundēm līdz 60 sekundēm vai vairāk. Tā radniecīgais mainīgais net_write_timeout pēc noklusējuma ir 60 sekundes un nosaka, cik ilgi serveris gaida, rakstot klientam. Klients, kas lielu rezultātu kopu lasa lēni, piemēram, apstrādā katru rindu pirms nākamās ielādes, var tam uzdurties.

Svarīgi ir arī klienta puses taimauti. Dokumentācijā minētas C API lasīšanas un rakstīšanas taimauta opcijas; vairumam draiveru ir līdzvērtīgas. Ja draiveris padodas pēc 30 sekundēm vaicājumam, kas ilgst 40, rezultāts izskatās pēc zaudēta savienojuma, lai gan serveris ir kārtībā.

Kļūdām pieslēgšanās brīdī dokumentācija norāda uz connect_timeout (noklusējums 10 sekundes) un statusa skaitītāju Aborted_connects, kas palielinās par vienu katram sākotnējam pieslēgšanās mēģinājumam, ko serveris pārtrauc. "reading authorization packet" ziņojumā ir mājiens šajā virzienā.

4. cēlonis: sesija tika pārtraukta vai serveris nokrita

Dokumentācijā kā cēlonis minēts KILL vaicājums vai mysqladmin kill. Praksē tas ietver rīkus, kas automātiski pārtrauc ilgus vaicājumus; to ir vērts pārbaudīt, ja kļūdas koncentrējas ap smagām atskaitēm. Mūsu rakstā par lock wait timeout parādīts, kā atrast bloķējošās sesijas, kas ir biežs iemesls, kāpēc kāds vispār ķeras pie KILL.

Servera avārija, OOM pārtraukšana vai pārslēgšanās uz repliku arī izbeidz visus savienojumus. Ja Uptime ir īss, sāciet ar kļūdu žurnālu un sistēmas žurnālu, nevis ar klientu.

5. cēlonis: kļūdas lietotnes savienojumu apstrādē

Divi cēloņi no dokumentācijas nāk tieši no lietotnes koda:

Uzmanieties ar automātisko atkārtoto pieslēgšanos. C API dokumentācijā teikts, ka auto-reconnect pēc noklusējuma ir izslēgts un funkcija ir novecojusi. Kad atkārtota pieslēgšanās notiek, servera puses sesijas stāvoklis tiek atiestatīts, un lietotne netiek informēta: aktīvās transakcijas tiek atritinātas, tabulu slēdzenes un GET_LOCK() slēdzenes atbrīvotas, pagaidu tabulas dzēstas, sesijas un lietotāja mainīgie zaudēti, un LAST_INSERT_ID() atiestatās uz 0. Kods, kas transakcijas vidū klusi pieslēdzas no jauna, var turpināt darbu tā, it kā puse tā darba nebūtu tikko izmesta. Pieslēdzieties no jauna un pēc tam sāciet visu darba vienību no sākuma.

Izmantojiet Aborted_clients kā agru brīdinājumu

Lapā par komunikācijas kļūdām paskaidrots, ka, ja klients veiksmīgi pieslēdzas, bet vēlāk atvienojas nepareizi vai tiek pārtraukts, serveris palielina Aborted_clients un ieraksta žurnālā ziņojumu "Aborted connection". Cēloņi ir klients, kas beidz darbu, neaizverot savienojumu, klients, kas guļ ilgāk par wait_timeout vai interactive_timeout, klients, kas beidz darbu datu pārsūtīšanas vidū, pārāk mazs max_allowed_packet un bojāta tīkla aparatūra. Attēlojiet skaitītāju grafikā. Vienmērīga plūsma daudzām lietotnēm ir normāla; pēkšņs pieaugums pēc izlaidiena vai tīkla izmaiņām pasaka, kur meklēt, pirms lietotāji sāk ziņot par kļūdām.

Galvenās atziņas

MySQL Savienojumi Taimauti Problēmu novēršana
Sadarbība ar mums

Produkcijā pārtrūkst savienojumi?

Mēs izsekojam pārtrūkušos MySQL savienojumus līdz serverim, tīklam vai lietotnei un novēršam cēloni, nevis tikai palielinām taimautus.

Sazināties Vairāk no emuāra