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 ovom linku: http://momjian.us/main/writings/pgsql/locking.sql)

Zdravo! Divno je ponovo biti ovde u Rusiji. Žao mi je što nisam mogao doći prošle godine, ali ove godine Ivan i ja imamo velike planove. Nadam se da ću biti ovde mnogo češće. Volim dolaziti u Rusiju. Posjetiću Tjumenj, Tver. Veoma mi je drago što ću moći da posetim ove gradove.

Moje ime je Bruce Momjian. Radim u EnterpriseDB-u i radim sa Postgres-om više od 23 godine. Živim u Philadelphia, SAD. Putujem oko 90 dana u godini. I prisustvujem oko 40 konferencija. Moj Web stranica, koji sadrži slajdove koje ću vam sada pokazati. Stoga ih nakon konferencije možete preuzeti sa moje lične web stranice. Takođe sadrži oko 30 prezentacija. Tu su i video zapisi i veliki broj unosa na blogu, više od 500. Ovo je prilično informativan izvor. A ako ste zainteresirani za ovaj materijal, onda vas pozivam da ga iskoristite.

Bio sam učitelj, profesor prije nego što sam počeo raditi sa Postgresom. I veoma mi je drago što ću sada moći da vam kažem ono što ću vam reći. Ovo je jedna od mojih najzanimljivijih prezentacija. I ova prezentacija sadrži 110 slajdova. Počećemo da pričamo o jednostavnim stvarima, a na kraju izveštaj će biti sve složeniji i poprilično složen.

Otključavanje Postgres Lock Managera. Bruce Momjian

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

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 rade u isto vrijeme. Treba im blokiranje. 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 biće prilično teško razumjeti.

Otključavanje Postgres Lock Managera. Bruce Momjian

Hajde da pričamo o blokiranju.

Otključavanje Postgres Lock Managera. Bruce Momjian

Naša terminologija je prilično složena. Koliko vas zna odakle dolazi ovaj odlomak? Dvoje ljudi. Ovo je iz igre koja se zove Colossal Cave Adventure. Mislim da je to bila kompjuterska igrica zasnovana na tekstu 80-ih. Tamo je trebalo ući u pećinu, u lavirint, i tekst se mijenjao, ali sadržaj je svaki put bio otprilike isti. Tako se sjećam ove utakmice.

Otključavanje Postgres Lock Managera. Bruce Momjian

I ovdje vidimo naziv brava koje su nam došle 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 početi s tim kako ove brave rade.

Otključavanje Postgres Lock Managera. Bruce Momjian

I riječ „pristup“ je takođe veoma važna. A riječi "red" su niz. To jest, distribucija pristupa, distribucija redova.

Otključavanje Postgres Lock Managera. Bruce Momjian

Još jedno pitanje koje treba razumjeti u Postgresu, a koje 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 vjerovatno 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 je ID transakcija. Mnoge transakcije ne mogu raditi bez jedinstvenih identifikatora. I ovdje imamo objašnjenje šta je transakcija. Postgres ima dva sistema numerisanja transakcija. Znam da ovo nije baš lijepo rješenje.

Otključavanje Postgres Lock Managera. Bruce Momjian

Takođe imajte na umu da će slajdove biti prilično teško razumjeti, tako da je ono na što je istaknuto crveno ono na šta trebate obratiti pažnju.

Otključavanje Postgres Lock Managera. Bruce Momjian

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

da vidimo. Broj transakcije je označen 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 odmah biti 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 virtuelni ID transakcije

I to moramo razumjeti. Ovo je veoma važno, inače nećemo moći da razumemo zaključavanje u Postgresu.

Virtuelni ID transakcije je ID transakcije koji ne sadrži trajne vrijednosti. Na primjer, ako pokrenem naredbu SELECT, onda najvjerovatnije neću mijenjati bazu podataka, neću ništa zaključati. Dakle, kada pokrenemo jednostavan SELECT, toj transakciji ne damo trajni ID. Tamo joj dajemo samo virtuelnu ličnu kartu.

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

Otključavanje Postgres Lock Managera. Bruce Momjian

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

Otključavanje Postgres Lock Managera. Bruce Momjian

A ako pokrenem niz takvih transakcija, onda 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 dvije kolone. Na lijevoj strani vidimo ID virtuelne transakcije – 2/12. A na desnoj strani imamo trajni ID transakcije. I ovo polje je prazno. I ova transakcija ne mijenja bazu podataka. Tako da mu ne dajem trajni ID transakcije.

Otključavanje Postgres Lock Managera. Bruce Momjian

