Escaladarea încuietorilor

Un pic de teorie

De regulă, organizarea datelor în SGBD este o ierarhie. De exemplu, "file-> database-> table-> data page-> entry-> câmp în înregistrare". Unele niveluri ale acestei ierarhii pot fi rearanjate sau pur virtual, sau chiar lipsesc cu totul. Totul depinde de caracteristicile unui anumit implementare, și chiar terminologia utilizată, iar în acest caz, este de valoare mică, este important doar ca într-o formă sau alta o astfel de ierarhie este aproape întotdeauna prezentă. SGBD de punere în aplicare mecanismul de blocare ierarhic (blocare multigranularity) pentru a asigura procesarea paralelă a tranzacțiilor, poate impune un sistem de blocare pe obiect la orice nivel al ierarhiei. În acest caz, obiectele corespunzătoare din nivelurile inferioare sunt blocate automat. De exemplu, o blocare exclusivă pe o pagină de date blochează toate intrările incluse în această pagină. Dar, în același timp, desigur, înregistrările pe paginile vecine nu sunt blocate în nici un fel. De obicei, termenul "granularitate" este folosit pentru a indica cantitatea de date care trebuie blocată. O granularitate mai mare înseamnă blocarea obiectului la un nivel superior al ierarhiei și, în consecință, a tuturor obiectelor care îl conțin, cu o mai mică granularitate.







Acum am ajuns la subiect de discuție. Escaladarea încuietorilor este un proces în care o mulțime de încuietori cu o granularitate mică sunt convertite într-o singură încuietoare la un nivel superior de ierarhie cu o mai mare granularitate.

De ce este necesar

Într-adevăr, la prima vedere nu este necesar. mod intuitiv de gândire despre acest lucru: Lock la un nivel mai ridicat al ierarhiei este blocarea site-urilor la un nivel inferior, inclusiv cele care, în general, nu blocați. Și aceasta conduce la o scădere a gradului de concurență a tranzacțiilor și, în cele din urmă, la scăderea productivității. Dar, de fapt, efectul este inversat. Dacă vă săturați ceva mai adânc, se pare că în unele cazuri este mai avantajos să blocați obiectele cu o mai mare granularitate.

În mod tradițional, sunt identificate trei efecte de la impunerea blocărilor, ceea ce face în unele cazuri mai avantajos blocarea la un nivel superior al ierarhiei menționate mai sus.

Blocarea deasupra capului. Nu contează cât de repede sau suprapuse pe și să decoleze și cât de multe ar fi puțin spațiu ocupat nu se blocheze, ar putea veni încă un moment în care mai profitabil să impună un sistem de blocare cu o mai mare granularitate decât câteva (sau câteva mii) mai mici. În ciuda costurilor asociate cu blocarea obiectelor inutile.

Confruntarea datelor. Suprapunerea unei blocări este o acțiune atomică, totuși, suprapunerea mai multor încuietori nu este deja. Între cele două încuietori de suprapunerea într-un server de tranzacție, ghidat de considerente de cea mai mare eficiență, se pot efectua una sau chiar mai multe, alte tranzacții în întregime. Dar dacă prima tranzacție se face relativ lungă și impune multe blocări mici, atunci pot apărea efecte secundare neplăcute. Să presupunem că există o tranzacție lungă T1 care blochează o mulțime de înregistrări. La un moment dat, a început și a început să-și impună încuietori. Până în momentul T1 a reușit să apuca tranzacții de câteva obiecte sunt executate Tx, care, la rândul său, blochează intrările care T1 va fi nevoie de curând, dar pentru a ajunge la ele T1 nu a fost încă. Ca rezultat, T1 este obligat să aștepte până când tranzacția Tx va lucra la el până când ea așteaptă una dintre Tx, aceste tranzacții (înregistrare interesant la care T1 nu a avut timp pentru a ajunge) poate fi chiar mai mult. Astfel, timpul necesar pentru a efectua T1 este semnificativ crescut. Situația este agravată de faptul că, după începerea T1 poate să apară tranzacții Ty care au nevoie de obiectele pe care T1 a reușit să capteze, și ca timpul de execuție T1 crește, crește și timpul de așteptare tranzacție Ty T1 la site-uri blocate.

