Categories: Security

MySQL Aklavietės 101

Kartais dirbdami su MySQL galite pamatyti šią keistoką klaidą:

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

Ši klaida praneša apie aklavietę – tai mes bandysime aptarti šiame įraše.

Kas yra Aklavietė?

Aklavietė atsiranda tada, kai nei viena iš skirtingų MySQL užklausų negali įvykti, nes abi iš jų turi po užraktą, reikalingą kitai užklausai. Šis paveiksliukas iliustruoja aklavietę:

Aklavietės Iliustracija

Verta paminėti, kad aklavietės nereikėtų painioti su užraktu – įrašai yra užrakinami tada, kai išteklius bando pasiekti keli procesai tuo pačiu metu, tačiau aklavietė atsiranda tada, kai dvi ar daugiau užklausų laukia kol viena kitos pabaigos.

Aklaviečių Aptikimas

Naudojant InnoDB variklį aklavietės aptinkamos automatiškai – kai aklavietė aptinkama, variklis automatiškai grąžina užklausą į buvusią vietą tam, kad ši nepapultų į aklavietę. Tikslų atšauktų operacijų kiekį yra sunku nustatyti, nes variklis pasirenka operacijas kurios turi būti atšauktos pagal tai, kiek įrašų paveikia INSERT, UPDATE ar DELETE užklausos.

Aklaviečių Pavyzdžiai

Tam, kad sumodeliuotume aklavietės situaciją, panaudosime dvi lenteles su dviejomis sesijomis toje pačioje duomenų bazėje.

Vienoje sesijoje mes paleisime šias užklausas:

START TRANSACTION;
UPDATE `table_1` SET `id` = ID WHERE `id` = 1;

Kitoje sesijoje mes taip pat paleisime panašias užklausas:

START TRANSACTION;
UPDATE `table_2` SET `id` = ID WHERE `id` = 1;

Tada vienu metu paleisime žemiau esančias užklausas. Pirmoje lentelėje paleisime šią užklausą:

UPDATE `table_1` SET `id` = ID WHERE `id` = 1;

Antroje lentelėje paleisime šią užklausą:

UPDATE `table_2` SET `id` = ID WHERE `id` = 1;

Įvykdę šias užklausas MySQL turėtume gauti tokią klaidą:

ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

Kitokį aklavietės pavyzdį galite rasti InnoDB dokumentacijoje.

Ar Aklavietės Pavojingos?

Kai kurie žmonės gali manyti, kad aklavietės yra pavojingos todėl, kad aklavietės gali neigiamai paveikti programos našumą, o tai gali tapti tiesiogine vartotojų skundų priežastimi: vartotojai ir MySQL duomenų bazių administratoriai dėl šios problemos gali kaltinti programuotojus, o programuotojai gali kaltinti duomenų bazių administratorius.

Tačiau aklaviečių neturėtume laikyti pavojingomis – net MySQL dokumentacijoje teigiama, kad aklavietės nėra pavojingos. Atsidūrus aklavietėje operacija gali būti papraščiausiai paleista iš naujo – operacijos paleidimas iš naujo yra vienas iš būdų, padedančių susidoroti su aklavietėmis MySQL ekosistemoje.

Kaip Išvengti Aklaviečių MySQL?

Išvengti MySQL aklaviečių nėra tik duomenų bazių administratorių darbas – gali atsitikti ir taip, kad į šį procesą reiks įsitraukti ir programuotojams. Aklavietės atsiranda tada, kai atsiranda kelios Coffman’o sąlygos – norint išvengti aklaviečių reiktų vengti šių sąlygų. Šias sąlygas sudaro:

  1. Tarpusavio atskirtis: bent viena iš užklausų turi būti atskirta nuo kitų užklausų;
  2. Resursų užklaikymas: viena užklausa turi užlaikyti bent vieną užklausą ir reikalauti papildomų išteklių, kuriuos užlaiko kiti procesai;
  3. Jokių išimčių (laikinų pertraukimų): užklausą gali būti “paleista” tik tos užklausos, kuri jį užlaiko;
  4. Apskritasis laukimas: kiekvienas procesas turi laukti resurso, kurį laiko kitas procesas, kuris laukia, kol bus paleistas pirmasis procesas.

Kitaip tariant, turime kelis variantus. Galime:

  • Padalinti ilgas transakcijas į trumpesnes. Tai darydami galėsime leisti užraktams greičiau atsilaisvinti;
  • Peržiūrėti užklausas, dirbančias su tais pačiais duomenimis – galbūt galite išvengti tų pačių dalykų prašymo tuo pačiu metu?
  • Optimizuoti savo užklausas taip, kad jos prieitų prie mažiau duomenų – gerai optimizuotos užklausos gali baigtis greičiau, ir, savo ruožtu, nesudaryti aklavietės;
  • Padaryti pertrauką prieš iš naujo paleisdami užklausą – aklavietėje esančios užklausos gali baigtis mums belaukiant;
  • Visiškai išjungti aklavietes – MySQL užraktai ir aklavietės yra mechanizmai, kurie mums padeda išlaikyti turimų duomenų nuoseklumą ir jie neturėtų būti apeinami nebent mes norime pakenkti savo duomenims, nors kai kuriuose scenarijuose juos išjungti gali būti prasminga, nes tai padarius paspartintume savo užklausas (kai kur gali būti išvengta užklausų, kurios laukia to paties užrakto “paleidimo”) – MySQL turi parinktį, leidžiančią išjungti aklavietes: aklaviečių aptikimą galima išjungti nustatant kintamąjį innodb_deadlock_detect į OFF. Aklavietes taip pat galima išjungti per komandinę eilutę, tokiu atveju reiktų naudoti --innodb-deadlock-detect komandą. Šios komandos priimtinos reikšmės yra ON ir OFF.

Santrauka

Kaip ir minėta ankščiau, užraktai ir aklavietės yra mechanizmai, skirti užtikrinti mūsų turimų duomenų saugumą – šių mechanizmų išjungimas yra naudingas tik labai retais atvejais. Į aklavietę turėtų būti žiūrima kaip į pagalbininkę, kuri padeda mums padaryti mūsų aplikacijas efektyvesnimėmis. Norėdami užkirsti kelią aklavietėms programuotojai turėti vengti Coffmano sąlygų – jei bent vienos iš šių sąlygų bus išvengta, aklavietės neturėtų būti problema.

Nirium

Recent Posts

Netflix Has Responded to a Massive Data Leak in 2024. Here’s What They Had to Say

In 2024, Netflix has responded to a massive data leak. Here’s what they said.

2 days ago

Now.gg Roblox Users Beware: 900K Roblox Users May Be at Risk

Almost a million Now.gg Roblox accounts have allegedly been leaked on a hacker forum.

2 days ago

How the KYC Crypto Process Looks Like

How does the KYC crypto process look like? Find out with BreachDirectory.

2 days ago

How to Clear Cache on Android?

How to clear cache on Android? Find out with BreachDirectory.

2 days ago

Missed Out on a Deal? Aloha Browser will Come to the Rescue

A Snip feature by Aloha Browser enables you to track discounts on the items you…

2 days ago

Researchers at Cybernews Uncovered a Massive Leak

Researchers at CyberNews have uncovered that a surveillance app WorkComposer may be leaking your data.…

2 days ago