Čim pokrenem naredbu analize ((ANALYZE)), isti upit mi daje trajni ID transakcije. Pogledajte kako se to kod nas promijenilo. Ranije nisam imao ovu ličnu kartu, ali sada je imam.

Otključavanje Postgres Lock Managera. Bruce Momjian

Dakle, evo još jednog zahtjeva, još jedne transakcije. Broj virtuelne transakcije je 2/13. A ako tražim trajni ID transakcije, onda ću ga dobiti kada pokrenem upit.

Otključavanje Postgres Lock Managera. Bruce Momjian

Dakle, još jednom. Imamo ID virtuelne transakcije i trajni ID transakcije. Samo shvatite ovu tač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. Poslednji deo će biti mnogo zanimljiviji. Ali moramo uzeti u obzir osnovne stvari, jer inače nećemo shvatiti šta će se dalje dogoditi.

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

Otključavanje Postgres Lock Managera. Bruce Momjian

Da kreiramo upit i vidimo šta se dešava u Postgresu, potrebno je da postavimo upit u sistemskom prikazu. U ovom slučaju, pg_lock je označen crvenom bojom. Pg_lock je sistemska tabela koja nam govori koje su brave trenutno u upotrebi u Postgresu.

Međutim, veoma mi je teško da vam pokažem pg_lock sam po sebi jer je prilično složen. Tako sam napravio prikaz koji pokazuje pg_locks. I takođe mi radi nešto što mi omogućava da bolje razumijem. To jest, isključuje moje brave, moju vlastitu sesiju, itd. To je samo standardni SQL i omogućava vam da vam bolje pokažete što se događa.

Otključavanje Postgres Lock Managera. Bruce Momjian

Drugi problem je što je ovaj pogled veoma širok, pa moram da napravim drugi - lockview2.

Otključavanje Postgres Lock Managera. Bruce Momjian I pokazuje mi još kolona iz tabele. I još jedan koji mi pokazuje ostale kolone. Ovo je prilično složeno, pa sam pokušao da ga predstavim što jednostavnije.

Otključavanje Postgres Lock Managera. Bruce Momjian

Tako smo kreirali tabelu pod nazivom Lockdemo. I tu smo napravili jednu liniju. Ovo je naš uzorak tabele. A mi ćemo kreirati odjeljke samo da bismo vam pokazali primjere brava.

Otključavanje Postgres Lock Managera. Bruce Momjian

Dakle, jedan red, jedna kolona. Prvi tip zaključavanja se zove 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 “lock table”. I očito će se blokirati, tj. u načinu ACCESS SHARE pokrećemo tablicu zaključavanja. A ako pokrenem PSQL u pozadini, onda počinjem drugu sesiju od svoje prve sesije na ovaj način. Odnosno, šta ću ja ovde? Idem na drugu sesiju i kažem joj "pokaži mi prikaz zaključavanja za ovaj zahtjev." I ovdje imam AccessShareLock u ovoj tabeli. To je upravo ono što sam tražio. I kaže da je blok dodijeljen. Veoma jednostavno.

Otključavanje Postgres Lock Managera. Bruce Momjian

Dalje, ako pogledamo drugu kolonu, onda tamo nema ničega. Oni su prazni.

Otključavanje Postgres Lock Managera. Bruce Momjian

A ako pokrenem naredbu "SELECT", onda je ovo implicitni (eksplicitni) način da zatražim AccessShareLock. Otpuštam svoju tabelu i pokrećem upit, a upit vraća više redova. I u jednom od redova vidimo AccessShareLock. Dakle, SELECT poziva AccessShareLock na tabeli. I nije u sukobu ni sa čim jer je zaključavanje niskog nivoa.

Otključavanje Postgres Lock Managera. Bruce Momjian

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

Otključavanje Postgres Lock Managera. Bruce Momjian

A sada kada pogledam upit, vidim 9 AccessShareLocks u tri tabele. Zašto? Tri tabele su istaknute 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 se praktički ne sukobljava s drugima. A sve što radi je da nas jednostavno sprečava da resetujemo tabelu dok je biramo. Ima smisla. Odnosno, ako odaberemo tabelu, ona u tom trenutku nestane, onda je ovo pogrešno, dakle AccessShare je zaključavanje niskog nivoa koje nam govori "ne ispuštajte ovaj sto dok radim". U suštini, 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 reda pojedinačno. Na ovaj način ih niko ne može izbrisati ili promijeniti dok ih mi gledamo.