Sustinerea resurselor. Încuietori, în plus față de ocuparea pur și simplu spațiu, de asemenea, nevoie de o întreținere care consumă resurse de sistem. De exemplu, o verificare periodică a graficului de așteptare tranzacție pentru prezența de blocaj, ocupația este destul de scump. Și cu cât sunt mai multe încuietori, cu atât mai multe resurse sunt cheltuite pentru astfel de verificări. În plus, există pur și simplu o limită a numărului de tranzacții care pot fi efectuate simultan pe sistem fără a sacrifica performanța. La un anumit punct, o mulțime de tranzacții simultane converg în lupta pentru timpul procesorului și alte resurse ale sistemului. Toate acestea conduc din nou la o creștere a timpului de răspuns și la o scădere generală a performanței.

Astfel, impactul acestor trei factori conduce la faptul că, în unele cazuri, atunci când numărul de încuietori în sistem este mare și este destul de lungi tranzacții, în termeni de performanță, este avantajos să se blocheze site-urile cu o mai mare granularitate. Scade numărul total de încuietori reduse tranzacții lungi de rulare și, în consecință, scurt, care trebuie să aștepte mult timp, consumă mai puține resurse de sistem. Figura 1 prezintă planuri de calitate a performanței față de granularitatea blocărilor pentru tranzacții scurte și lungi.








Figura 1. Graficele de performanță din granularitatea blocărilor pentru tranzacțiile scurte și lungi.

Principala problemă este de a determina de la ce punct tranzacția este considerată "suficient de lungă". Din păcate, nu este întotdeauna posibil să determinați strategia de suprapunere a blocării la timpul de compilare, astfel încât uneori trebuie să efectuați dinamică creșterea granularității, chiar în timpul executării interogării.

Aplicare practică

Ca o implementare practică a mecanismului de escaladare a încuieturilor, puteți aduce Microsoft SQL Server. În acest caz, ierarhia obiectelor care ne interesează este după cum urmează: "table-> data page-> record".


Figura 2. Ierarhia obiectelor în MSSQL

În mod implicit, dacă nu interferezi cu logica serverului, acesta încearcă să impună o blocare de scriere, adică o încuietoare care are cea mai mică granularitate. Dar dacă serverul decide că blocarea la nivelul unei înregistrări individuale nu este cea mai optimă soluție, atunci va bloca un volum mai mare. Cu toate acestea, puteți specifica în mod explicit cu ce granularitate doriți să blocați, folosind sugestii speciale pentru optimizator (sugestii).

  • ROWLOCK - blocare la nivel de scriere.
  • PGLOCK - blocarea la nivelul paginii de date.
  • TABLOCK - blocare la nivelul mesei.

Dacă indicele sunt construite în tabel, atunci puteți face fără o indicație explicită a granularității interogării. Folosind o procedură stocată în sistem special, sp_indexoption, puteți specifica granularitatea blocării indexului. Astfel, toate eșantioanele din tabelul din acest index vor merge la nivelul ierarhic specificat fără instrucțiuni explicite.

Pentru interogări care nu utilizează indexuri, setările sp_indxoption nu funcționează. Dar dacă tabela are un indice de cluster, iar în acest caz, paginile de date fac parte din indicele, granularitatea este specificat pentru un indice de cluster, va fi folosit pentru interogări care se execută fără indicii.

Dar, în general, toate aceste setări de granularitate funcționează doar într-o singură direcție. Puteți să cereți serverului să blocheze numai la nivelul de scriere, dar dacă pare să fie prea mic în timpul executării interogării, acesta va escalada în continuare blocarea. Dar dacă specificați că doriți o blocare la nivel de pagină, apoi la nivel de înregistrare, blocarea nu va fi niciodată, ci numai la nivelul paginii sau al mesei. Dacă solicitați o blocare de tabelă specificând acest lucru în mod explicit sau prin intermediul setărilor indexului, atunci întregul tabel va fi întotdeauna blocat și niciodată o singură intrare sau pagină.

