Otključavanje Postgres Lock Managera. Bruce Momjian

Transkript govora Brucea Momjiana iz 2020. "Otključavanje Postgres Lock Managera".

Otključavanje Postgres Lock Managera. Bruce Momjian

(Napomena: Svi SQL upiti sa slajdova mogu se dobiti na ovoj poveznici: http://momjian.us/main/writings/pgsql/locking.sql)

Zdravo! Sjajno je ponovno biti ovdje u Rusiji. Žao mi je što prošle godine nisam mogao doći, ali ove godine Ivan i ja imamo velike planove. Nadam se da ću biti ovdje mnogo češće. Volim dolaziti u Rusiju. Posjetit ću Tyumen, Tver. Jako mi je drago što ću moći posjetiti ove gradove.

Moje ime je Bruce Momjian. Radim u EnterpriseDB-u i radim s Postgresom više od 23 godine. Živim u Philadelphiji, SAD. Putujem oko 90 dana godišnje. I sudjelujem na 40-ak konferencija. Moj Web stranica, koji sadrži slajdove koje ću vam sada pokazati. Stoga ih nakon konferencije možete preuzeti s moje osobne web stranice. Također sadrži oko 30 prezentacija. Tu su i video zapisi i velik broj unosa u blogove, više od 500. Ovo je prilično informativan izvor. A ako ste zainteresirani za ovaj materijal, onda vas pozivam da ga koristite.

Prije nego što sam počeo raditi s Postgresom, bio sam učitelj, profesor. I jako mi je drago što ću vam sada moći reći ovo što ću vam reći. Ovo je jedna od mojih najzanimljivijih prezentacija. A ova prezentacija sadrži 110 slajdova. Počet ćemo pričati s jednostavnim stvarima, a do kraja će izvješće postajati sve složenije i postat će prilično složeno.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovo je prilično neugodan razgovor. Blokiranje nije najpopularnija tema. Želimo da ovo negdje nestane. To je kao da idete zubaru.

Otključavanje Postgres Lock Managera. Bruce Momjian

  1. Zaključavanje je problem za mnoge ljude koji rade u bazama podataka i imaju više procesa koji se izvode u isto vrijeme. Treba im blokada. Odnosno, danas ću vam dati osnovna znanja o blokiranju.
  2. ID-ovi transakcija. Ovo je prilično dosadan dio prezentacije, ali ih treba razumjeti.
  3. Zatim ćemo govoriti o vrstama blokiranja. Ovo je prilično mehanički dio.
  4. U nastavku ćemo dati neke primjere blokiranja. I bit će to prilično teško razumjeti.

Otključavanje Postgres Lock Managera. Bruce Momjian

Razgovarajmo o blokiranju.

Otključavanje Postgres Lock Managera. Bruce Momjian

Naša je terminologija prilično složena. Koliko vas zna odakle dolazi ovaj odlomak? Dvoje ljudi. Ovo je iz igre koja se zove Colossal Cave Adventure. Bila je to računalna igra temeljena na tekstu 80-ih, mislim. Tamo je trebalo ući u pećinu, u labirint, i tekst se mijenjao, ali sadržaj je svaki put bio približno isti. Tako se sjećam ove utakmice.

Otključavanje Postgres Lock Managera. Bruce Momjian

I ovdje vidimo ime brava koje su nam stigle iz Oraclea. Koristimo ih.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovdje vidimo pojmove koji me zbunjuju. Na primjer, SHARE UPDATE ECXLUSIVE. Sljedeći PODIJELI RAW ECXLUSIVE. Da budem iskren, ova imena nisu baš jasna. Pokušat ćemo ih detaljnije razmotriti. Neki sadrže riječ "dijeliti", što znači odvojiti. Neki sadrže riječ "ekskluzivno". Neki sadrže obje ove riječi. Želio bih započeti s tim kako ove brave rade.

Otključavanje Postgres Lock Managera. Bruce Momjian

I riječ "pristup" također je vrlo važna. A riječi "red" su niz. Odnosno, distribucija pristupa, distribucija redova.

Otključavanje Postgres Lock Managera. Bruce Momjian

Još jedan problem koji treba razumjeti u Postgresu, a koji nažalost neću moći pokriti u svom govoru, je MVCC. Imam zasebnu prezentaciju na ovu temu na svojoj web stranici. A ako mislite da je ova prezentacija teška, MVCC mi je vjerojatno najteža. A ako ste zainteresirani, možete ga pogledati na web stranici. Možete pogledati video.

Otključavanje Postgres Lock Managera. Bruce Momjian

Još jedna stvar koju moramo razumjeti su ID-ovi transakcija. Mnoge transakcije ne mogu funkcionirati bez jedinstvenih identifikatora. A ovdje imamo objašnjenje što je transakcija. Postgres ima dva sustava numeriranja transakcija. Znam da ovo nije baš lijepo rješenje.

Otključavanje Postgres Lock Managera. Bruce Momjian

Također imajte na umu da će slajdove biti prilično teško razumjeti, pa morate obratiti pozornost na ono što je označeno crvenom bojom.

Otključavanje Postgres Lock Managera. Bruce Momjian

http://momjian.us/main/writings/pgsql/locking.sql

Da vidimo. Broj transakcije označen je crvenom bojom. Ovdje je prikazana funkcija SELECT pg_back. Vraća moju transakciju i ID transakcije.

Još jedna stvar, ako vam se sviđa ova prezentacija i želite je pokrenuti u svojoj bazi podataka, onda možete otići na ovaj link u ružičastoj boji i preuzeti SQL za ovu prezentaciju. Možete ga jednostavno pokrenuti u svom PSQL-u i cijela prezentacija će se odmah pojaviti na vašem ekranu. Neće sadržavati cvijeće, ali ga barem možemo vidjeti.

Otključavanje Postgres Lock Managera. Bruce Momjian

U ovom slučaju vidimo ID transakcije. Ovo je broj koji smo joj dodijelili. Postoji još jedna vrsta ID-a transakcije u Postgresu, koja se zove ID virtualne transakcije

I ovo moramo razumjeti. Ovo je vrlo važno, inače nećemo moći razumjeti zaključavanje u Postgresu.

ID virtualne transakcije je ID transakcije koji ne sadrži trajne vrijednosti. Na primjer, ako pokrenem naredbu SELECT, onda najvjerojatnije neću promijeniti bazu podataka, neću ništa zaključati. Dakle, kada izvodimo jednostavan SELECT, toj transakciji ne dajemo trajni ID. Tamo joj dajemo samo virtualnu iskaznicu.

A ovo poboljšava performanse Postgresa, poboljšava mogućnosti čišćenja, tako da se ID virtualne transakcije sastoji od dva broja. Prvi broj prije kose crte je ID pozadine. A s desne strane vidimo samo brojač.

Otključavanje Postgres Lock Managera. Bruce Momjian

Stoga, ako pokrenem zahtjev, on kaže da je ID pozadine 2.

Otključavanje Postgres Lock Managera. Bruce Momjian

I ako pokrenem niz takvih transakcija, tada vidimo da se brojač povećava svaki put kada pokrenem upit. Na primjer, kada pokrenem upit 2/10, 2/11, 2/12 itd.

Otključavanje Postgres Lock Managera. Bruce Momjian

Imajte na umu da ovdje postoje dva stupca. S lijeve strane vidimo ID virtualne transakcije – 2/12. A s desne strane imamo stalni ID transakcije. I ovo polje je prazno. I ova transakcija ne mijenja bazu podataka. Stoga mu ne dajem trajni ID transakcije.

Otključavanje Postgres Lock Managera. Bruce Momjian

Čim pokrenem naredbu za analizu ((ANALYZE)), isti upit daje mi stalni ID transakcije. Pogledajte kako se ovo promijenilo za nas. Prije nisam imao ovu iskaznicu, ali sada je imam.

Otključavanje Postgres Lock Managera. Bruce Momjian

Evo još jednog zahtjeva, još jedne transakcije. Virtualni transakcijski broj je 2/13. A ako tražim trajni ID transakcije, dobit ću ga kada pokrenem upit.

Otključavanje Postgres Lock Managera. Bruce Momjian

Dakle, još jednom. Imamo ID virtualne transakcije i trajni ID transakcije. Samo shvatite ovu točku da biste razumjeli ponašanje Postgresa.

Otključavanje Postgres Lock Managera. Bruce Momjian

Prelazimo na treći dio. Ovdje ćemo jednostavno proći kroz različite vrste brava u Postgresu. Nije baš zanimljivo. Posljednji dio bit će puno zanimljiviji. Ali moramo uzeti u obzir osnovne stvari, jer inače nećemo razumjeti što će se sljedeće dogoditi.

Proći ćemo kroz ovaj odjeljak, pogledat ćemo svaku vrstu brave. I pokazat ću vam primjere kako su instalirani, kako rade, pokazat ću vam neke upite koje možete koristiti da vidite kako funkcionira zaključavanje u Postgresu.

Otključavanje Postgres Lock Managera. Bruce Momjian

Da bismo stvorili upit i vidjeli što se događa u Postgresu, moramo postaviti upit u prikazu sustava. U ovom slučaju, pg_lock je označen crvenom bojom. Pg_lock je tablica sustava koja nam govori koje se brave trenutno koriste u Postgresu.

Međutim, vrlo mi je teško pokazati vam pg_lock samog jer je prilično složen. Pa sam stvorio pogled koji prikazuje pg_locks. I također radi nešto za mene što mi omogućuje bolje razumijevanje. To jest, isključuje moja zaključavanja, moju vlastitu sesiju, itd. To je samo standardni SQL i omogućuje vam da vam bolje pokažete što se događa.

Otključavanje Postgres Lock Managera. Bruce Momjian

Još jedan problem je što je ovaj pogled vrlo širok, pa moram stvoriti drugi - lockview2.

Otključavanje Postgres Lock Managera. Bruce Momjian I pokazuje mi više stupaca iz tablice. I još jedan koji mi pokazuje ostale stupce. Ovo je prilično složeno, pa sam pokušao to prikazati što jednostavnije.

Otključavanje Postgres Lock Managera. Bruce Momjian

Tako smo napravili tablicu pod nazivom Lockdemo. I tamo smo stvorili jednu liniju. Ovo je naš ogledni stol. A mi ćemo stvarati odjeljke samo da vam pokažemo primjere brava.

Otključavanje Postgres Lock Managera. Bruce Momjian

Dakle, jedan red, jedan stupac. Prva vrsta zaključavanja naziva se ACCESS SHARE. Ovo je najmanje restriktivno blokiranje. To znači da praktički nije u sukobu s drugim bravama.

A ako želimo eksplicitno definirati zaključavanje, pokrećemo naredbu "zaključaj tablicu". I očito će blokirati, tj. u ACCESS SHARE modu pokrećemo tablicu zaključavanja. A ako pokrenem PSQL u pozadini, tada započinjem drugu sesiju od prve sesije na ovaj način. Odnosno, što ću ja ovdje? Idem na drugu sesiju i kažem joj "pokaži mi lockview za ovaj zahtjev." I ovdje imam AccessShareLock u ovoj tablici. To je upravo ono što sam tražio. I kaže da je blok dodijeljen. Jako jednostavno.

Otključavanje Postgres Lock Managera. Bruce Momjian

Nadalje, ako pogledamo drugi stupac, onda tamo nema ničega. Prazne su.

Otključavanje Postgres Lock Managera. Bruce Momjian

A ako pokrenem naredbu "SELECT", onda je to implicitni (eksplicitni) način za traženje AccessShareLock-a. Otpuštam svoju tablicu i pokrećem upit, a upit vraća više redaka. I u jednom od redaka vidimo AccessShareLock. Dakle, SELECT poziva AccessShareLock na tablici. I nije u sukobu s praktički ničim jer je zaključavanje niske razine.

Otključavanje Postgres Lock Managera. Bruce Momjian

Što ako pokrenem SELECT i imam tri različite tablice? Ranije sam pokretao samo jednu tablicu, sada pokrećem tri: pg_class, pg_namespace i pg_attribute.

Otključavanje Postgres Lock Managera. Bruce Momjian

I sada kada pogledam upit, vidim 9 AccessShareLocks u tri tablice. Zašto? Tri tablice označene su plavom bojom: pg_attribute, pg_class, pg_namespace. Ali također možete vidjeti da svi indeksi koji su definirani kroz ove tablice također imaju AccessShareLock.

A ovo je brava koja praktički nije u sukobu s drugima. I sve što radi je da nas jednostavno spriječi da ponovno postavimo tablicu dok je odabiremo. Ima smisla. Odnosno, ako odaberemo tablicu, ona u tom trenutku nestane, onda je to pogrešno, dakle AccessShare je zaključavanje niske razine koje nam govori "nemojte ispustiti ovaj stol dok radim". U biti, to je sve što ona radi.

Otključavanje Postgres Lock Managera. Bruce Momjian

ROW SHARE - Ova brava je malo drugačija.

Otključavanje Postgres Lock Managera. Bruce Momjian

Uzmimo primjer. SELECT ROW SHARE metoda zaključavanja svakog retka pojedinačno. Na taj način ih nitko ne može izbrisati ili promijeniti dok ih mi gledamo.

Otključavanje Postgres Lock Managera. Bruce MomjianDakle, što radi SHARE LOCK? Vidimo da je ID transakcije 681 za SELECT. A ovo je zanimljivo. Što se ovdje dogodilo? Broj prvi put vidimo u polju "Zaključaj". Uzimamo ID transakcije i kaže da ga blokira u ekskluzivnom načinu rada. Sve što radi je da kaže da imam redak koji je tehnički zaključan negdje u tablici. Ali ne kaže gdje točno. Pogledat ćemo to detaljnije malo kasnije.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovdje kažemo da bravu koristimo mi.

Otključavanje Postgres Lock Managera. Bruce Momjian

Dakle, ekskluzivna brava eksplicitno govori da je ekskluzivna. I također ako izbrišete red u ovoj tablici, onda će se ovo dogoditi, kao što vidite.

Otključavanje Postgres Lock Managera. Bruce Momjian

SHARE EXCLUSIVE je duži pramen.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovo je naredba analizatora (ANALIZIRAJ) koja će se koristiti.

Otključavanje Postgres Lock Managera. Bruce Momjian

DIJELJENJE ZAKLJUČAVANJE – možete eksplicitno zaključati u načinu dijeljenja.

Otključavanje Postgres Lock Managera. Bruce Momjian

Također možete stvoriti jedinstveni indeks. I tamo možete vidjeti SHARE LOCK, koji je dio njih. I zaključava stol i stavlja SHARE LOCK na njega.

Prema zadanim postavkama, SHARE LOCK na tablici znači da drugi ljudi mogu čitati tablicu, ali je nitko ne može mijenjati. A upravo se to događa kada izradite jedinstveni indeks.

Ako kreiram jedinstveni istodobni indeks, tada ću imati drugačiji tip zaključavanja jer, kao što se sjećate, korištenje istodobnih indeksa smanjuje zahtjev za zaključavanjem. A ako koristim normalno zaključavanje, normalni indeks, tada ću spriječiti pisanje indeksa tablice dok se stvara. Ako koristim istodobno indeks, tada trebam koristiti drugu vrstu zaključavanja.

Otključavanje Postgres Lock Managera. Bruce Momjian

SHARE ROW EXCLUSIVE – opet se može postaviti eksplicitno (eksplicitno).

Otključavanje Postgres Lock Managera. Bruce Momjian

Ili možemo stvoriti pravilo, tj. uzeti određeni slučaj u kojem će se ono koristiti.

Otključavanje Postgres Lock Managera. Bruce Momjian

EKSKLUZIVNO zaključavanje znači da nitko drugi ne može promijeniti stol.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovdje vidimo različite vrste brava.

Otključavanje Postgres Lock Managera. Bruce Momjian

ACCESS EXCLUSIVE, na primjer, je naredba za blokiranje. Na primjer, ako to učinite CLUSTER table, onda će to značiti da tamo nitko neće moći pisati. I zaključava ne samo samu tablicu, već i indekse.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovo je druga stranica blokade ACCESS EXCLUSIVE, gdje u tablici vidimo što točno blokira. Zaključava pojedinačne redove tablice, što je vrlo zanimljivo.

To su sve osnovne informacije koje sam htio dati. Razgovarali smo o bravama, o ID-ovima transakcija, razgovarali smo o ID-ovima virtualnih transakcija, o trajnim ID-ovima transakcija.

Otključavanje Postgres Lock Managera. Bruce Momjian

A sada ćemo proći kroz neke blokirajuće primjere. Ovo je najzanimljiviji dio. Pogledat ćemo vrlo zanimljive slučajeve. A moj cilj u ovoj prezentaciji je dati vam bolje razumijevanje onoga što Postgres zapravo radi kada pokušava blokirati određene stvari. Mislim da je vrlo dobar u blokiranju dijelova.

Pogledajmo neke konkretne primjere.

Otključavanje Postgres Lock Managera. Bruce Momjian

Počet ćemo s tablicama i jednim redom u tablici. Kad nešto umetnem, na tablici se prikazuju ExclusiveLock, ID transakcije i ExclusiveLock.

Otključavanje Postgres Lock Managera. Bruce Momjian

Što se događa ako umetnem još dva retka? I sada naša tablica ima tri reda. I umetnuo sam jedan red i dobio ovo kao izlaz. I ako ubacim još dva reda, što je tu čudno? Ovdje postoji čudna stvar jer sam ovoj tablici dodao tri retka, ali još uvijek imam dva retka u zaključanoj tablici. I to je u biti temeljno ponašanje Postgresa.

Mnogi ljudi misle da ako u bazi podataka zaključate 100 redaka, tada ćete morati stvoriti 100 zaključanih unosa. Ako blokiram 1 redaka odjednom, trebat će mi 000 takvih upita. I ako mi treba milijun ili milijarda za blokadu. Ali ako to učinimo, neće dobro funkcionirati. Ako ste koristili sustav koji stvara blokirajuće unose za svaki pojedinačni redak, možete vidjeti da je ovo komplicirano. Zato što trebate odmah definirati zaključanu tablicu koja se može prelijevati, ali Postgres to ne radi.

A ono što je stvarno važno kod ovog slajda je da jasno pokazuje da postoji još jedan sustav koji radi unutar MVCC-a koji zaključava pojedinačne retke. Dakle, kada zaključate milijarde redaka, Postgres ne stvara milijardu zasebnih naredbi za zaključavanje. A to ima vrlo dobar učinak na produktivnost.

Otključavanje Postgres Lock Managera. Bruce Momjian

Što je s ažuriranjem? Sada ažuriram red i možete vidjeti da je izvršio dvije različite operacije odjednom. Zaključao je tablicu u isto vrijeme, ali je zaključao i indeks. I morao je zaključati indeks jer postoje jedinstvena ograničenja na ovoj tablici. I želimo biti sigurni da ga nitko ne mijenja, pa ga blokiramo.

Otključavanje Postgres Lock Managera. Bruce Momjian

Što se događa ako želim ažurirati dva retka? I vidimo da se i on tako ponaša. Radimo dvostruko više ažuriranja, ali točno isti broj redaka za zaključavanje.

Ako se pitate kako Postgres to radi, morat ćete poslušati moje govore o MVCC-u da biste saznali kako Postgres interno označava ove retke koje mijenja. I Postgres ima način na koji to radi, ali to ne radi na razini zaključavanja tablice, radi to na nižoj i učinkovitijoj razini.

Otključavanje Postgres Lock Managera. Bruce Momjian

Što ako želim nešto izbrisati? Ako izbrišem, na primjer, jedan red i još uvijek imam svoja dva blokirajuća ulaza, čak i ako ih želim sve izbrisati, oni su i dalje tu.

Otključavanje Postgres Lock Managera. Bruce Momjian

I, na primjer, želim umetnuti 1 redaka, a zatim ili izbrisati ili dodati 000 redaka, onda ti pojedinačni redovi koje dodam ili promijenim, oni se ovdje ne bilježe. Napisane su na nižoj razini unutar same serije. I tijekom govora MVCC-a govorio sam o tome detaljno. Ali vrlo je važno kada analizirate zaključavanja da budete sigurni da zaključavate na razini tablice i da ne vidite kako se ovdje bilježe pojedinačni redovi.

Otključavanje Postgres Lock Managera. Bruce Momjian

Što je s eksplicitnim blokiranjem?

Otključavanje Postgres Lock Managera. Bruce Momjian

Ako kliknem na osvježi, imam zaključana dva retka. A ako ih sve odaberem i kliknem "ažuriraj posvuda", još uvijek imam dva blokirajuća zapisa.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ne stvaramo zasebne zapise za svaki pojedinačni redak. Jer tada pada produktivnost, može ga biti previše. I možemo se naći u neugodnoj situaciji.

Otključavanje Postgres Lock Managera. Bruce Momjian

I ista stvar, ako dijelimo, možemo to učiniti svih 30 puta.

Otključavanje Postgres Lock Managera. Bruce Momjian

Vraćamo našu tablicu, brišemo sve, zatim ponovno umećemo jedan red.

Otključavanje Postgres Lock Managera. Bruce Momjian

Još jedno ponašanje koje vidite u Postgresu, a koje je vrlo dobro poznato i poželjno ponašanje je da možete napraviti ažuriranje ili odabir. I to možete učiniti u isto vrijeme. I odaberite ne blokira ažuriranje i isto u suprotnom smjeru. Kažemo čitatelju da ne blokira pisca, a pisac nije blokirao čitatelja.

Pokazat ću vam primjer ovoga. Sada ću napraviti izbor. Zatim ćemo napraviti INSERT. I tada možete vidjeti - 694. Možete vidjeti ID transakcije koja je izvršila ovo umetanje. I tako to funkcionira.

Otključavanje Postgres Lock Managera. Bruce Momjian

I ako sada pogledam svoj pozadinski ID, sada je 695.

Otključavanje Postgres Lock Managera. Bruce Momjian

I vidim da se 695 pojavljuje u mojoj tablici.

Otključavanje Postgres Lock Managera. Bruce Momjian

I ako ažuriram ovdje ovako, onda ću dobiti drugačiji slučaj. U ovom slučaju, 695 je ekskluzivno zaključavanje, a ažuriranje ima isto ponašanje, ali nema sukoba između njih, što je prilično neobično.

I možete vidjeti da je na vrhu ShareLock, a na dnu ExclusiveLock. I obje su transakcije uspjele.

I morate poslušati moj govor u MVCC-u da biste razumjeli kako se to događa. Ali ovo je ilustracija da to možete učiniti u isto vrijeme, tj. napraviti SELECT i UPDATE u isto vrijeme.

Otključavanje Postgres Lock Managera. Bruce Momjian

Idemo resetirati i napraviti još jednu operaciju.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ako pokušate pokrenuti dva ažuriranja istovremeno u istom retku, ono će biti blokirano. I zapamtite, rekao sam da čitatelj ne blokira pisca, a pisac ne blokira čitatelja, ali jedan pisac blokira drugog pisca. To jest, ne možemo dopustiti da dvije osobe ažuriraju isti redak u isto vrijeme. Morate pričekati dok jedan od njih ne završi.

Otključavanje Postgres Lock Managera. Bruce Momjian

A kako bih ovo ilustrirao, pogledat ću tablicu Lockdemo. I pogledat ćemo jedan red. Po transakciji 698.

Ovo smo ažurirali na 2. 699 je prvo ažuriranje. I bila je uspješna ili je u transakciji na čekanju i čeka našu potvrdu ili otkazivanje.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ali pogledajte nešto drugo - 2/51 je naša prva transakcija, naša prva sesija. 3/112 je drugi zahtjev koji je došao s vrha koji je promijenio tu vrijednost na 3. I ako primijetite, gornji se sam zaključao, što je 699. Ali 3/112 nije odobrio zaključavanje. Stupac Lock_mode govori što se čeka. Očekuje 699. A ako pogledate gdje je 699, to je više. I što je učinila prva sesija? Stvorila je ekskluzivno zaključavanje vlastitog ID-a transakcije. Postgres to radi ovako. Blokira vlastiti ID transakcije. A ako želite pričekati da netko potvrdi ili otkaže, tada morate pričekati dok postoji transakcija na čekanju. I zato možemo vidjeti čudnu liniju.

Pogledajmo ponovno. S lijeve strane vidimo naš ID obrade. U drugom stupcu vidimo naš ID virtualne transakcije, au trećem vidimo lock_type. Što to znači? U biti piše da blokira ID transakcije. Ali primijetite da svi redovi na dnu govore o odnosu. I tako imate dvije vrste brava na stolu. Postoji zaključavanje odnosa. A tu je i transakcijski ID blokiranje, gdje sami blokirate, što je upravo ono što se događa u prvom redu ili na samom dnu, gdje je transakcijski ID, gdje čekamo da 699 završi svoju operaciju.

Vidjet ću što će se ovdje dogoditi. I tu se dvije stvari događaju istovremeno. Gledate zaključavanje ID-a transakcije u prvom redu koje se samo zaključava. I sama se blokira kako bi ljudi čekali.

Ako pogledate 6. redak, to je isti unos kao i prvi. Zbog toga je transakcija 699 blokirana. 700 je također samozaključavajuća. A onda ćete u donjem redu vidjeti da čekamo da 699 završi svoju operaciju.

Otključavanje Postgres Lock Managera. Bruce Momjian

A u lock_type, tuple vidite brojeve.

Otključavanje Postgres Lock Managera. Bruce Momjian

Možete vidjeti da je 0/10. A ovo je broj stranice, a također i pomak ovog određenog retka.

Otključavanje Postgres Lock Managera. Bruce Momjian

I vidite da postaje 0/11 kada ažuriramo.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ali u stvarnosti je 0/10, jer se čeka na ovu operaciju. Imamo priliku vidjeti da je ovo serijal koju čekam potvrditi.

Otključavanje Postgres Lock Managera. Bruce Momjian

Nakon što smo to potvrdili i pritisnuli commit, i kada je ažuriranje završeno, to je ono što ponovno dobivamo. Transakcija 700 je jedino zaključavanje, ne čeka nikoga drugog jer je predano. Jednostavno čeka da se transakcija završi. Nakon što istekne 699, više ništa ne čekamo. I sada transakcija 700 kaže da je sve u redu, da ima sve potrebne brave na svim dopuštenim tablicama.

Otključavanje Postgres Lock Managera. Bruce Momjian

A da bi cijela stvar bila još kompliciranija, stvaramo još jedan pogled, koji će nam ovaj put pružiti hijerarhiju. Ne očekujem da ćete razumjeti ovaj zahtjev. Ali ovo će nam dati jasniji pogled na ono što se događa.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovo je rekurzivni pogled koji također ima još jedan odjeljak. A onda opet sve skupi. Iskoristimo ovo.

Otključavanje Postgres Lock Managera. Bruce Momjian

Što ako napravimo tri istovremena ažuriranja i kažemo da je red sada tri. I promijenit ćemo 3 u 4.

Otključavanje Postgres Lock Managera. Bruce Momjian

I ovdje vidimo 4. I ID transakcije 702.

Otključavanje Postgres Lock Managera. Bruce Momjian

A onda ću promijeniti 4 u 5. I 5 u 6, i 6 u 7. I poredat ću nekoliko ljudi koji će čekati da ova jedna transakcija završi.

Otključavanje Postgres Lock Managera. Bruce Momjian

I sve postaje jasno. Koji je prvi red? Ovo je 702. Ovo je ID transakcije koji je izvorno postavio ovu vrijednost. Što piše u mojoj koloni Odobreno? Imam oznake f. Ovo su moja ažuriranja koja (5, 6, 7) ne mogu biti odobrena jer čekamo da ID transakcije 702 završi. Tu imamo blokiranje ID transakcije. A to rezultira s 5 transakcijskih ID zaključavanja.

I ako pogledate 704, 705, tamo još ništa nije napisano, jer oni još ne znaju što se događa. Jednostavno pišu da nemaju pojma što se događa. I samo će otići spavati jer čekaju da netko završi i da ih se probudi kad se ukaže prilika za promjenu redova.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovako to izgleda. Jasno je da svi oni čekaju 12. red.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovo smo vidjeli ovdje. Evo 0/12.

Otključavanje Postgres Lock Managera. Bruce Momjian

Dakle, kada je prva transakcija odobrena, ovdje možete vidjeti kako funkcionira hijerarhija. I sada sve postaje jasno. Svi postaju čisti. I zapravo još uvijek čekaju.

Otključavanje Postgres Lock Managera. Bruce Momjian

Evo što se događa. 702 obvezuje. I sada 703 dobiva ovo zaključavanje retka, a zatim 704 počinje čekati da 703 preda. A 705 čeka i ovo. A kad se sve to završi, čiste se. I želio bih istaknuti da svi stoje u redu. I to je vrlo slično situaciji u prometnoj gužvi kada svi čekaju prvi auto. Zaustavlja se prvi auto i svi se postrojavaju u dugi red. Zatim se pomakne, zatim sljedeći automobil može voziti naprijed i dobiti svoj blok, itd.

Otključavanje Postgres Lock Managera. Bruce Momjian

A ako vam se ovo nije činilo dovoljno komplicirano, sada ćemo razgovarati s vama o zastojima. Ne znam tko se od vas susreo s njima. Ovo je prilično čest problem u sustavima baza podataka. Ali zastoji su kada jedna sesija čeka da druga sesija nešto učini. I u ovom trenutku još jedna sesija čeka prvu sesiju da nešto učini.

I, na primjer, ako Ivan kaže: "Daj mi nešto", a ja kažem: "Ne, dat ću ti samo ako mi daš nešto drugo." A on kaže: "Ne, neću ti dati ako ti meni ne daš." I završimo u bezizlaznoj situaciji. Siguran sam da Ivan to neće učiniti, ali shvaćate što znači da imamo dvoje ljudi koji žele nešto dobiti i nisu spremni to dati dok im drugi ne da ono što žele. A rješenja nema.

I u biti, vaša baza podataka to mora otkriti. A onda trebate izbrisati ili zatvoriti jednu od sesija, jer će u protivnom ostati tamo zauvijek. I vidimo to u bazama podataka, vidimo to u operativnim sustavima. I na svim mjestima gdje imamo paralelne procese to se može dogoditi.

Otključavanje Postgres Lock Managera. Bruce Momjian

A sada ćemo instalirati dva zastoja. Stavit ćemo 50 i 80. U prvom redu ću ažurirati s 50 na 50. Dobit ću broj transakcije 710.

Otključavanje Postgres Lock Managera. Bruce Momjian

A onda ću promijeniti 80 u 81, i 50 u 51.

Otključavanje Postgres Lock Managera. Bruce Momjian

A ovako će to izgledati. I tako 710 ima blokiran red, a 711 čeka potvrdu. To smo vidjeli kada smo ažurirali. 710 je vlasnik naše serije. I 711 čeka da 710 završi transakciju.

Otključavanje Postgres Lock Managera. Bruce Momjian

I čak piše u kojem retku se pojavljuju zastoji. I tu počinje biti čudno.

Otključavanje Postgres Lock Managera. Bruce Momjian

Sada ažuriramo 80 na 80.

Otključavanje Postgres Lock Managera. Bruce Momjian

I tu počinju zastoji. 710 čeka odgovor od 711, a 711 čeka 710. I to neće dobro završiti. I nema izlaza iz ovoga. I očekivat će odgovor jedni od drugih.

Otključavanje Postgres Lock Managera. Bruce Momjian

I samo će početi sve odgađati. A mi to ne želimo.

Otključavanje Postgres Lock Managera. Bruce Momjian

A Postgres ima načine da primijeti kada se to dogodi. A kada se to dogodi, dobivate ovu pogrešku. I iz ovoga je jasno da taj i takav proces čeka SHARE LOCK od drugog procesa, tj. koji je blokiran od strane 711 procesa. I taj proces je čekao da se SHARE LOCK da na taj i taj ID transakcije i blokirao ga je taj i taj proces. Dakle, ovdje postoji bezizlazna situacija.

Otključavanje Postgres Lock Managera. Bruce Momjian

Postoje li trostrani zastoji? Je li moguće? Da.

Otključavanje Postgres Lock Managera. Bruce Momjian

Te brojeve unosimo u tablicu. Mijenjamo 40 na 40, radimo blokadu.

Otključavanje Postgres Lock Managera. Bruce Momjian

Mijenjamo 60 u 61, 80 u 81.

Otključavanje Postgres Lock Managera. Bruce Momjian

A onda promijenimo 80 i onda bum!

Otključavanje Postgres Lock Managera. Bruce Momjian

A 714 sada čeka 715. 716. čeka 715. I tu se ništa ne može učiniti.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovdje više nema dvoje ljudi, ovdje je već troje ljudi. Ja hoću nešto od tebe, ovaj hoće nešto od treće osobe, a treća osoba hoće nešto od mene. I završimo u trosmjernom čekanju jer svi čekamo da druga osoba dovrši ono što treba učiniti.

Otključavanje Postgres Lock Managera. Bruce Momjian

A Postgres zna u kojem se retku to događa. I tako će vam dati sljedeću poruku, koja pokazuje da imate problem gdje se tri ulaza međusobno blokiraju. I ovdje nema ograničenja. To može biti slučaj kada se 20 unosa međusobno blokira.

Otključavanje Postgres Lock Managera. Bruce Momjian

Sljedeći problem se može serijalizirati.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ako je posebna brava koja se može serijalizirati.

Otključavanje Postgres Lock Managera. Bruce Momjian

I vraćamo se na 719. Njegov izlaz je sasvim normalan.

Otključavanje Postgres Lock Managera. Bruce Momjian

I možete kliknuti da biste transakciju učinili serijalizirajućom.

Otključavanje Postgres Lock Managera. Bruce Momjian

I shvatite da sada imate drugačiju vrstu SA zaključavanja - to znači da se može serijalizirati.

Otključavanje Postgres Lock Managera. Bruce Momjian

Otključavanje Postgres Lock Managera. Bruce Momjian

I tako imamo novu vrstu brave koja se zove SARieadLock, koja je serijska brava i omogućuje vam unos serijskih brojeva.

Otključavanje Postgres Lock Managera. Bruce Momjian

Također možete umetnuti jedinstvene indekse.

Otključavanje Postgres Lock Managera. Bruce Momjian

U ovoj tablici imamo jedinstvene indekse.

Otključavanje Postgres Lock Managera. Bruce Momjian

Dakle, ako ovdje stavim broj 2, tako da imam 2. Ali na samom vrhu, stavio sam još 2. I možete vidjeti da 721 ima ekskluzivnu bravu. Ali sada 722 čeka da 721 završi svoju operaciju jer ne može umetnuti 2 dok ne zna što će se dogoditi sa 721.

Otključavanje Postgres Lock Managera. Bruce Momjian

A ako radimo podtransakciju.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovdje imamo 723.

Otključavanje Postgres Lock Managera. Bruce Momjian

A ako spremimo točku i zatim je ažuriramo, tada ćemo dobiti novi ID transakcije. Ovo je još jedan obrazac ponašanja kojeg morate biti svjesni. Ako ovo vratimo, ID transakcije nestaje. 724 odlazi. Ali sada imamo 725.

Dakle, što ja pokušavam učiniti ovdje? Pokušavam vam pokazati primjere neobičnih brava koje biste mogli pronaći: bilo da se radi o serijalizirajućim bravama ili SAVEPOINT, ovo su različite vrste brava koje će se pojaviti u tablici zaključavanja.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovo je stvaranje eksplicitnih (eksplicitnih) brava, koje imaju pg_advisory_lock.

Otključavanje Postgres Lock Managera. Bruce Momjian

I vidite da je vrsta blokiranja navedena kao savjetodavna. A ovdje crvenom bojom piše "savjetodavno". I možete istovremeno blokirati ovako s pg_advisory_unlock.

Otključavanje Postgres Lock Managera. Bruce Momjian

I na kraju, želio bih vam pokazati još jednu nevjerojatnu stvar. Stvorit ću drugi pogled. Ali pridružit ću tablicu pg_locks tablici pg_stat_activity. I zašto to želim učiniti? Zato što će mi to omogućiti da pogledam i vidim sve trenutne sesije i točno vidim kakvu vrstu zaključavanja čekaju. I ovo je vrlo zanimljivo kada spojimo tablicu zaključavanja i tablicu upita.

Otključavanje Postgres Lock Managera. Bruce Momjian

I ovdje stvaramo pg_stat_view.

Otključavanje Postgres Lock Managera. Bruce Momjian

I ažuriramo red po jedan. I ovdje vidimo 724. I onda ažuriramo naš red na tri. I što sad vidite ovdje? To su zahtjevi, odnosno vidite cijeli popis zahtjeva koji su navedeni u lijevom stupcu. A onda s desne strane možete vidjeti blokade i što one stvaraju. I može vam biti jasnije tako da se ne morate svaki put vraćati na svaku sesiju i vidjeti trebate li joj se pridružiti ili ne. Oni to rade za nas.

Još jedna značajka koja je vrlo korisna je pg_blocking_pids. Vjerojatno nikad niste čuli za nju. Što ona radi? Omogućuje nam da kažemo za ovu sesiju 11740 koje specifične ID-ove procesa čeka. I vidi se da 11740 čeka 724. A 724 je na samom vrhu. A 11306 je ID vašeg procesa. U osnovi, ova funkcija prolazi kroz vašu tablicu zaključavanja. I znam da je malo komplicirano, ali uspjeli ste to razumjeti. U suštini, ova funkcija prolazi kroz ovu tablicu zaključavanja i pokušava pronaći gdje se ovaj ID procesa nalazi s obzirom na zaključavanja na koja čeka. Također pokušava otkriti koji ID procesa ima proces koji čeka na zaključavanje. Dakle, možete pokrenuti ovu funkciju pg_blocking_pids.

A ovo može biti vrlo korisno. Dodali smo ovo samo u verziji 9.6, tako da je ova značajka stara samo 5 godina, ali je vrlo, vrlo korisna. Isto vrijedi i za drugi zahtjev. Pokazuje točno ono što trebamo vidjeti.

Otključavanje Postgres Lock Managera. Bruce Momjian

O ovome sam htio razgovarati s tobom. I kao što sam i očekivao, potrošili smo svo vrijeme jer je bilo toliko slajdova. A slajdovi su dostupni za preuzimanje. Htio bih vam zahvaliti što ste ovdje. Siguran sam da ćete uživati ​​u ostatku konferencije, hvala vam puno!

Pitanja:

Na primjer, ako pokušavam ažurirati retke, a druga sesija pokušava izbrisati cijelu tablicu. Koliko ja razumijem, trebalo bi postojati nešto poput zaključavanja namjere. Postoji li takvo što u Postgresu?

Otključavanje Postgres Lock Managera. Bruce Momjian

Vratimo se na sam početak. Možda se sjećate da kada učinite bilo što, na primjer kada napravite SELECT, izdajemo AccessShareLock. I to sprječava pad stola. Dakle, ako vi, na primjer, želite ažurirati redak u tablici ili izbrisati redak, tada netko ne može obrisati cijelu tablicu u isto vrijeme jer držite ovaj AccessShareLock preko cijele tablice i preko retka. A kad završite, mogu ga izbrisati. Ali dok vi tamo nešto izravno promijenite, oni to neće moći učiniti.

Napravimo to ponovno. Prijeđimo na primjer brisanja. I vidite kako postoji ekskluzivna brava u redu iznad cijele tablice.

Ovo će izgledati kao ekskluzivna brava, zar ne?

Da, tako izgleda. Razumijem o čemu govoriš. Kažete da ako napravim SELECT, onda imam ShareExclusive i onda ga učinim Row Exclusive, postaje li to problem? No, začudo, to ne predstavlja problem. Ovo izgleda kao povećanje stupnja zaključavanja, ali u biti imam zaključavanje koje sprječava brisanje. I sada, kada ovo zaključavanje učinim snažnijim, ono i dalje sprječava brisanje. Dakle, nije da idem gore. Odnosno, spriječio je da se to dogodi i kad je bio na nižoj razini, pa kad podignem njegovu razinu, i dalje sprječava brisanje tablice.

Razumijem o čemu govoriš. Ovdje nema slučaja eskalacije zaključavanja, gdje pokušavate odustati od jednog zaključavanja da biste uveli jače. Ovdje samo povećava ovu prevenciju u cijelosti, tako da ne uzrokuje nikakav sukob. Ali to je dobro pitanje. Hvala vam što ste ovo postavili!

Što trebamo učiniti kako bismo izbjegli situaciju zastoja kada imamo mnogo sesija, veliki broj korisnika?

Postgres automatski primjećuje situacije zastoja. I automatski će izbrisati jednu od sesija. Jedini način da izbjegnete mrtvo blokiranje je da blokirate ljude istim redoslijedom. Dakle, kada pogledate svoju aplikaciju, često je razlog zastoja... Zamislimo da želim blokirati dvije različite stvari. Jedna aplikacija zaključava tablicu 1, a druga aplikacija zaključava tablicu 2, a zatim tablicu 1. A najlakši način da izbjegnete zastoj je da pogledate svoju aplikaciju i pokušate se uvjeriti da se zaključavanje odvija istim redoslijedom u svim aplikacijama. I to obično eliminira 80% problema, jer svakakvi ljudi pišu ove aplikacije. A ako ih blokirate istim redoslijedom, nećete naići na situaciju zastoja.

Hvala vam puno na vašem nastupu! Govorili ste o potpunom vakuumu i, ako dobro razumijem, puni vakuum iskrivljuje redoslijed zapisa u zasebnoj pohrani, tako da trenutni zapisi ostaju nepromijenjeni. Zašto puni vakuum zahtijeva ekskluzivni pristup zaključavanju i zašto je u sukobu s operacijama pisanja?

To je dobro pitanje. Razlog je što vakuum pun zauzima stol. I mi u biti stvaramo novu verziju tablice. I stol će biti nov. Ispostavilo se da će ovo biti potpuno nova verzija tablice. A problem je u tome što kada ovo radimo, ne želimo da ljudi to čitaju jer trebamo da vide novu tablicu. I tako se ovo povezuje s prethodnim pitanjem. Da možemo čitati u isto vrijeme, ne bismo ga mogli pomaknuti i usmjeriti ljude na novi stol. Trebali bismo pričekati da svi završe s čitanjem ove tablice, pa je to u biti situacija isključivanja brave.
Samo kažemo da zaključavamo od početka jer znamo da će nam na samom kraju trebati ekskluzivno zaključavanje kako bismo sve premjestili na novu kopiju. Tako da to potencijalno možemo riješiti. A mi to radimo na ovaj način uz istovremeno indeksiranje. Ali ovo je mnogo teže učiniti. I ovo se uvelike odnosi na vaše prethodno pitanje o zaključavanju.

Je li moguće dodati vremensko ograničenje zaključavanja u Postgres? U Oracleu mogu, primjerice, napisati "select to update" i pričekati 50 sekundi prije ažuriranja. Bilo je dobro za aplikaciju. Ali u Postgresu to moram učiniti odmah i ne čekati uopće, ili čekati neko vrijeme.

Da, možete odabrati vrijeme čekanja na svojim bravama, na svojim bravama. Također možete izdati naredbu zabrane, koja će... ako ne možete odmah dobiti bravu. Stoga, ili vremensko ograničenje zaključavanja ili nešto drugo što će vam omogućiti da to učinite. To se ne radi na sintaktičkoj razini. To se radi kao varijabla na poslužitelju. Ponekad se to ne može koristiti.

Možete li otvoriti slajd 75?

Da.

Otključavanje Postgres Lock Managera. Bruce Momjian

A moje pitanje je sljedeće. Zašto oba procesa ažuriranja očekuju 703?

A ovo je odlično pitanje. Usput, ne razumijem zašto Postgres to radi. Ali kada je stvoren 703, očekivao se 702. A kada se pojave 704 i 705, čini se kao da ne znaju što očekuju jer tamo još nema ničega. A Postgres to radi ovako: kad ne možete dobiti bravu, piše "Koja je svrha obrađivati ​​vas?", jer već čekate nekoga. Pa ćemo ga pustiti da visi u zraku, neće ga uopće ažurirati. Ali što se ovdje dogodilo? Čim je 702 završio proces i 703 dobio svoju bravu, sustav se vratio natrag. I rekla je da sada imamo dvoje ljudi koji čekaju. A onda ih ažurirajmo zajedno. I naznačimo da oboje očekuju.

Ne znam zašto Postgres to radi. Ali postoji problem koji se zove f…. Čini mi se da to nije izraz u ruskom. To je kad svi čekaju jedan dvorac, makar 20 vlasti čekalo dvorac. I odjednom se svi probude u isto vrijeme. I svi počnu pokušavati reagirati. Ali sustav radi tako da svi čekaju 703. Jer svi čekaju i odmah ćemo ih sve postrojiti. A ako se pojavi još neki novi zahtjev koji je generiran nakon ovoga, npr. 707, onda će opet biti praznina.

I čini mi se da je to napravljeno da možemo reći da u ovoj fazi 702 čeka 703, a svi oni koji dođu nakon toga neće imati nikakav unos u ovo polje. Ali čim prvi konobar ode, svi oni koji su čekali u tom trenutku prije ažuriranja dobivaju isti token. I zato mislim da je ovo učinjeno kako bismo mogli obraditi po redu tako da budu ispravno poredani.

Uvijek sam na to gledao kao na prilično čudan fenomen. Jer ovdje ih, na primjer, uopće ne navodimo. Ali čini mi se da svaki put kad damo novu bravu pogledamo sve one koji su na čekanju. Zatim ih sve poredamo. A onda svaki novi koji dođe ulazi u red samo kada sljedeća osoba završi s obradom. Vrlo dobro pitanje. Hvala vam puno na vašem pitanju!

Čini mi se da je puno logičnije kada 705 očekuje 704.

Ali ovdje je problem sljedeći. Tehnički, možete probuditi jednog ili drugog. I tako ćemo probuditi jedno ili drugo. Ali što se događa u sustavu? Možete vidjeti kako je 703 na samom vrhu blokirao vlastiti ID transakcije. Ovako funkcionira Postgres. A 703 je blokiran vlastitim ID-om transakcije, tako da ako netko želi čekati, onda će čekati 703. I, u biti, 703 dovršava. I tek nakon njegovog završetka jedan od procesa se budi. I ne znamo kakav će točno biti ovaj proces. Zatim sve postupno obrađujemo. Ali nije jasno koji se proces prvi budi, jer to može biti bilo koji od ovih procesa. U biti, imali smo planer koji je rekao da sada možemo probuditi bilo koji od ovih procesa. Nasumično biramo jednog. Dakle, oboje ih treba zabilježiti jer možemo probuditi bilo kojeg od njih.

A problem je što imamo CP-beskonačnost. I stoga je vrlo vjerojatno da možemo probuditi kasnijeg. A ako, primjerice, probudimo kasnijeg, čekat ćemo onoga koji je upravo dobio blok, tako da ne određujemo tko će se točno prvi probuditi. Jednostavno stvorimo takvu situaciju, a sustav će ih probuditi nasumičnim redoslijedom.

Tu je članci o bravama Egor Rogov. Pogledajte, oni su također zanimljivi i korisni. Tema je, naravno, užasno kompleksna. Puno ti hvala, Bruce!

Izvor: www.habr.com

Dodajte komentar