Otključavanje Postgres Lock Managera. Bruce MomjianDakle, šta radi SHARE LOCK? Vidimo da je ID transakcije 681 za SELECT. I ovo je zanimljivo. Šta se desilo ovde? Prvi put kada vidimo broj je u polju “Zaključaj”. Uzimamo ID transakcije i on kaže da ga blokira u ekskluzivnom načinu. Sve što radi je da piše da imam red koji je tehnički zaključan negdje u tabeli. Ali ne kaže gde tačno. Ovo ćemo detaljnije pogledati 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 kaže da je isključiva. Takođe, ako izbrišete red u ovoj tabeli, to će se desiti, kao što vidite.

Otključavanje Postgres Lock Managera. Bruce Momjian

SHARE EXCLUSIVE je duža brava.

Otključavanje Postgres Lock Managera. Bruce Momjian

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

Otključavanje Postgres Lock Managera. Bruce Momjian

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

Otključavanje Postgres Lock Managera. Bruce Momjian

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

Podrazumevano, SHARE LOCK na tabeli znači da drugi ljudi mogu čitati tabelu, ali je niko ne može menjati. A to je upravo ono što se dešava kada kreirate jedinstveni indeks.

Ako kreiram jedinstveni istovremeno indeks, onda ću imati drugačiji tip zaključavanja jer, kao što se sjećate, korištenje istovremenog indeksa smanjuje zahtjev za zaključavanjem. A ako koristim normalno zaključavanje, normalan indeks, onda ću na taj način spriječiti pisanje u indeks tablice dok se kreira. Ako koristim istovremeno indeks, onda moram koristiti drugu vrstu zaključavanja.

Otključavanje Postgres Lock Managera. Bruce Momjian

DIJELI RED EKSKLUZIVNO – opet se može eksplicitno (eksplicitno) postaviti.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ili možemo kreirati pravilo, tj. uzeti konkretan slučaj u kojem će se ono koristiti.

Otključavanje Postgres Lock Managera. Bruce Momjian

EKSKLUZIVNO zaključavanje znači da niko drugi ne može promijeniti sto.

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 tu niko neće moći pisati. I zaključava ne samo samu tabelu, već i indekse.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovo je druga stranica blokade PRISTUP ISKLJUČIVO, gdje vidimo šta tačno blokira u tabeli. Zaključava pojedinačne redove tabele, što je prilično zanimljivo.

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

Otključavanje Postgres Lock Managera. Bruce Momjian

A sada ćemo proći kroz nekoliko primjera blokiranja. Ovo je najzanimljiviji dio. Pogledaćemo veoma zanimljive slučajeve. I moj cilj u ovoj prezentaciji je da vam pružim bolje razumijevanje šta Postgres zapravo radi kada pokušava da blokira određene stvari. Mislim da je veoma dobar u blokiranju delova.

Pogledajmo neke konkretne primjere.

Otključavanje Postgres Lock Managera. Bruce Momjian

Počećemo sa tabelama i jednim redom u tabeli. Kada nešto ubacim, na tabeli su mi prikazani ExclusiveLock, ID transakcije i ExclusiveLock.

Otključavanje Postgres Lock Managera. Bruce Momjian

Šta se dešava ako ubacim još dva reda? I sada naša tabela ima tri reda. I ubacio sam jedan red i dobio ovo kao izlaz. A ako ubacim još dva reda, šta je tu čudno? Ovdje je čudna stvar jer sam dodao tri reda ovoj tabeli, ali još uvijek imam dva reda u tablici zaključavanja. A ovo je u suštini osnovno ponašanje Postgresa.

Mnogi ljudi misle da ako u bazi podataka zaključate 100 redova, onda ćete morati kreirati 100 zaključanih unosa. Ako blokiram 1 redova odjednom, onda će mi trebati 000 takvih upita. I ako mi treba milion ili milijarda da blokiram. Ali ako ovo uradimo, neće dobro funkcionisati. Ako ste koristili sistem koji kreira blokirajuće unose za svaki pojedinačni red, onda možete vidjeti da je ovo komplikovano. Zato što morate odmah definisati tabelu zaključavanja koja se može preliti, ali Postgres to ne radi.

I ono što je zaista važno kod ovog slajda je da jasno pokazuje da postoji još jedan sistem koji radi unutar MVCC-a koji zaključava pojedinačne redove. Dakle, kada zaključate milijarde redova, Postgres ne kreira milijardu zasebnih naredbi za zaključavanje. A to ima jako dobar učinak na produktivnost.

Otključavanje Postgres Lock Managera. Bruce Momjian

Šta je sa ažuriranjem? Sada ažuriram red i možete vidjeti da je izvršio dvije različite operacije odjednom. Istovremeno je zaključao tabelu, ali je zaključao i indeks. I morao je da zaključa indeks jer postoje jedinstvena ograničenja na ovoj tabeli. I želimo biti sigurni da ga niko ne mijenja, pa ga blokiramo.

Otključavanje Postgres Lock Managera. Bruce Momjian

Šta se dešava ako želim ažurirati dva reda? I vidimo da se i on ponaša na isti način. Radimo duplo više ažuriranja, ali potpuno isti broj linija za zaključavanje.

Ako se pitate kako Postgres to radi, moraćete da poslušate moje govore o MVCC-u da saznate kako Postgres interno označava ove redove koje menja. I Postgres ima način na koji to radi, ali to ne radi na nivou zaključavanja tabele, već na nižem i efikasnijem nivou.

Otključavanje Postgres Lock Managera. Bruce Momjian

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

Otključavanje Postgres Lock Managera. Bruce Momjian

I, na primjer, želim da ubacim 1 redova, a onda ili izbrišem ili dodam 000 redova, pa ti pojedinačni redovi koje dodam ili promijenim, oni se ovdje ne snimaju. Napisane su na nižem nivou unutar same serije. I tokom govora MVCC-a sam o tome detaljno govorio. Ali veoma je važno kada analizirate zaključavanja kako biste bili sigurni da zaključavate na nivou tabele i da ne vidite kako se ovde beleže pojedinačni redovi.

Otključavanje Postgres Lock Managera. Bruce Momjian

Šta je sa eksplicitnim blokiranjem?

Otključavanje Postgres Lock Managera. Bruce Momjian

Ako kliknem na osvježi, imam dva zaključana reda. A ako ih sve odaberem i kliknem na "ažuriraj svugdje", onda i dalje imam dva blokirajuća zapisa.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ne kreiramo zasebne zapise za svaki pojedinačni red. Budući da tada produktivnost opada, može je biti previše. I možemo se naći u neprijatnoj situaciji.

Otključavanje Postgres Lock Managera. Bruce Momjian

I ista stvar, ako dijelimo, možemo sve 30 puta.

Otključavanje Postgres Lock Managera. Bruce Momjian

Vraćamo našu tabelu, brišemo sve, a zatim ponovo ubacujemo jedan red.

Otključavanje Postgres Lock Managera. Bruce Momjian

Još jedno ponašanje koje vidite u Postgresu koje je vrlo dobro poznato i poželjno je da možete izvršiti ažuriranje ili odabir. I to možete učiniti u isto vrijeme. I select ne blokira ažuriranje i ista stvar u suprotnom smjeru. Poručujemo čitaocu da ne blokira pisca, a pisac nije blokirao čitaoca.

Pokazat ću vam primjer ovoga. Sada ću napraviti izbor. Zatim ćemo uraditi INSERT. I onda 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

A ako sada pogledam svoj backend ID, sada je 695.

Otključavanje Postgres Lock Managera. Bruce Momjian

I vidim da se 695 pojavljuje u mojoj tabeli.

Otključavanje Postgres Lock Managera. Bruce Momjian

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

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

I morate poslušati moj govor na 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

Hajde da resetujemo i uradimo još jednu operaciju.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ako pokušate pokrenuti dva ažuriranja istovremeno u istom redu, ona će biti blokirana. I zapamtite, rekao sam da čitač ne blokira pisca, a pisac ne blokira čitaoca, ali jedan pisac blokira drugog pisca. To jest, ne možemo imati dvije osobe da ažuriraju isti red u isto vrijeme. Morate sačekati dok se jedan od njih ne završi.

Otključavanje Postgres Lock Managera. Bruce Momjian

A da bih ovo ilustrovao, pogledaću tabelu Lockdemo. A mi ćemo pogledati 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 da potvrdimo ili otkažemo.

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 u 3. I ako primijetite, gornji se zaključao sam, a to je 699. Ali 3/112 nije odobrio zaključavanje. Kolona Lock_mode kaže šta čeka. Očekuje se 699. A ako pogledate gdje je 699, to je više. I šta je uradila prva sesija? Napravila je ekskluzivnu bravu na svom ID-u transakcije. Ovako to radi Postgres. Blokira svoj ID transakcije. A ako želite da sačekate da neko potvrdi ili otkaže, onda morate da sačekate dok postoji transakcija na čekanju. I zato možemo vidjeti čudnu liniju.

Pogledajmo ponovo. Na lijevoj strani vidimo naš ID obrade. U drugoj koloni vidimo naš ID virtualne transakcije, au trećoj vidimo lock_type. Šta to znači? U suštini ono što piše je da blokira ID transakcije. Ali primijetite da svi redovi na dnu kažu odnos. I tako imate dvije vrste brava na stolu. Postoji zaključavanje odnosa. A tu je i blokada transakcije, gdje sami blokirate, što se upravo dešava u prvom redu ili na samom dnu, gdje je transakcijski ID, gdje čekamo da 699 završi svoj rad.

Videću šta će biti ovde. I ovdje se dvije stvari dešavaju istovremeno. Gledate bravu ID transakcije u prvom redu koja se sama zaključava. I ona se blokira kako bi natjerala ljude da čekaju.

Ako pogledate 6. red, to je isti unos kao i prvi. I stoga je transakcija 699 blokirana. 700 je također samozaključavajući. 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, kao i pomak ovog određenog reda.

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 da vidimo da je ovo serija koju čekam da potvrdim.

Otključavanje Postgres Lock Managera. Bruce Momjian

Nakon što smo to potvrdili i pritisnuli commit, i kada je ažuriranje završeno, ovo je ono što ponovo dobijamo. Transakcija 700 je jedino zaključavanje, ne čeka nikog drugog jer je predano. Jednostavno čeka da se transakcija završi. Kada ponestane 699, više ne čekamo ništa. I sada transakcija 700 kaže da je sve u redu, da ima sva zaključavanja koja su joj potrebna na svim dozvoljenim tablicama.

Otključavanje Postgres Lock Managera. Bruce Momjian

A da bi cijela stvar bila još složenija, kreiramo još jedan pogled, koji će nam ovoga puta pružiti hijerarhiju. Ne očekujem da ćete razumjeti ovaj zahtjev. Ali ovo će nam dati jasniji uvid u ono što se dešava.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovo je rekurzivni pogled koji također ima još jedan odjeljak. A onda sve ponovo spaja. Hajde da iskoristimo ovo.

Otključavanje Postgres Lock Managera. Bruce Momjian

Šta ako uradimo 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

I onda ću promijeniti 4 u 5. I 5 u 6, i 6 u 7. I postrojit ću određeni broj ljudi koji će čekati da se ova 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 prvobitno postavio ovu vrijednost. Šta piše u mojoj rubrici Granted? Imam oznake f. Ovo su moja ažuriranja koja (5, 6, 7) ne mogu biti odobrena jer čekamo da se transakcija ID 702 završi. Tu imamo blokiranje ID-a transakcije. I to rezultira 5 transakcijskih ID zaključavanja.

A ako pogledate 704, 705, tamo još ništa nije napisano, jer oni još ne znaju šta se dešava. Oni jednostavno pišu da nemaju pojma šta se dešava. A oni će samo ići na spavanje jer čekaju da neko završi i da se probudi kada se ukaže prilika za promjenu redova.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovako to izgleda. Jasno je da svi č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 hijerarhija funkcionira. I sada sve postaje jasno. Svi postaju čisti. I zapravo još čekaju.

Otključavanje Postgres Lock Managera. Bruce Momjian

Evo šta se dešava. 702 commits. I sada 703 dobija ovo zaključavanje reda, a onda 704 počinje da čeka da se 703 urezuje. A 705 čeka i ovo. A kada se sve ovo završi, oni se čiste. I želio bih da istaknem da svi stoje u redu. A ovo je vrlo slično situaciji u saobraćajnoj gužvi kada svi čekaju prvi auto. Prvi auto staje i svi se poređaju u dugački red. Zatim se kreće, onda sljedeći auto može krenuti naprijed i dobiti svoj blok, itd.

Otključavanje Postgres Lock Managera. Bruce Momjian

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

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šavamo u ćorsokaku. Siguran sam da Ivan to neće uraditi, ali razumete šta znači da imamo dvoje ljudi koji žele nešto da dobiju i nisu spremni da to daju dok im druga osoba ne da ono što žele. I nema rješenja.

I u suštini, vaša baza podataka to treba da otkrije. A onda trebate izbrisati ili zatvoriti jednu od sesija, jer će u suprotnom ostati tu zauvijek. I vidimo to u bazama podataka, vidimo to u operativnim sistemima. 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 blokada. Stavićemo 50 i 80. U prvom redu ću ažurirati sa 50 na 50. Dobić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 red blokiran, 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 redu dolazi do zastoja. I evo gdje 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 ovo se 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 da odlaže sve. A mi to ne želimo.

Otključavanje Postgres Lock Managera. Bruce Momjian

I Postgres ima načine da primijeti kada se to dogodi. A kada se to dogodi, dobićete ovu grešku. I iz ovoga je jasno da taj i taj proces čeka na SHARE LOCK od drugog procesa, tj. koji je blokiran 711 procesom. I taj proces je čekao da se SHARE LOCK da na taj i takav ID transakcije i bio je blokiran od tog i takvog procesa. Dakle, ovdje postoji ćorsokak.

Otključavanje Postgres Lock Managera. Bruce Momjian

Postoje li trosmjerni zastoji? Moguće je? Da.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ove brojeve unosimo u tabelu. Mijenjamo 40 u 40, radimo blokiranje.

Otključavanje Postgres Lock Managera. Bruce Momjian

Mijenjamo 60 u 61, 80 u 81.

Otključavanje Postgres Lock Managera. Bruce Momjian

I 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 su već tri osobe. Ja hoću nešto od tebe, ovaj hoće nešto od treće osobe, a treći želi nešto od mene. I završimo u trostrukom čekanju jer svi čekamo da druga osoba završi ono što treba da uradi.

Otključavanje Postgres Lock Managera. Bruce Momjian

I Postgres zna u kom redu se to dešava. I tako će vam dati sljedeću poruku, koja pokazuje da imate problem gdje tri ulaza blokiraju jedan drugog. I ovdje nema ograničenja. Ovo može biti slučaj kada 20 unosa blokiraju jedni druge.

Otključavanje Postgres Lock Managera. Bruce Momjian

Sljedeći problem je serijalizabilan.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ako je posebna serializable brava.

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 transakciju učinite iz serijalizirane.

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 pod nazivom SARieadLock, koja je serijska brava i omogućava vam da unesete serijske brojeve.

Otključavanje Postgres Lock Managera. Bruce Momjian

Takođe možete umetnuti jedinstvene indekse.

Otključavanje Postgres Lock Managera. Bruce Momjian

U ovoj tabeli imamo jedinstvene indekse.

Otključavanje Postgres Lock Managera. Bruce Momjian

Dakle, ako stavim broj 2 ovdje, 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 šta će se dogoditi sa 721.

Otključavanje Postgres Lock Managera. Bruce Momjian

A ako izvršimo podtransakciju.

Otključavanje Postgres Lock Managera. Bruce Momjian

Ovdje imamo 723.

Otključavanje Postgres Lock Managera. Bruce Momjian

A ako sačuvamo tačku i zatim je ažuriramo, onda ć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.

Pa šta ja pokušavam da uradim ovde? Pokušavam vam pokazati primjere neobičnih zaključavanja koje biste mogli pronaći: bilo da se radi o bravama koje se mogu serijalizirati ili SAVEPOINT, ovo su različite vrste brava koje će se pojaviti u tabeli 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 tip blokiranja naveden kao savjetodavni. I ovdje piše "savjetodavno" crvenom bojom. I možete istovremeno blokirati ovako sa pg_advisory_unlock.

Otključavanje Postgres Lock Managera. Bruce Momjian

I u zaključku, želio bih da vam pokažem još jednu zapanjujuću stvar. Napravit ću drugi pogled. Ali pridružit ću se pg_locks tablici sa pg_stat_activity tablicom. I zašto to želim da uradim? Zato što će mi to omogućiti da pogledam i vidim sve trenutne sesije i vidim tačno kakve brave čekaju. I ovo je prilično zanimljivo kada sastavite tabelu zaključavanja i tabelu upita.

Otključavanje Postgres Lock Managera. Bruce Momjian

I ovdje kreiramo 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 šta sad vidite ovdje? Ovo su zahtjevi, odnosno vidite cijelu listu zahtjeva koji su navedeni u lijevoj koloni. A onda na desnoj strani možete vidjeti blokade i šta one stvaraju. I može vam biti jasnije, tako da ne morate svaki put da se vraćate na svaku sesiju i vidite da li treba da joj se pridružite ili ne. Oni to rade za nas.

Još jedna značajka koja je vrlo korisna je pg_blocking_pids. Verovatno nikada niste čuli za nju. Šta to ona radi? Omogućava nam da kažemo da za ovu sesiju 11740 koje specifične ID-ove procesa čeka. I vidite da 11740 čeka 724. A 724 je na samom vrhu. A 11306 je vaš ID procesa. U suštini, ova funkcija prolazi kroz vašu tablicu zaključavanja. I znam da je malo komplikovano, ali ti to uspevaš da razumeš. U suštini, ova funkcija prolazi kroz ovu tabelu zaključavanja i pokušava pronaći gdje je ovom ID-u procesa data zaključavanja na koja čeka. I 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 veoma korisno. Ovo smo dodali samo u verziji 9.6, tako da je ova funkcija stara samo 5 godina, ali je vrlo, vrlo korisna. Isto važi i za drugi zahtev. Pokazuje tačno ono što treba da vidimo.

Otključavanje Postgres Lock Managera. Bruce Momjian

To je ono o čemu sam htio razgovarati s tobom. I kao što sam očekivao, potrošili smo svo vrijeme jer je bilo toliko slajdova. I slajdovi su dostupni za preuzimanje. Želeo bih da vam se zahvalim što ste ovde. Siguran sam da ćete uživati ​​u ostatku konferencije, hvala vam puno!

Pitanja:

Na primjer, ako pokušavam ažurirati redove, a druga sesija pokušava izbrisati cijelu tablicu. Koliko sam shvatio, trebalo bi da postoji nešto poput zaključavanja namere. Postoji li tako nešto u Postgresu?

Otključavanje Postgres Lock Managera. Bruce Momjian

Vratimo se na sam početak. Možda se sećate da kada bilo šta radite, na primer kada uradite SELECT, izdajemo AccessShareLock. I to sprečava ispuštanje tabele. Dakle, ako vi, na primjer, želite ažurirati red u tabeli ili izbrisati red, onda neko ne može izbrisati cijelu tabelu u isto vrijeme jer držite ovaj AccessShareLock preko cijele tablice i iznad reda. A kada završite, oni ga mogu izbrisati. Ali dok tamo nešto direktno promijenite, oni to neće moći.

Uradimo to ponovo. Prijeđimo na primjer brisanja. I vidite kako postoji ekskluzivna brava na redu iznad cijele tablice.

Ovo će izgledati kao ekskluzivno zaključavanje, zar ne?

Da, izgleda tako. Razumijem o čemu pričaš. Kažete da ako uradim SELECT onda imam ShareExclusive i onda ga učinim ekskluzivnim za redove, da li to postaje problem? Ali iznenađujuće, to ne predstavlja problem. Ovo izgleda kao povećanje stepena zaključavanja, ali u suštini imam zaključavanje koje sprečava brisanje. A sada, kada ovu bravu učinim snažnijom, ona i dalje sprječava brisanje. Dakle, nije da idem gore. Odnosno, sprečio je da se to desi i kada je bio na nižem nivou, tako da kada mu podignem nivo i dalje sprečava brisanje tabele.

Razumijem o čemu pričaš. Ne postoji slučaj eskalacije zaključavanja, gdje pokušavate odustati od jedne brave da biste uveli jaču. Ovdje samo povećava ovu prevenciju u cijelosti, tako da ne uzrokuje nikakav sukob. Ali to je dobro pitanje. Hvala vam puno što ste ovo pitali!

Šta treba da uradimo da bismo izbegli zastoj kada imamo mnogo sesija, veliki broj korisnika?

Postgres automatski uočava situacije zastoja. I automatski će izbrisati jednu od sesija. Jedini način da se izbjegne mrtvo blokiranje je blokiranje ljudi istim redoslijedom. Dakle, kada pogledate svoju aplikaciju, često je razlog zastoja... Zamislimo da želim blokirati dvije različite stvari. Jedna aplikacija zaključava tabelu 1, a druga aplikacija zaključava 2, a zatim tabelu 1. A najlakši način da izbegnete zastoje je da pogledate svoju aplikaciju i pokušate da se uverite da se zaključavanje dešava istim redosledom u svim aplikacijama. I to obično eliminira 80% problema, jer sve vrste ljudi pišu ove aplikacije. A ako ih blokirate istim redoslijedom, onda nećete naići na situaciju zastoja.

Hvala vam puno na vašem nastupu! Govorili ste o punom vakuumu i, ako sam dobro razumio, puni vakuum iskrivljuje redoslijed zapisa u odvojenim skladištima, tako da oni zadržavaju trenutne zapise nepromijenjenim. Zašto potpuni vakuum uzima ekskluzivni pristup zaključavanju i zašto je u sukobu s operacijama pisanja?

To je dobro pitanje. Razlog je taj što vakum pun zauzima sto. I mi u suštini stvaramo novu verziju tabele. I sto će biti nov. Ispostavilo se da će ovo biti potpuno nova verzija tabele. A problem je što kada to radimo, ne želimo da ljudi to čitaju jer nam je potrebno da vide novu tabelu. I tako se ovo povezuje sa prethodnim pitanjem. Kad bismo mogli čitati u isto vrijeme, ne bismo ga mogli pomjeriti i usmjeriti ljude na novi sto. Trebalo bi da sačekamo da svi završe čitanje ove tabele, tako da je to u suštini situacija isključivanja zaključavanja.
Samo kažemo da zaključavamo od početka jer znamo da će nam na samom kraju trebati ekskluzivno zaključavanje kako bismo sve prebacili na novu kopiju. Tako da to možemo potencijalno riješiti. I mi to radimo na ovaj način uz istovremeno indeksiranje. Ali ovo je mnogo teže uraditi. I ovo se u velikoj mjeri odnosi na vaše prethodno pitanje o isključivanju brave.