După cum sa menționat deja, serverul poate crește granularitatea de blocare direct în timpul executării cererii, cu escaladarea se întâmplă întotdeauna la nivelul mesei, chiar și în cazul în care înregistrările individuale de blocare înainte. SQL Server determină necesitatea unei escaladări din următoarele motive: În cazul în care numărul de blocări a impus o singură tranzacție depășește 1250 sau numărul de încuietori pe un singur index sau mai mare de 765, iar în cazul în care mai mult de patruzeci la sută din memoria disponibilă la server este utilizat pentru blocarea, atunci serverul selectează masa cea mai potrivită și încearcă să escaladeze încuietori la un nivel de masă. În caz de eșec, în cazul în care unele dintre intrările din tabel sunt impuse incompatibile blocarea altor tranzacții, serverul nu așteptați, și continuă să funcționeze la același nivel de granularitate la următoarea încercare. Astfel, posibilitatea blocării este eliminată direct prin eroarea de escaladare.

Nu este greu de observat că, datorită escaladării blocărilor, nu puteți fi sigur niciodată cu ce granularitate serverul va bloca obiecte. De aceea, nu trebuie să te bazezi niciodată pe asta.

Deși există două modalități de a interzice escaladarea:

Prima cale, "aproape hacker". Dacă vrem ca niciodată să nu apară escaladarea blocărilor de pe o anumită masă, atunci trebuie să executăm următoarea interogare într-o tranzacție separată, dar trebuie să finalizăm această tranzacție împreună cu închiderea aplicației.

Astfel, la prima vedere, o interogare fără sens, va cauza impunerea clapetei IX pe masă. Această încuietoare nu este compatibilă nici cu S, nici cu U, nici mai ales cu încuietori X. Astfel, din cauza incapacității de a impune o blocare pe masă, escaladarea nu va trece la ea. Cu toate acestea, alte cereri, cu interconexiuni mai puțin detaliate, vor fi, în general, fără probleme. Singurul efect secundar este acela că va fi imposibil chiar să impui în mod explicit o blocare pe toată masa.

A doua cale, "oficial". De asemenea, este posibil, fără a utiliza un workarounds complicat dezactiva escaladarea, în general, nici măcar într-o bază de date separată, și în întregime într-o singură instanță (instanță) SQL Server“. În acest scop, există o urmă de pavilion de construcții - 1211. Punerea în aplicare a comenzii DBCC TRACEON (1211), să interzică escaladarea într-o instanță separată a unui bun timp, până la următoarea comandă DBCC TRACEOFF (1211).

Dar, în ciuda posibilității, folosind metode semi-legale și destul de documentate, de a interzice escaladarea încuietorilor, nu aș recomanda acest lucru. Escaladarea este un mecanism de server intern bine stabilit, care ajută la obținerea performanțelor maxime chiar și sub sarcină mare. Și nu vă recomandăm să vă urcați în acest mecanism cu mâinile fără necesități extreme.

Puteți încerca, de asemenea, să rupă o tranzacție lungă în multe mici, care, în general, este întotdeauna util, chiar dacă nu iau în considerare escaladarea, la fel ca în cele mai multe cazuri, este doar în beneficiul serverului. Și, în general, cu cele mai bine tranzacționate tranzacții și solicitări, cu atât mai puțin riscul de escaladare a încuietorilor. Dar, din nou, nu pot fi niciodată sigur că o escaladare nu se va întâmpla. Pe de altă parte, de regulă, escaladarea de blocare este un clopot de avertizare că aplicația are o strangulare, și ar fi frumos să rescrie optimă.

În cazul în care pentru orice caz trebuie să fie sigur că va fi blocat de un singur obiect sau este necesar pentru a bloca obiectele abstracte, cum ar fi „document“ care există pentru această blocare utilizator, care se poate lucra cu un cuplu de proceduri memorate de sistem, sp_getapplock și sp_releaseapplock. Cu aceste proceduri, serverul permite aplicațiilor de la terțe părți să utilizeze managerul de blocare a serverului pentru nevoile acestora. Implementarea aceluiași mecanism de blocare - ocupat și supărător, datorită escaladării, puțin promițătoare.

Link-uri utile

Literatura utilizată

[1] Controlul și recuperarea concurentă în sistemele de baze de date. Philip A. Bernstein, Vassos Hadzilacos, Nathan Goodman.







Articole similare

Trimiteți-le prietenilor: