Oplåsning af Postgres Lock Manager. Bruce Momjian

Transskription af Bruce Momjians foredrag fra 2020 "Unlocking the Postgres Lock Manager".

Oplåsning af Postgres Lock Manager. Bruce Momjian

(Bemærk: Du kan få alle SQL-forespørgsler fra slides på dette link: http://momjian.us/main/writings/pgsql/locking.sql)

Hej! Det er dejligt at være her i Rusland igen. Jeg er ked af, at jeg ikke kunne komme sidste år, men i år har Ivan og jeg store planer. Jeg håber at være her meget oftere. Jeg elsker at komme til Rusland. Jeg vil besøge Tyumen, Tver. Jeg er meget glad for, at jeg vil være i stand til at besøge disse byer.

Mit navn er Bruce Momjian. Jeg arbejder hos EnterpriseDB og har arbejdet med Postgres i over 23 år. Jeg bor i Philadelphia, USA. Jeg rejser omkring 90 dage om året. Og jeg deltager i omkring 40 konferencer. Min Internet side, som indeholder de slides, som jeg vil vise dig nu. Derfor kan du efter konferencen downloade dem fra min personlige side. Den indeholder også omkring 30 oplæg. Og der er også videoer og et stort antal blogindlæg, mere end 500. Dette er en ret informativ ressource. Og hvis du er interesseret i dette materiale, så inviterer jeg dig til at bruge det.

Jeg plejede at være lærer, professor, før jeg begyndte at arbejde med Postgres. Og jeg er meget glad for, at jeg nu kan fortælle dig, hvad jeg vil fortælle dig. Dette er et af mine mest interessante oplæg. Og denne præsentation indeholder 110 slides. Vi vil begynde at tale med simple ting, og i slutningen af ​​rapporten vil det blive mere og mere kompliceret, og det vil blive ret kompliceret.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Det er en ret ubehagelig samtale. Blokering er ikke det mest populære emne. Vi vil have det til at forsvinde et sted. Det er som at gå til tandlægen.

Oplåsning af Postgres Lock Manager. Bruce Momjian

  1. Låsning er et problem for mange mennesker, der arbejder på databaser og har flere processer kørende på samme tid. De har brug for blokering. Det vil sige, at jeg i dag vil give dig grundlæggende viden om blokering.
  2. Transaktions-id'er. Dette er en ret kedelig del af præsentationen, men de skal forstås.
  3. Dernæst vil vi tale om typerne af blokering. Det er en ret mekanisk del.
  4. Og så vil vi give nogle eksempler på blokering. Og det vil være ret svært at forstå.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Lad os tale om blokering.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Vores terminologi er ret kompliceret. Hvor mange af jer ved, hvor denne passage kommer fra? To personer. Det er fra et spil kaldet Colossal Cave Adventure. Det var et tekstbaseret computerspil i 80'erne, tror jeg. Der var det nødvendigt at gå ind i hulen, ind i labyrinten og teksten ændrede sig, men indholdet var nogenlunde det samme hver gang. Det er sådan jeg husker dette spil.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og her ser vi navnet på de låse, der kom til os fra Oracle. Vi bruger dem.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Her ser vi udtryk, der forvirrer mig. For eksempel DEL OPDATERING ECXLUSIVE. Næste DEL RAW ECXLUSIVE. Helt ærligt er disse navne ikke særlig klare. Vi vil prøve at overveje dem mere detaljeret. Nogle indeholder ordet "dele", som betyder at adskille. Nogle indeholder ordet "eksklusiv" - eksklusiv. Nogle indeholder begge disse ord. Jeg vil gerne starte med, hvordan disse låse fungerer.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og ordet "adgang" er også meget vigtigt. Og ordene "række" - en linje. Det vil sige adgangsfordeling, rækkefordeling.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Et andet problem, der skal forstås i Postgres, som jeg desværre ikke kan komme ind på i mit foredrag, er MVCC. Jeg har en separat præsentation om dette emne på min hjemmeside. Og hvis du synes denne præsentation er svær, så er MVCC nok min sværeste. Og hvis du er interesseret, kan du se det på siden. Du kan se videoen.

Oplåsning af Postgres Lock Manager. Bruce Momjian

En anden ting, vi skal forstå, er transaktions-id'er. Mange transaktioner kan ikke fungere uden unikke identifikatorer. Og her har vi en forklaring på, hvad en transaktion er. Postgres har to transaktionsnummereringssystemer. Jeg ved godt, at det ikke er en særlig køn løsning.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Husk også, at slides vil være ret svære at læse, så det, der er fremhævet med rødt, er det, du skal være opmærksom på.

Oplåsning af Postgres Lock Manager. Bruce Momjian

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

Vi ser. Transaktionsnummeret er fremhævet med rødt. Her er SELECT pg_back-funktionen vist. Det returnerer min transaktion og id'et for denne transaktion.

En ting mere, hvis du kan lide denne præsentation og vil køre den i din database, så kan du følge dette link fremhævet i pink og downloade SQL'en til denne præsentation. Og du kan bare køre det i din PSQL, og hele præsentationen vil være på din skærm på ingen tid. Den vil ikke indeholde blomster, men vi kan i det mindste se den.

Oplåsning af Postgres Lock Manager. Bruce Momjian

I dette tilfælde ser vi transaktions-id'et. Dette er det nummer, vi tildelte hende. Og der er en anden type transaktions-id i Postgres kaldet virtuel transaktions-id

Og det skal vi forstå. Dette er meget vigtigt, ellers vil vi ikke kunne forstå låsning i Postgres.

Et virtuelt transaktions-id er et transaktions-id, der ikke indeholder konstante værdier. For eksempel, hvis jeg kører en SELECT-kommando, så vil jeg højst sandsynligt ikke ændre databasen, jeg vil ikke låse noget. Så når vi kører en simpel SELECT, giver vi ikke transaktionen et permanent ID. Vi giver hende kun et virtuelt ID der.

Og dette forbedrer ydeevnen af ​​Postgres, forbedrer muligheden for at rydde op, så det virtuelle transaktions-id består af to numre. Det første tal før skråstreg er backend-id'et. Og til højre ser vi bare en tæller.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Derfor, hvis jeg kører en anmodning, står der, at backend-id'et er 2.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og hvis jeg kører en række sådanne transaktioner, så ser vi, at tælleren øges, hver gang jeg kører forespørgslen. For eksempel når jeg kører forespørgsel 2/10, 2/11, 2/12 osv.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Husk, at der er to kolonner her. Til venstre ser vi det virtuelle transaktions-id - 2/12. Og til højre har vi et permanent transaktions-id. Og dette felt er tomt. Og denne transaktion ændrer ikke databasen. Derfor tildeler jeg ikke et permanent transaktions-id til det.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Så snart jeg kører analysekommandoen ((ANALYSE)), giver den samme forespørgsel mig et permanent transaktions-id. Se hvordan vi har ændret os. Tidligere havde jeg ikke dette ID, nu har jeg det.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Så her er endnu en anmodning, endnu en transaktion. Det virtuelle transaktionsnummer er 2/13. Og hvis jeg beder om et permanent transaktions-id, så får jeg det, når jeg kører anmodningen.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Så en gang til. Vi har et virtuelt transaktions-id og et permanent transaktions-id. Bare tag dette punkt for at forstå Postgres adfærd.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Vi går videre til tredje afsnit. Her vil vi blot gå gennem de forskellige typer af låse i Postgres. Det er ikke særlig interessant. Det sidste afsnit bliver meget mere interessant. Men vi skal overveje de grundlæggende ting, for ellers forstår vi ikke, hvad der så skal ske.

Vi vil gennemgå dette afsnit, vi vil se på hver type blokering. Og jeg vil vise dig eksempler på, hvordan de er installeret, hvordan de virker, vise dig nogle forespørgsler, som du kan bruge til at se, hvordan blokering fungerer i Postgres.

Oplåsning af Postgres Lock Manager. Bruce Momjian

For at oprette en forespørgsel og se, hvad der foregår i Postgres, skal vi sende forespørgslen til systemvisningen. I dette tilfælde er pg_lock fremhævet med rødt. pg_lock er en systemtabel, der fortæller os, hvilke låse der i øjeblikket er i brug i Postgres.

Det er dog meget svært for mig at vise dig pg_lock i sig selv, fordi det er ret kompliceret. Så jeg oprettede en visning, der viser pg_locks. Og det gør også noget arbejde for mig, der gør det muligt for mig at forstå bedre. Det vil sige, at det udelukker mine låse, min egen session osv. Det er bare standard SQL, og det giver dig mulighed for bedre at vise, hvad der foregår.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Et andet problem er, at denne visning er meget bred, så jeg er nødt til at oprette en anden - lockview2.

Oplåsning af Postgres Lock Manager. Bruce Momjian Og det viser mig flere kolonner fra tabellen. Og en anden, der viser mig resten af ​​spalterne. Dette er ret kompliceret, så jeg forsøgte at præsentere det så enkelt som muligt.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Så vi har lavet en tabel kaldet Lockdemo. Og vi lavede en linje der. Dette er vores eksempeltabel. Og vi vil oprette sektioner bare for at vise dig eksempler på blokering.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Altså en række, en kolonne. Den første type lås kaldes ADGANGSDEL. Dette er den mindst restriktive blokering. Det betyder, at den praktisk talt ikke er i konflikt med andre låse.

Og hvis vi eksplicit vil definere en lås, kører vi kommandoen "lås tabel". Og det vil eksplicit blokere, dvs. i ACCESS SHARE-tilstanden kører vi låsetabellen. Og hvis jeg starter PSQL i baggrunden, så starter jeg den anden session fra min første session på denne måde. Det vil sige, hvad skal jeg gøre her? Jeg går til en anden session og fortæller den at "vis mig låsevisningen for denne anmodning". Og her har jeg en AccessShareLock på dette bord. Dette er lige hvad jeg bad om. Og han siger, at låsen er blevet tildelt. Meget simpelt.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Yderligere, hvis vi ser på den anden kolonne, så er der intet der. De er tomme.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og hvis jeg kører kommandoen "SELECT", så er dette den implicitte (eksplicitte) måde at anmode om AccessShareLock på. Så jeg frigiver min tabel og kører en forespørgsel, og forespørgslen returnerer flere rækker. Og i en af ​​linjerne ser vi AccessShareLock. Så SELECT kalder AccessShareLock på bordet. Og det er ikke i konflikt med næsten hvad som helst, for det er en lås på lavt niveau.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Hvad hvis jeg kører en SELECT, og jeg har tre forskellige tabeller? Tidligere kørte jeg kun én tabel, nu kører jeg tre: pg_class, pg_namespace og pg_attribute.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og nu, når jeg ser på forespørgslen, ser jeg 9 AccessShareLocks i XNUMX tabeller. Hvorfor? Tre tabeller er fremhævet med blåt: pg_attribute, pg_class, pg_namespace. Men du kan også se, at alle indekser, der er defineret gennem disse tabeller, også har AccessShareLock.

Og dette er en blokering, der praktisk talt ikke er i konflikt med andre. Og alt det gør er bare at forhindre os i at tabe bordet, mens vi vælger det. Det giver mening. Det vil sige, at hvis vi vælger en tabel, forsvinder den i det øjeblik, så er dette forkert, derfor AccessShare er en lås på lavt niveau, der fortæller os "slet ikke denne tabel, mens jeg arbejder". Dybest set er det alt, hun gør.

Oplåsning af Postgres Lock Manager. Bruce Momjian

ROW SHARE - Denne lås er lidt anderledes.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Lad os tage et eksempel. SELECT ROW SHARE måde at låse hver række individuelt. På den måde kan ingen slette dem eller ændre dem, mens vi ser dem.

Oplåsning af Postgres Lock Manager. Bruce MomjianSå hvad gør SHARE LOCK? Vi ser, at transaktions-id'et er 681 for SELECT. Og det er interessant. Hvad skete der her? For første gang ser vi nummeret i feltet "Lås". Vi tager transaktions-id'et, og han siger, at han blokerer det i eksklusiv tilstand. Det eneste den gør er, at den siger, at jeg har en række, der teknisk set er låst et sted i tabellen. Men han siger ikke præcist hvor. Vi vil se nærmere på dette lidt senere.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Her siger vi, at låsen bruges af os.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Så en eksklusiv lås siger eksplicit (eksplicit) at den er eksklusiv. Og også hvis du sletter en række i denne tabel, er det, hvad der sker, som du kan se.

Oplåsning af Postgres Lock Manager. Bruce Momjian

SHARE EXCLUSIVE er en længere lås.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Dette er (ANALYSER) analysatorkommandoen, der skal bruges.

Oplåsning af Postgres Lock Manager. Bruce Momjian

DEL LÅS - Du kan udtrykkeligt låse i deletilstand.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Du kan også oprette et unikt indeks. Og der kan du se SHARE LOCK, som er en del af dem. Og den låser bordet og sætter en SHARE LOCK-lås på det.

Standard SHARE LOCK på et bord betyder, at andre personer kan læse tabellen, men ingen kan ændre den. Og det er præcis, hvad der sker, når du opretter et unikt indeks.

Hvis jeg opretter et unikt samtidig indeks, så vil jeg have en anden type lås, fordi husk, at brug af samtidige indekser reducerer låsekravet. Og hvis jeg bruger en normal lås, et normalt indeks, så forhindrer jeg således at skrive til indekset i tabellen under oprettelsen. Hvis jeg bruger et samtidig indeks, skal jeg bruge en anden type lås.

Oplåsning af Postgres Lock Manager. Bruce Momjian

DEL RÆKKE EKSKLUSIVT - igen, det kan indstilles eksplicit (eksplicit).

Oplåsning af Postgres Lock Manager. Bruce Momjian

Eller vi kan oprette en regel, det vil sige, tage et bestemt tilfælde, hvor det vil blive brugt.

Oplåsning af Postgres Lock Manager. Bruce Momjian

EKSKLUSIV lås betyder, at ingen andre kan ændre bordet.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Her ser vi forskellige typer låse.

Oplåsning af Postgres Lock Manager. Bruce Momjian

ACCESS EXCLUSIVE er for eksempel en låsekommando. For eksempel, hvis du gør det CLUSTER table, så vil det betyde, at ingen vil kunne skrive der. Og det låser ikke kun selve bordet, men også indekserne.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Dette er den anden side af ACCESS EXCLUSIVE-låsen, hvor vi ser specifikt, hvad den låser i tabellen. Den låser individuelle tabelrækker, hvilket er interessant nok.

Det er alle de grundlæggende oplysninger, jeg ønskede at give. Vi talte om låse, om transaktions-id'er, vi talte om virtuelle transaktions-id'er, om permanente transaktions-id'er.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og nu vil vi gennemgå de blokerende eksempler. Dette er den mest interessante del. Vi vil se meget interessante cases. Og mit mål i denne præsentation er at give dig en bedre idé om, hvad Postgres rent faktisk gør, når det forsøger at blokere ting. Det forekommer mig, at han er meget god til at blokere enkelte dele.

Lad os se på nogle specifikke eksempler.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Vi starter med tabeller og en række pr. tabel. Når jeg indsætter noget, får jeg ExclusiveLock, Transaction ID og ExclusiveLock på bordet.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Hvad sker der, hvis jeg indsætter to rækker mere? Og nu har vores tabel tre rækker. Og jeg indsatte en række og fik denne som et output. Og hvis jeg indsætter to rækker mere, hvad er så mærkeligt her? Der er en særhed her, fordi jeg har tilføjet tre rækker til denne tabel, men jeg har stadig to rækker i låsetabellen. Og dette er faktisk Postgres' grundlæggende adfærd.

Mange mennesker tror, ​​at hvis du låser 100 rækker i en database, så bliver du nødt til at oprette 100 låseposter. Hvis jeg blokerer 1 rækker på én gang, skal jeg bruge 000 sådanne anmodninger. Og om jeg skal bruge en million eller en milliard for at blokere. Men hvis vi gør dette, vil det ikke fungere særlig godt. Hvis du har brugt et system, der opretter blokeringsposter for hver enkelt række, så kan du se, at dette er kompliceret. For du skal definere låsebordet med det samme, som kan løbe over, men det gør Postgres ikke.

Og det er meget vigtigt på dette slide, at det tydeligt demonstrerer, at der er et andet system, der fungerer inde i MVCC, som blokerer individuelle linjer. Så når du låser milliarder af rækker, opretter Postgres ikke en milliard separate låseinstruktioner. Og det er meget godt for ydeevnen.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Hvad med en opdatering? Jeg er ved at opdatere serien nu, og du kan se, at den har udført to forskellige operationer på én gang. Det låste bordet på samme tid, men det låste også indekset. Og han var nødt til at låse indekset, fordi der er unikke begrænsninger på det bord. Og vi vil sikre os, at ingen ændrer det, så vi blokerer det.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Hvad sker der, hvis jeg vil opdatere to rækker? Og vi ser, at han opfører sig på samme måde. Vi laver dobbelt så mange opdateringer, men præcis det samme antal blokeringslinjer.

Hvis du undrer dig over, hvordan Postgres gør dette, bør du lytte til mine foredrag om MVCC for at finde ud af, hvordan Postgres internt markerer disse linjer, som det ændrer. Og Postgres har en måde at gøre det på, men det gør det ikke på bordlåsningsniveau, det gør det på et lavere og mere effektivt niveau.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Hvad hvis jeg vil slette noget? Hvis jeg for eksempel sletter en række, og jeg stadig har mine to indgange ved låsen, og selvom jeg vil slette dem alle, er de der stadig.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og for eksempel vil jeg indsætte 1 linjer, og så enten slette eller tilføje 000 linjer, så bliver de enkelte linjer, som jeg tilføjer eller ændrer, de er ikke optaget her. De er skrevet på et lavere niveau i selve rækken. Og under MVCC-talen talte jeg om det i detaljer. Men det er meget vigtigt, når du analyserer låse, at sikre dig, at du har en lås på tabelniveau, og at du ikke kan se, hvordan individuelle rækker bliver skrevet her.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Hvad med eksplicit blokering?

Oplåsning af Postgres Lock Manager. Bruce Momjian

Hvis jeg klikker på "opdater" så har jeg to rækker låst. Og hvis jeg vælger dem alle og klikker på "opdater overalt", så har jeg stadig to låseposter.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Vi opretter ikke separate poster for hver enkelt række. For så falder ydelsen, kan der være for meget af det. Og vi kan komme i en ubehagelig situation.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og det samme, hvis vi gør det delt, kan vi gøre alt 30 gange.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Vi gendanner vores tabel, sletter alt og indsætter derefter en række igen.

Oplåsning af Postgres Lock Manager. Bruce Momjian

En anden form for adfærd, du ser i Postgres, som er meget kendt og ønsket adfærd, er, at du kan lave en opdatering eller et udvalg. Og du kan gøre det på samme tid. Og select blokerer ikke for opdatering og det samme i den modsatte retning. Vi fortæller læseren om ikke at blokere forfatteren, og forfatteren har ikke blokeret læseren.

Jeg vil vise dig et eksempel på dette. Jeg vil træffe et valg nu. Så laver vi et INDSÆT. Og så kan du se - 694. Du kan se ID'et for transaktionen, der lavede denne indsættelse. Og sådan fungerer det.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og hvis jeg nu ser på mit backend ID, er det blevet til - 695.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og jeg kan se, at 695 dukker op i min tabel.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og hvis jeg opdaterer her sådan, så får jeg en anden sag. I dette tilfælde er 695 en eksklusiv lås, og opdatering har samme adfærd, men der er ingen konflikt mellem dem, hvilket er ret usædvanligt.

Og du kan bemærke, at på toppen er ShareLock og på bunden er ExclusiveLock. Og begge transaktioner lykkedes.

Og du skal lytte til mit foredrag på MVCC for at forstå, hvordan dette sker. Men dette er en illustration af det faktum, at du kan gøre det på samme tid, dvs. lave SELECT og UPDATE på samme tid.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Lad os nulstille og udføre en handling igen.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Hvis du forsøger at køre to opdateringer på samme tid på samme række, vil det blokere. Og husk, jeg sagde, at læseren ikke blokerer forfatteren, men forfatteren af ​​læseren, men en forfatter blokerer en anden forfatter. Det vil sige, at vi ikke kan have to personer til at opdatere den samme række på samme tid. Du skal vente, indtil en af ​​dem er færdig.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og for at illustrere dette, vil jeg se på Lockdemo-tabellen. Og vi ser på en række. For transaktion 698.

Vi har opgraderet den til 2. 699 er den første opdatering. Og det lykkedes, eller det er i en afventende transaktion og venter på, at vi forpligter eller annullerer.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Men se på noget andet - 2/51 er vores første transaktion, vores første session. 3/112 er den anden anmodning, der kom fra toppen og ændrede den værdi til 3. Og hvis du bemærker, har den øverste låst sig selv, hvilket er 699. Men 3/112 gav ikke en lås. Kolonnen Lock_mode siger, at den venter. Han forventer 699. Og hvis du ser hvor 699 er, er han højere. Og hvad gjorde den første session? Hun oprettede en eksklusiv lås på sit eget transaktions-id. Sådan gør Postgres det. Det blokerer sit eget transaktions-id. Og hvis du vil vente på, at nogen forpligter sig eller annullerer, så skal du vente, mens der er en afventende transaktion. Og så kan vi se en mærkelig streg.

Lad os se igen. Til venstre ser vi vores behandlings-id. I den anden kolonne ser vi vores virtuelle transaktions-id, og i den tredje ser vi lock_type. Hvad betyder det? Faktisk siger hun, at hun blokerer transaktions-id'et. Men bemærk at i alle rækkerne nederst er skrevet relation. Og så har du to slags låse på bordet. Der er en relationslås. Og der er også en transaktions-id-lås, hvor du låser på vores egen, det er præcis, hvad der sker på den første række eller helt nederst, hvor transaktions-id'et er, hvor vi forventer, at 699 afslutter sin operation.

Jeg ser, hvad der sker her. Og her sker der to ting på samme tid. Du ser på transaktions-id-låsen i den første række, som låser sig selv. Og hun blokerer sig selv for at få folk til at vente.

Hvis du ser på den 6. linje, er det den samme indgang som den første. Så transaktion 699 er blokeret. 700 er også selvlåsende. Og så i nederste række vil du se, at vi venter på, at 699 fuldfører sin operation.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og i lock_type, tuple ser du tal.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Du kan se det er 0/10. Og det er sidetallet, og også forskydningen af ​​den pågældende række.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og du ser, hvad der bliver 0/11, når vi opdaterer.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Men faktisk er det 0/10, for der er en forventning til denne operation. Vi har mulighed for at se, at det er den række, jeg venter på at få bekræftet.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Når vi har bekræftet det og trykket på commit, og når opdateringen er færdig, får vi det igen. Transaktion 700 er den eneste lås, den venter ikke på nogen anden, fordi den blev begået. Den venter bare på, at transaktionen er fuldført. Når 699 slutter, venter vi ikke på andet. Og nu siger transaktion 700, at alt er i orden, at det har alle de låse, det skal bruge i alle tilladte borde.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og for at komplicere det hele yderligere, skaber vi et andet syn, som denne gang vil give os et hierarki. Jeg forventer ikke, at du forstår denne anmodning. Men det vil give os et klarere overblik over, hvad der foregår.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Dette er et rekursivt synspunkt, der også har et afsnit mere. Og så bringer det alt sammen igen. Lad os bruge dette.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Hvad hvis vi laver tre samtidige opdateringer og siger, at rækken nu er tre. Og vi ændrer 3 til 4.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og her ser vi 4. Og transaktions-ID 702.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og så bytter jeg 4 med 5. Og 5 med 6 og 6 med 7. Og jeg stiller et antal personer i kø for at vente på, at denne ene transaktion er fuldført.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og alt bliver klart. Hvad er den første række? Dette er 702. Dette er transaktions-id'et, der oprindeligt indstillede denne værdi. Hvad har jeg i kolonnen Granted? Jeg har mærker f. Dette er mine opdateringer, der (5, 6, 7) ikke kan godkendes, fordi vi venter på, at transaktions-ID 702 udløber. Der har vi en transaktions-id-lås. Og det viser sig 5 transaktionslåse ID.

Og hvis man ser på 704, på 705, er der ikke skrevet noget der endnu, for de ved ikke, hvad der foregår endnu. De skriver bare, at de ikke aner, hvad der foregår. Og de vil bare gå i seng, for de venter på, at nogen er færdige, og de bliver vækket, når det er muligt at skifte række.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Sådan ser det ud. Det er tydeligt, at de alle venter på 12. linje.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Det er, hvad vi så her. Her er 0/12.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Så når den første transaktion er godkendt, kan du se, hvordan hierarkiet fungerer her. Og nu er det hele klart. De bliver alle rene. Og de venter faktisk stadig.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Her er hvad der sker. 702 er forpligtet. Og nu får 703 denne rækkelås, og så begynder 704 at vente på, at 703 begår. Og det venter 705 også på. Og når alt dette er gennemført, rydder de selv op. Og jeg vil gerne pointere, at alle stiller op. Og det minder meget om trafikpropsituationen, hvor alle venter på den første bil. Den første bil er stoppet, og alle stiller sig op i en lang række. Så bevæger den sig, så kan den næste bil komme frem og få sin blok, og så videre.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og hvis det forekom dig ikke svært nok, så vil vi nu tale med dig om dødvande. Jeg ved ikke hvem af jer der har oplevet dem. Dette er et ret almindeligt problem i databasesystemer. Men dødvande er, når en session venter på en anden session for at gøre noget. Og i det øjeblik venter endnu en session på den første session for at gøre noget.

Og for eksempel, hvis Ivan siger: "Giv mig noget," og jeg siger: "Nej, jeg vil kun give det til dig, hvis du giver mig noget andet." Og han siger: "Nej, jeg vil ikke give det til dig, hvis du ikke giver det til mig." Og vi ender i en fastlåst situation. Jeg er sikker på, at Ivan ikke vil gøre det, men du forstår, at vi har to personer, der ønsker noget, og de er ikke klar til at give det væk, før den anden person giver dem, hvad de vil have. Og der er ingen løsning.

Og faktisk skal din database opdage dette. Og så skal du slette eller lukke en af ​​sessionerne, for ellers forbliver de der for altid. Og vi ser det i databaser, vi ser det i operativsystemer. Og alle steder, hvor vi har parallelle processer, kan det ske.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og vi vil sætte to dødvande nu. Vi sætter 50 og 80. I første række vil jeg opdatere fra 50 til 50. Jeg får transaktionsnummer 710.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og så ændrer jeg 80 til 81 og 50 til 51.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og her er, hvordan det kommer til at se ud. Så 710 har en rækkelås, og 711 venter på bekræftelse. Vi så det, da vi opdaterede. 710 - er ejer af vores serie. Og 711 venter på, at 710 fuldfører transaktionen.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og der står endda på hvilken række vi har dødvande. Og det er her, det begynder at blive mærkeligt.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Nu opdaterer vi 80 til 80.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og det er her dødvande begynder. 710 venter på svar fra 711, og 711 venter på 710. Og det ender ikke godt. Og der er ingen vej ud af dette. Og de vil forvente et svar fra hinanden.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og det begynder bare at forsinke alt. Og det ønsker vi ikke.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og Postgres har måder at lægge mærke til, når dette sker. Og når det sker, får du denne fejl. Og ud fra dette er det klart, at sådan og sådan en proces venter på en SHARE LOCK fra en anden proces, dvs., som er blokeret af 711-processen. Og den proces ventede på, at en DELINGSLÅS skulle blive givet til sådan og sådan et transaktions-id og blive blokeret af sådan og sådan en proces. Derfor er der en situation med død blokering.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Er der tre-vejs dødvande? Er det muligt? Ja.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Vi kører disse tal ind i tabellen. Vi ændrer 40 til 40, vi laver en lås.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Skift 60 til 61, 80 til 81.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og så skifter vi 80 og så bom!

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og 714 venter nu på 715. 716 venter på 715. Og der er ikke noget at gøre ved det.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Der er ikke længere to personer, der er allerede tre personer. Jeg vil have noget af dig, denne vil have noget af den tredje person, og den tredje person vil have noget af mig. Og vi ender i en tre-vejs ventetid, fordi vi alle venter på, at den anden person fuldfører, hvad de skal gøre.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og Postgres ved, hvilken række det sker på. Og så vil det give dig følgende besked, som viser, at du har et problem, hvor de tre indgange blokerer hinanden. Og der er ingen begrænsninger. Dette kan være tilfældet, hvor 20 poster spærrer for hinanden.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Det næste nummer kan serialiseres.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Hvis en speciel serialiserbar lås.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og vi vender tilbage til 719. Han har et helt normalt problem.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og du kan presse på for at gøre transaktionen fra serialiserbar.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og du forstår, at du nu har en anden slags SA-lås - det betyder, at du kan serialisere.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og så har vi en ny slags lås kaldet SARieadLock, som er en seriel lås og giver dig mulighed for at indtaste serienumre.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og du kan også indsætte unikke indekser.

Oplåsning af Postgres Lock Manager. Bruce Momjian

I denne tabel har vi unikke indekser.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Så hvis jeg sætter tallet 2 ind her, er det derfor jeg har en 2. Men helt i toppen sætter jeg en anden 2. Og man kan se, at 721'eren har en eksklusiv lås. Men nu venter 722 på, at 721 fuldfører sin operation, fordi den ikke kan indsætte 2, før den ved, hvad der vil ske med 721.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og hvis vi laver undertransaktion.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Her har vi 723.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og hvis vi gemmer punktet og derefter opdaterer det, så får vi et nyt transaktions-id. Dette er en anden adfærd, du skal være opmærksom på. Hvis vi returnerer det, så er transaktions-id'et væk. 724 rejser. Men nu har vi 725.

Og hvad prøver jeg at gøre her? Jeg forsøger at vise dig eksempler på usædvanlige låse, som du kan finde: hvad enten det er serialiserbare låse eller SAVEPOINT-låse, er disse forskellige slags låse, der vises i låsetabellen.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Dette er oprettelsen af ​​eksplicitte (eksplicitte) låse, som har pg_advisory_lock.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og du kan se, at låsetypen er angivet her som rådgivende. Og her står der "rådgivende" med rødt. Og du kan blokere samtidigt med pg_advisory_unlock.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og afslutningsvis vil jeg gerne vise dig endnu en tankevækkende ting. Jeg vil oprette en anden visning. Men jeg vil slutte mig til tabellen pg_locks med tabellen pg_stat_activity. Og hvorfor vil jeg gøre dette? Fordi det giver mig mulighed for at se og se alle aktuelle sessioner og se, hvilken slags låse de venter på. Og det er interessant nok, når vi sammensætter en låsetabel og en forespørgselstabel.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og her laver vi pg_stat_view.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og vi opdaterer rækken efter én. Og her ser vi 724. Og så opdaterer vi vores række til tre. Og hvad ser du her nu? Det er forespørgsler, dvs. du ser hele listen over forespørgsler, der er opført i venstre kolonne. Og så i højre side kan du se låse og hvad de skaber. Og det kan være mere forståeligt for dig, så du ikke behøver at gå tilbage til hver session hver gang og se, om du skal være med eller ej. De gør det for os.

En anden funktion, der er meget nyttig er pg_blocking_pids. Du har sikkert aldrig hørt om hende. Hvad laver hun? Det giver os mulighed for at fortælle, at for denne session 11740, hvilke proces-id'er den venter på. Og man kan se, at 11740 venter 724. Og 724 er helt i top. Og 11306 er dit proces-id. I det væsentlige går denne funktion over dit låsebord. Og jeg ved godt det er lidt kompliceret, men du forstår. I det væsentlige går denne funktion gennem denne låsetabel og forsøger at finde, hvor dette proces-id er, givet de låse, den venter på. Og den forsøger også at finde ud af, hvilket proces-id den proces, der venter på låsen, har. Så du kan køre denne funktion pg_blocking_pids.

Og dette er meget nyttigt. Vi har kun tilføjet dette siden version 9.6, så denne funktion er kun 5 år gammel, men den er meget, meget nyttig. Og det samme gælder den anden anmodning. Det viser præcis, hvad vi skal se.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Det var det, jeg ville tale med dig om. Og som jeg forventede, brugte vi al vores tid, fordi der var så mange rutsjebaner. Og slides er tilgængelige til download. Jeg vil gerne takke dig for at være her. Jeg er sikker på, at du vil nyde resten af ​​konferencen, mange tak!

Spørgsmål:

For eksempel, hvis jeg forsøger at opdatere rækkerne, og den anden session forsøger at slette hele tabellen. Så vidt jeg forstår, burde der være noget i retning af en hensigtslås. Er der sådan noget i Postgres?

Oplåsning af Postgres Lock Manager. Bruce Momjian

Vi vender tilbage til begyndelsen. Du husker måske, at når du gør noget, som når du laver et SELECT, udsteder vi en AccessShareLock. Og det forhindrer bordet i at blive tabt. Så hvis du for eksempel vil opdatere en række i en tabel eller slette en række, så kan nogen ikke slette hele tabellen på samme tid, fordi du holder denne AccessShareLock over hele tabellen og over rækken. Og når du er færdig, kan de fjerne det. Men så længe du direkte ændrer noget der, vil de ikke kunne gøre det.

Lad os gøre det igen. Lad os gå videre til sletningseksemplet. Og du ser, hvordan rækken har en eksklusiv lås over hele bordet.

Det vil ligne en eksklusiv lås, ikke?

Ja, det ligner det. Jeg forstår, hvad du taler om. Siger du, at hvis jeg laver en SELECT, så har jeg en ShareExclusive, og så sætter jeg den i en Row Exclusive-tilstand, bliver det et problem? Men overraskende nok udgør dette ikke et problem. Det er ligesom at øge graden af ​​låsen, men i bund og grund har jeg en lås, der forhindrer den i at blive slettet. Og nu, når jeg gør denne lås mere kraftfuld, forhindrer den stadig sletning. Så det er ikke sådan, at jeg skal op. D.v.s. det forhindrede det også, når det var på et lavere niveau, så når jeg hæver det, forhindrer det stadig bordet i at blive tabt.

Jeg forstår, hvad du taler om. Der er ingen tilfælde af at øge graden af ​​blokering, hvor du forsøger at opgive en blok for at indføre en mere kraftfuld. Her øger det bare denne undgåelse alle steder, så det giver ingen konflikt. Men det er et godt spørgsmål. Mange tak fordi du spurgte!

Hvad skal vi gøre for at undgå en deadlock-situation, når vi har mange sessioner, et stort antal brugere?

Postgres bemærker automatisk dødvande situationer. Og det vil automatisk slette en af ​​sessionerne. Den eneste måde at undgå en fastlåst situation er at blokere folk i samme rækkefølge. Så når du ser på din ansøgning, er det ofte årsagen til dødvande... Lad os sige, at jeg vil blokere to forskellige ting. En applikation låser tabel 1 og en anden applikation låser tabel 2 og derefter tabel 1. Og den nemmeste måde at undgå dødvande er at se på din ansøgning og forsøge at sikre, at låsen sker i samme rækkefølge i alle applikationer. Og dette fjerner normalt 80% af problemerne, fordi alle slags mennesker skriver disse ansøgninger. Og blokerer du dem i samme rækkefølge, så løber du ikke ind i en dødvande.

Mange tak for din præstation! Du talte om vakuum fuld, og hvis jeg forstår det rigtigt, fordrejer vakuum fuld rækkefølgen af ​​poster i en separat butik, så det holder de nuværende poster uændrede. Hvorfor tager vakuum fuld eksklusiv låseadgang, og hvorfor er det i konflikt med skriveoperationer?

Det er et godt spørgsmål. Årsagen er, at vakuum fuld tager et bord. Og vi er i bund og grund ved at skabe en ny version af bordet. Og bordet bliver nyt. Det viser sig, at det bliver en helt ny version af bordet. Og problemet er, at når vi gør det, vil vi ikke have, at folk læser det, fordi vi vil have dem til at se den nye tabel. Og det hænger altså sammen med det foregående spørgsmål. Hvis vi kunne læse på samme tid, så ville vi ikke kunne flytte det og lede folk til et nyt bord. Vi ville være nødt til at vente på, at alle er færdige med at læse denne tabel, og så i bund og grund er dette en låseeksklusiv situation.
Vi siger bare, at vi låser fra starten, fordi vi ved, at vi skal bruge en eksklusiv lås til allersidst for at flytte alle til den nye kopi. Så potentielt kan vi løse det. Og sådan gør vi det med samtidig indeksering. Men dette er meget sværere at gøre. Og det gælder i høj grad dit tidligere spørgsmål om lås eksklusiv.

Er det muligt at tilføje låsetimeout i Postgres? I Oracle kan jeg fx skrive "vælg at opdatere" og vente 50 sekunder før jeg opdaterer. Det var godt for ansøgningen. Men i Postgres skal jeg enten gøre dette med det samme og slet ikke vente, eller vente til et stykke tid.

Ja, du kan vælge at timeout dine låse, dine låse. Du kan også udstede kommandoen no way, som vil være ... hvis du ikke kan få låsen med det samme. Derfor skal du enten låse timeout eller noget andet, der giver dig mulighed for at gøre dette. Dette gøres ikke på det syntaktiske niveau. Dette gøres som en variabel på serveren. Nogle gange kan det ikke bruges.

Kan du åbne slide 75?

Ja.

Oplåsning af Postgres Lock Manager. Bruce Momjian

Og mit spørgsmål er det næste. Hvorfor venter begge opdateringsprocesser på 703?

Og det er et godt spørgsmål. Jeg forstår i øvrigt ikke, hvorfor Postgres gør dette. Men da 703 blev oprettet, ventede den på 702. Og når 704 og 705 dukker op, ser de ikke ud til at vide, hvad de venter på, for der er intet der endnu. Og Postgres gør det sådan her: når du ikke kan få en lås, siger den "Hvad er meningen med at behandle dig?", For du venter allerede på nogen. Så lad det bare hænge i luften, det opdaterer det slet ikke. Men hvad skete der her? Så snart 702 fuldførte processen og 703 modtog sin lås, vendte systemet tilbage. Og hun sagde, at nu har vi to personer, der venter. Og lad os så opdatere dem sammen. Og angiv, at begge dele forventes.

Jeg ved ikke, hvorfor Postgres gør dette. Men der er et problem kaldet f…. Det forekommer mig, at dette ikke er et udtryk på russisk. Det er, når alle venter på et slot, selvom der er 20 instanser, der venter på slottet. Og pludselig vågner de alle sammen på samme tid. Og alle begynder at prøve at reagere. Men systemet gør det sådan, at alle venter på 703. For de venter alle sammen, og vi vil straks stille dem alle i kø. Og hvis der dukker en anden ny anmodning op, som blev dannet efter det, for eksempel 707, så vil der igen være et tomrum.

Og det forekommer mig, at dette er gjort for at kunne sige, at på dette stadium venter 702 på 703, og alle dem, der kommer efter det, vil ikke have nogen indgang i dette felt. Men så snart den første tjener går, og alle dem, der ventede på det tidspunkt før opdateringen, modtager den samme token. Og det forekommer mig altså, at det er gjort, for at vi kan behandle i orden, så de bliver ordentligt bestilt.

Jeg har altid set på det som et ret mærkeligt fænomen. For her er de for eksempel slet ikke opført. Men, det forekommer mig, hver gang vi giver en ny lås, kigger vi på alle dem, der er i gang med at vente. Så stiller vi dem alle sammen. Og så bliver enhver ny, der kommer ind, først i kø, når den næste person er færdig med at behandle. Et meget godt spørgsmål. Mange tak for dit spørgsmål!

Det forekommer mig meget mere logisk, når 705 forventer 704.

Men problemet her er følgende. Teknisk set kan du vække enten den ene eller den anden. Og så vågner vi det ene eller det andet. Men hvad sker der i driften af ​​systemet? Du kan se, hvordan 703 helt øverst har blokeret sit eget transaktions-id. Sådan fungerer Postgres. Og 703 er blokeret af sit eget transaktions-id, så hvis nogen vil vente, så vil han vente på 703. Og faktisk fuldfører 703. Og først efter dens afslutning vågner en af ​​processerne op. Og vi ved ikke, hvad det er for en proces. Så behandler vi gradvist alt. Men det er ikke klart, hvilken proces der vågner først, fordi det kan være en af ​​disse processer. Grundlæggende havde vi en planlægger, der sagde, at vi nu kunne vække enhver af disse processer. Vi vælger bare en tilfældigt. Derfor skal begge bemærkes, for vi kan vække enhver af dem.

Og problemet er, at vi har CP-infinity. Og derfor er det ret sandsynligt, at vi kan vække den senere. Og hvis vi for eksempel vågner senere, så venter vi på den, der lige har fået låsen, så vi ikke bestemmer, hvem der præcist bliver vækket først. Vi skaber netop sådan en situation, og systemet vil vække dem tilfældigt.

Der er artikler om Egor Rogovs låse. Se, de er også interessante og nyttige. Emnet er selvfølgelig frygteligt komplekst. Mange tak Bruce!

Kilde: www.habr.com

Tilføj en kommentar