Da li je moguće dodati timeout zaključavanja u Postgres? U Oracle-u mogu, na primjer, napisati "odaberite za ažuriranje" i pričekati 50 sekundi prije ažuriranja. Bilo je dobro za aplikaciju. Ali u Postgresu, moram to učiniti odmah i ne čekati uopće, ili čekati neko vrijeme.

Da, možete odabrati vremensko ograničenje na vašim bravama, na vašim bravama. Također možete izdati naredbu no way, koja će... ako ne možete odmah dobiti zaključavanje. Stoga, ili tajmout zaključavanja ili nešto drugo što će vam omogućiti da to učinite. Ovo se ne radi na sintaksičkom nivou. Ovo se radi kao varijabla na serveru. Ponekad se ovo 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?

I ovo je odlično pitanje. Usput, ne razumijem zašto Postgres to radi. Ali kada je 703 stvoren, očekivao je 702. A kada se pojave 704 i 705, čini se da ne znaju šta očekuju jer tamo još nema ničega. A Postgres to radi na ovaj način: kada ne možete da zaključate, piše „Koja je svrha da vas obrađujemo?“, jer već čekate nekoga. Tako da ćemo ga pustiti da visi u zraku, neće ga uopće ažurirati. Ali šta se ovde dogodilo? Čim je 702 završio proces i 703 primio svoje zaključavanje, sistem se vratio nazad. I rekla je da sada imamo dvoje ljudi koji čekaju. A onda hajde da ih ažuriramo 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 ovo nije termin u ruskom jeziku. To je kada svi čekaju jedan dvorac, čak i ako ima 20 vlasti koje čekaju zamak. I odjednom se svi probude u isto vrijeme. I svi počinju da pokušavaju da reaguju. Ali sistem je napravio tako da svi čekaju 703. Jer svi čekaju, a mi ćemo ih odmah sve postrojiti. A ako se pojavi bilo koji drugi novi zahtjev koji je generiran nakon ovoga, na primjer, 707, onda će opet biti praznina.

I čini mi se da je to urađeno da bismo mogli reći da u ovoj fazi 702 čeka 703, a svi oni koji dođu nakon toga neće imati nikakav upis u ovo polje. Ali čim prvi konobar ode, svi oni koji su u tom trenutku čekali prije ažuriranja dobijaju isti token. I zato mislim da je ovo urađeno da bismo mogli da obradimo po redu kako bi oni bili kako treba.

Uvek sam na ovo gledao kao na prilično čudan fenomen. Jer ovdje ih, na primjer, uopće ne navodimo. Ali čini mi se da svaki put kada damo novu bravu, pogledamo sve one koji su u procesu čekanja. Onda ih sve poređamo. A onda svaki novi koji dođe dolazi u red tek kada je sljedeća osoba završila obradu. Vrlo dobro pitanje. Hvala vam puno na vašem pitanju!

Čini mi se da je mnogo 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 jednog ili drugog. Ali šta se dešava u sistemu? Možete vidjeti kako je 703 na samom vrhu blokirao vlastiti ID transakcije. Ovako funkcionira Postgres. A 703 je blokiran vlastitim ID-om transakcije, pa ako neko želi čekati, onda će čekati 703. I, u suštini, 703 se završava. I tek nakon njegovog završetka budi se jedan od procesa. I ne znamo šta će tačno ovaj proces biti. Zatim sve obrađujemo postepeno. Ali nije jasno koji se proces prvi budi, jer bi to mogao biti bilo koji od ovih procesa. U suštini, imali smo planer koji je rekao da sada možemo probuditi bilo koji od ovih procesa. Samo nasumično biramo jednu. Dakle, obojicu treba zabilježiti jer možemo probuditi bilo koju od njih.

A problem je što imamo CP-beskonačnost. I stoga, vrlo je vjerovatno da ćemo kasnije probuditi. A ako, na primjer, probudimo kasniji, čekat ćemo onoga koji je upravo primio blok, tako da ne određujemo ko će se tačno probuditi prvi. Jednostavno stvorimo takvu situaciju, a sistem će ih probuditi nasumičnim redoslijedom.

Postoje članci o bravama Egora Rogova. Vidite, i oni su zanimljivi i korisni. Tema je, naravno, užasno složena. Hvala puno, Bruce!

izvor: www.habr.com

Dodajte komentar