Låser opp Postgres Lock Manager. Bruce Momjian

Transkripsjon av Bruce Momjians foredrag fra 2020 "Låse opp Postgres Lock Manager".

Låser opp Postgres Lock Manager. Bruce Momjian

(Merk: Alle SQL-spørringer fra lysbildene kan hentes fra denne lenken: http://momjian.us/main/writings/pgsql/locking.sql)

Hallo! Det er flott å være her i Russland igjen. Jeg beklager at jeg ikke kunne komme i fjor, men i år har Ivan og jeg store planer. Jeg håper å være her mye oftere. Jeg elsker å komme til Russland. Jeg vil besøke Tyumen, Tver. Jeg er veldig glad for at jeg vil kunne besøke disse byene.

Jeg heter Bruce Momjian. Jeg jobber i EnterpriseDB og har jobbet med Postgres i over 23 år. Jeg bor i Philadelphia, USA. Jeg reiser rundt 90 dager i året. Og jeg deltar på rundt 40 konferanser. Min nettsted, som inneholder lysbildene som jeg nå skal vise deg. Derfor kan du etter konferansen laste dem ned fra min personlige nettside. Den inneholder også rundt 30 presentasjoner. Det er også videoer og et stort antall blogginnlegg, mer enn 500. Dette er en ganske informativ ressurs. Og hvis du er interessert i dette materialet, så inviterer jeg deg til å bruke det.

Jeg pleide å være lærer, professor før jeg begynte å jobbe med Postgres. Og jeg er veldig glad for at jeg nå skal kunne fortelle deg det jeg skal fortelle deg. Dette er en av mine mest interessante presentasjoner. Og denne presentasjonen inneholder 110 lysbilder. Vi vil begynne å snakke med enkle ting, og mot slutten vil rapporten bli mer og mer kompleks, og vil bli ganske kompleks.

Låser opp Postgres Lock Manager. Bruce Momjian

Dette er en ganske ubehagelig samtale. Blokkering er ikke det mest populære emnet. Vi vil at dette skal forsvinne et sted. Det er som å gå til tannlegen.

Låser opp Postgres Lock Manager. Bruce Momjian

  1. Låsing er et problem for mange mennesker som jobber i databaser og har flere prosesser som kjører samtidig. De trenger blokkering. Det vil si at jeg i dag vil gi deg grunnleggende kunnskap om blokkering.
  2. Transaksjons-IDer. Dette er en ganske kjedelig del av presentasjonen, men de må forstås.
  3. Deretter vil vi snakke om typer blokkering. Dette er en ganske mekanisk del.
  4. Og nedenfor vil vi gi noen eksempler på blokkering. Og det vil være ganske vanskelig å forstå.

Låser opp Postgres Lock Manager. Bruce Momjian

La oss snakke om blokkering.

Låser opp Postgres Lock Manager. Bruce Momjian

Terminologien vår er ganske kompleks. Hvor mange av dere vet hvor denne passasjen kommer fra? To mennesker. Dette er fra et spill kalt Colossal Cave Adventure. Det var et tekstbasert dataspill på 80-tallet, tror jeg. Der måtte man inn i en hule, inn i en labyrint, og teksten endret seg, men innholdet var omtrent det samme hver gang. Det er slik jeg husker dette spillet.

Låser opp Postgres Lock Manager. Bruce Momjian

Og her ser vi navnet på låsene som kom til oss fra Oracle. Vi bruker dem.

Låser opp Postgres Lock Manager. Bruce Momjian

Her ser vi begreper som forvirrer meg. For eksempel, DEL OPPDATERING ECXLUSIVE. Neste DEL RÅ ECXLUSIVE. For å være ærlig er disse navnene ikke veldig klare. Vi vil prøve å vurdere dem mer detaljert. Noen inneholder ordet "dele", som betyr å skille. Noen inneholder ordet "eksklusiv". Noen inneholder begge disse ordene. Jeg vil gjerne begynne med hvordan disse låsene fungerer.

Låser opp Postgres Lock Manager. Bruce Momjian

Og ordet "tilgang" er også veldig viktig. Og ordene "rad" er en streng. Det vil si tilgangsfordeling, radfordeling.

Låser opp Postgres Lock Manager. Bruce Momjian

En annen sak som må forstås i Postgres, som jeg dessverre ikke vil kunne dekke i foredraget mitt, er MVCC. Jeg har en egen presentasjon om dette temaet på nettsiden min. Og hvis du synes denne presentasjonen er vanskelig, er MVCC sannsynligvis min vanskeligste. Og hvis du er interessert kan du se den på nettsiden. Du kan se videoen.

Låser opp Postgres Lock Manager. Bruce Momjian

En annen ting vi må forstå er transaksjons-IDer. Mange transaksjoner kan ikke fungere uten unike identifikatorer. Og her har vi en forklaring på hva en transaksjon er. Postgres har to transaksjonsnummereringssystemer. Jeg vet at dette ikke er en veldig pen løsning.

Låser opp Postgres Lock Manager. Bruce Momjian

Husk også at lysbildene vil være ganske vanskelige å forstå, så det som er uthevet i rødt er det du må være oppmerksom på.

Låser opp Postgres Lock Manager. Bruce Momjian

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

La oss se. Transaksjonsnummeret er uthevet i rødt. SELECT pg_back-funksjonen vises her. Den returnerer transaksjonen min og transaksjons-IDen.

En ting til, hvis du liker denne presentasjonen og vil kjøre den på databasen din, kan du gå til denne lenken i rosa og laste ned SQL-en for denne presentasjonen. Og du kan ganske enkelt kjøre den i PSQL-en din, og hele presentasjonen vises umiddelbart på skjermen. Den vil ikke inneholde blomster, men vi kan i det minste se den.

Låser opp Postgres Lock Manager. Bruce Momjian

I dette tilfellet ser vi transaksjons-IDen. Dette er nummeret vi tildelte henne. Og det er en annen type transaksjons-ID i Postgres, som kalles virtuell transaksjons-ID

Og vi må forstå dette. Dette er veldig viktig, ellers vil vi ikke kunne forstå låsing i Postgres.

En virtuell transaksjons-ID er en transaksjons-ID som ikke inneholder vedvarende verdier. For eksempel, hvis jeg kjører en SELECT-kommando, vil jeg mest sannsynlig ikke endre databasen, jeg vil ikke låse noe. Så når vi kjører en enkel SELECT, gir vi ikke transaksjonen en vedvarende ID. Vi gir henne bare en virtuell ID der.

Og dette forbedrer Postgres-ytelsen, forbedrer oppryddingsmulighetene, slik at den virtuelle transaksjons-IDen består av to tall. Det første tallet før skråstreken er backend-IDen. Og til høyre ser vi bare en teller.

Låser opp Postgres Lock Manager. Bruce Momjian

Derfor, hvis jeg kjører en forespørsel, står det at backend-IDen er 2.

Låser opp Postgres Lock Manager. Bruce Momjian

Og hvis jeg kjører en serie slike transaksjoner, så ser vi at telleren øker hver gang jeg kjører en spørring. For eksempel, når jeg kjører spørringen 2/10, 2/11, 2/12, etc.

Låser opp Postgres Lock Manager. Bruce Momjian

Husk at det er to kolonner her. Til venstre ser vi den virtuelle transaksjons-IDen – 2/12. Og til høyre har vi en permanent transaksjons-ID. Og dette feltet er tomt. Og denne transaksjonen endrer ikke databasen. Så jeg gir den ikke en permanent transaksjons-ID.

Låser opp Postgres Lock Manager. Bruce Momjian

Så snart jeg kjører analysekommandoen ((ANALYSE)), gir den samme spørringen meg en permanent transaksjons-ID. Se hvordan dette har endret seg for oss. Jeg hadde ikke denne ID-en før, men nå har jeg den.

Låser opp Postgres Lock Manager. Bruce Momjian

Så her er en annen forespørsel, en annen transaksjon. Det virtuelle transaksjonsnummeret er 2/13. Og hvis jeg ber om en vedvarende transaksjons-ID, får jeg den når jeg kjører spørringen.

Låser opp Postgres Lock Manager. Bruce Momjian

Så en gang til. Vi har en virtuell transaksjons-ID og en vedvarende transaksjons-ID. Bare forstå dette punktet for å forstå Postgres oppførsel.

Låser opp Postgres Lock Manager. Bruce Momjian

Vi går videre til den tredje delen. Her skal vi ganske enkelt gå gjennom de forskjellige typene låser i Postgres. Det er ikke veldig interessant. Den siste delen vil være mye mer interessant. Men vi må vurdere de grunnleggende tingene, for ellers forstår vi ikke hva som skjer videre.

Vi går gjennom denne delen, vi skal se på hver type lås. Og jeg skal vise deg eksempler på hvordan de er installert, hvordan de fungerer, jeg skal vise deg noen spørsmål som du kan bruke for å se hvordan låsing fungerer i Postgres.

Låser opp Postgres Lock Manager. Bruce Momjian

For å opprette en spørring og se hva som skjer i Postgres, må vi sende spørringen i systemvisningen. I dette tilfellet er pg_lock uthevet i rødt. Pg_lock er en systemtabell som forteller oss hvilke låser som for tiden er i bruk i Postgres.

Imidlertid er det veldig vanskelig for meg å vise deg pg_lock i seg selv fordi det er ganske komplekst. Så jeg opprettet en visning som viser pg_locks. Og det gjør også noe for meg som lar meg forstå bedre. Det vil si at det ekskluderer mine låser, min egen økt osv. Det er bare standard SQL og det lar deg bedre vise deg hva som skjer.

Låser opp Postgres Lock Manager. Bruce Momjian

Et annet problem er at denne visningen er veldig bred, så jeg må lage en andre - lockview2.

Låser opp Postgres Lock Manager. Bruce Momjian Og det viser meg flere kolonner fra tabellen. Og en annen som viser meg resten av kolonnene. Dette er ganske komplekst, så jeg prøvde å presentere det så enkelt som mulig.

Låser opp Postgres Lock Manager. Bruce Momjian

Så vi laget en tabell kalt Lockdemo. Og vi laget en linje der. Dette er prøvetabellen vår. Og vi lager seksjoner bare for å vise deg eksempler på låser.

Låser opp Postgres Lock Manager. Bruce Momjian

Så, en rad, en kolonne. Den første typen lås kalles TILGANGSDEL. Dette er den minst restriktive blokkeringen. Dette betyr at den praktisk talt ikke kommer i konflikt med andre låser.

Og hvis vi vil eksplisitt definere en lås, kjører vi kommandoen "lås tabell". Og det vil åpenbart blokkere, dvs. i ACCESS SHARE-modus starter vi låsetabellen. Og hvis jeg kjører PSQL i bakgrunnen, starter jeg den andre økten fra min første økt på denne måten. Det vil si, hva skal jeg gjøre her? Jeg går til en annen økt og forteller den "vis meg låsevisningen for denne forespørselen." Og her har jeg AccessShareLock i denne tabellen. Dette er akkurat det jeg ba om. Og han sier at blokken er tildelt. Veldig enkelt.

Låser opp Postgres Lock Manager. Bruce Momjian

Videre, hvis vi ser på den andre kolonnen, er det ingenting der. De er tomme.

Låser opp Postgres Lock Manager. Bruce Momjian

Og hvis jeg kjører "SELECT"-kommandoen, så er dette den implisitte (eksplisitte) måten å be om AccessShareLock. Så jeg slipper tabellen og kjører spørringen og spørringen returnerer flere rader. Og i en av linjene ser vi AccessShareLock. Dermed kaller SELECT AccessShareLock på bordet. Og det er ikke i konflikt med praktisk talt noe fordi det er en lås på lavt nivå.

Låser opp Postgres Lock Manager. Bruce Momjian

Hva om jeg kjører en SELECT og har tre forskjellige tabeller? Tidligere kjørte jeg bare én tabell, nå kjører jeg tre: pg_class, pg_namespace og pg_attribute.

Låser opp Postgres Lock Manager. Bruce Momjian

Og nå når jeg ser på spørringen, ser jeg 9 AccessShareLocks i tre tabeller. Hvorfor? Tre tabeller er uthevet i blått: pg_attribute, pg_class, pg_namespace. Men du kan også se at alle indekser som er definert gjennom disse tabellene også har AccessShareLock.

Og dette er en lås som praktisk talt ikke er i konflikt med andre. Og alt det gjør er ganske enkelt å hindre oss i å nullstille bordet mens vi velger det. Det gir mening. Det vil si at hvis vi velger en tabell, forsvinner den i det øyeblikket, så er dette feil, så AccessShare er en lavnivålås som forteller oss "ikke slipp dette bordet mens jeg jobber". I hovedsak er det alt hun gjør.

Låser opp Postgres Lock Manager. Bruce Momjian

RADDELING - Denne låsen er litt annerledes.

Låser opp Postgres Lock Manager. Bruce Momjian

La oss ta et eksempel. SELECT ROW SHARE-metoden for å låse hver rad individuelt. På denne måten kan ingen slette dem eller endre dem mens vi ser på dem.

Låser opp Postgres Lock Manager. Bruce MomjianSå hva gjør SHARE LOCK? Vi ser at transaksjons-IDen er 681 for SELECT. Og dette er interessant. Hva skjedde her? Første gang vi ser nummeret er i "Lås"-feltet. Vi tar transaksjons-IDen og den sier at den blokkerer den i eksklusiv modus. Alt det gjør er at det står at jeg har en rad som teknisk sett er låst et sted i tabellen. Men han sier ikke nøyaktig hvor. Vi skal se nærmere på dette litt senere.

Låser opp Postgres Lock Manager. Bruce Momjian

Her sier vi at låsen brukes av oss.

Låser opp Postgres Lock Manager. Bruce Momjian

Så en eksklusiv lås sier eksplisitt at den er eksklusiv. Og også hvis du sletter en rad i denne tabellen, så er dette hva som vil skje, som du kan se.

Låser opp Postgres Lock Manager. Bruce Momjian

SHARE EXCLUSIVE er en lengre lås.

Låser opp Postgres Lock Manager. Bruce Momjian

Dette er (ANALYSE) analysatorkommandoen som skal brukes.

Låser opp Postgres Lock Manager. Bruce Momjian

DEL LÅS – du kan eksplisitt låse i delemodus.

Låser opp Postgres Lock Manager. Bruce Momjian

Du kan også lage en unik indeks. Og der kan du se SHARE LOCK, som er en del av dem. Og den låser bordet og setter en DELINGSLÅS på det.

Som standard betyr SHARE LOCK på et bord at andre kan lese tabellen, men ingen kan endre den. Og dette er nøyaktig hva som skjer når du lager en unik indeks.

Hvis jeg oppretter en unik samtidig indeks, vil jeg ha en annen type låsing fordi, som du husker, bruk av samtidige indekser reduserer låsekravet. Og hvis jeg bruker en vanlig lås, en normal indeks, så vil jeg dermed forhindre skriving til tabellindeksen mens den lages. Hvis jeg bruker en samtidig indeks, må jeg bruke en annen type låsing.

Låser opp Postgres Lock Manager. Bruce Momjian

DEL RAD EKSKLUSIVT – igjen kan den angis eksplisitt (eksplisitt).

Låser opp Postgres Lock Manager. Bruce Momjian

Eller vi kan lage en regel, dvs. ta et spesifikt tilfelle der den skal brukes.

Låser opp Postgres Lock Manager. Bruce Momjian

EKSKLUSIV låsing gjør at ingen andre kan endre bordet.

Låser opp Postgres Lock Manager. Bruce Momjian

Her ser vi ulike typer låser.

Låser opp Postgres Lock Manager. Bruce Momjian

ACCESS EXCLUSIVE, for eksempel, er en blokkeringskommando. For eksempel hvis du gjør det CLUSTER table, så vil dette bety at ingen vil kunne skrive der. Og den låser ikke bare selve bordet, men også indeksene.

Låser opp Postgres Lock Manager. Bruce Momjian

Dette er den andre siden av ACCESS EXCLUSIVE-blokkeringen, der vi ser nøyaktig hva den blokkerer i tabellen. Den låser individuelle bordrader, noe som er ganske interessant.

Det er all den grunnleggende informasjonen jeg ønsket å gi. Vi snakket om låser, om transaksjons-IDer, vi snakket om virtuelle transaksjons-IDer, om permanente transaksjons-IDer.

Låser opp Postgres Lock Manager. Bruce Momjian

Og nå skal vi gå gjennom noen blokkeringseksempler. Dette er den mest interessante delen. Vi skal se på veldig interessante saker. Og målet mitt i denne presentasjonen er å gi deg en bedre forståelse av hva Postgres faktisk gjør når den prøver å blokkere visse ting. Jeg synes han er veldig flink til å blokkere deler.

La oss se på noen spesifikke eksempler.

Låser opp Postgres Lock Manager. Bruce Momjian

Vi starter med tabeller og en rad i en tabell. Når jeg setter inn noe har jeg ExclusiveLock, Transaction ID og ExclusiveLock vist på bordet.

Låser opp Postgres Lock Manager. Bruce Momjian

Hva skjer hvis jeg setter inn to rader til? Og nå har tabellen vår tre rader. Og jeg satte inn en rad og fikk denne som en utgang. Og hvis jeg setter inn to rader til, hva er rart med det? Det er en merkelig ting her fordi jeg har lagt til tre rader til denne tabellen, men jeg har fortsatt to rader i låsetabellen. Og dette er egentlig den grunnleggende oppførselen til Postgres.

Mange tror at hvis du låser 100 rader i en database, må du opprette 100 låseoppføringer. Hvis jeg blokkerer 1 rader samtidig, trenger jeg 000 slike søk. Og om jeg trenger en million eller en milliard for å blokkere. Men hvis vi gjør dette, vil det ikke fungere særlig bra. Hvis du har brukt et system som lager blokkeringsoppføringer for hver enkelt rad, så kan du se at dette er komplisert. Fordi du umiddelbart må definere en låsetabell som kan flyte over, men Postgres gjør ikke det.

Og det som er veldig viktig med dette lysbildet er at det tydelig viser at det er et annet system som kjører inne i MVCC som låser individuelle rader. Så når du låser milliarder av rader, oppretter ikke Postgres en milliard separate låsekommandoer. Og dette har veldig god effekt på produktiviteten.

Låser opp Postgres Lock Manager. Bruce Momjian

Hva med en oppdatering? Jeg oppdaterer raden nå, og du kan se at den har utført to forskjellige operasjoner samtidig. Det låste bordet samtidig, men det låste også indeksen. Og han trengte å låse indeksen fordi det er unike begrensninger på denne tabellen. Og vi vil sørge for at ingen endrer det, så vi blokkerer det.

Låser opp Postgres Lock Manager. Bruce Momjian

Hva skjer hvis jeg vil oppdatere to rader? Og vi ser at han oppfører seg på samme måte. Vi gjør dobbelt så mange oppdateringer, men nøyaktig like mange låselinjer.

Hvis du lurer på hvordan Postgres gjør dette, må du lytte til foredragene mine om MVCC for å finne ut hvordan Postgres internt markerer disse linjene som endres. Og Postgres har en måte den gjør dette på, men den gjør det ikke på bordlåsnivå, den gjør det på et lavere og mer effektivt nivå.

Låser opp Postgres Lock Manager. Bruce Momjian

Hva om jeg vil slette noe? Hvis jeg sletter for eksempel én rad og jeg fortsatt har mine to blokkeringsinnganger, og selv om jeg vil slette alle, er de fortsatt der.

Låser opp Postgres Lock Manager. Bruce Momjian

Og for eksempel vil jeg sette inn 1 linjer, og deretter enten slette eller legge til 000 linjer, så de individuelle linjene som jeg legger til eller endrer, de blir ikke registrert her. De er skrevet på et lavere nivå innenfor selve serien. Og under MVCC-talen snakket jeg om dette i detalj. Men det er veldig viktig når du analyserer låser å være sikker på at du låser på tabellnivå og at du ikke ser hvordan individuelle rader blir registrert her.

Låser opp Postgres Lock Manager. Bruce Momjian

Hva med eksplisitt blokkering?

Låser opp Postgres Lock Manager. Bruce Momjian

Hvis jeg klikker på oppdater, har jeg to rader låst. Og hvis jeg velger dem alle og klikker "oppdater overalt", så har jeg fortsatt to blokkeringsposter.

Låser opp Postgres Lock Manager. Bruce Momjian

Vi oppretter ikke separate poster for hver enkelt rad. For da synker produktiviteten, kan det bli for mye av det. Og vi kan komme i en ubehagelig situasjon.

Låser opp Postgres Lock Manager. Bruce Momjian

Og det samme, hvis vi deler, kan vi gjøre alt 30 ganger.

Låser opp Postgres Lock Manager. Bruce Momjian

Vi gjenoppretter tabellen vår, sletter alt og setter inn en rad igjen.

Låser opp Postgres Lock Manager. Bruce Momjian

En annen oppførsel som du ser i Postgres som er veldig kjent og ønsket oppførsel er at du kan gjøre en oppdatering eller et utvalg. Og du kan gjøre dette samtidig. Og select blokkerer ikke oppdatering og det samme i motsatt retning. Vi ber leseren om ikke å blokkere forfatteren, og forfatteren blokkerte ikke leseren.

Jeg skal vise deg et eksempel på dette. Jeg tar et valg nå. Vi vil da gjøre INSERT. Og så kan du se - 694. Du kan se ID-en til transaksjonen som utførte denne innsettingen. Og det er slik det fungerer.

Låser opp Postgres Lock Manager. Bruce Momjian

Og hvis jeg ser på backend-ID-en min nå, er den nå 695.

Låser opp Postgres Lock Manager. Bruce Momjian

Og jeg kan se 695 dukke opp i tabellen min.

Låser opp Postgres Lock Manager. Bruce Momjian

Og hvis jeg oppdaterer her slik, så får jeg en annen sak. I dette tilfellet er 695 en eksklusiv lås, og oppdateringen har samme oppførsel, men det er ingen konflikt mellom dem, noe som er ganske uvanlig.

Og du kan se at øverst er det ShareLock, og nederst er det ExclusiveLock. Og begge transaksjonene fungerte.

Og du må lytte til foredraget mitt på MVCC for å forstå hvordan dette skjer. Men dette er en illustrasjon på at du kan gjøre det samtidig, dvs. gjøre en SELECT og en UPDATE samtidig.

Låser opp Postgres Lock Manager. Bruce Momjian

La oss tilbakestille og gjøre en operasjon til.

Låser opp Postgres Lock Manager. Bruce Momjian

Hvis du prøver å kjøre to oppdateringer samtidig på samme rad, vil det bli blokkert. Og husk, jeg sa at leseren ikke blokkerer forfatteren, og forfatteren blokkerer ikke leseren, men en forfatter blokkerer en annen forfatter. Det vil si at vi ikke kan ha to personer til å oppdatere samme rad samtidig. Du må vente til en av dem er ferdig.

Låser opp Postgres Lock Manager. Bruce Momjian

Og for å illustrere dette, skal jeg se på Lockdemo-tabellen. Og vi skal se på en rad. Per transaksjon 698.

Vi har oppdatert denne til 2. 699 er den første oppdateringen. Og den var vellykket, eller den er i en ventende transaksjon og venter på at vi skal bekrefte eller avbryte.

Låser opp Postgres Lock Manager. Bruce Momjian

Men se på noe annet - 2/51 er vår første transaksjon, vår første økt. 3/112 er den andre forespørselen som kom fra toppen som endret den verdien til 3. Og hvis du legger merke til, låste den øverste seg selv, som er 699. Men 3/112 ga ikke låsen. Lock_mode-kolonnen sier hva den venter på. Den forventer 699. Og hvis du ser på hvor 699 er, er den høyere. Og hva gjorde den første økten? Hun opprettet en eksklusiv lås på sin egen transaksjons-ID. Slik gjør Postgres det. Den blokkerer sin egen transaksjons-ID. Og hvis du vil vente på at noen bekrefter eller kansellerer, må du vente mens det er en ventende transaksjon. Og det er derfor vi kan se en merkelig strek.

La oss se igjen. Til venstre ser vi vår behandlings-ID. I den andre kolonnen ser vi vår virtuelle transaksjons-ID, og ​​i den tredje ser vi lock_type. Hva betyr dette? I hovedsak er det det står at det blokkerer transaksjons-IDen. Men legg merke til at alle radene nederst sier relasjon. Og så har du to typer låser på bordet. Det er en relasjonslås. Og så er det transaksjons-ID-blokkeringen, der du blokkerer på egen hånd, som er nøyaktig det som skjer på den første raden eller helt nederst, der transaksjons-ID-en er, hvor vi venter på at 699 skal fullføre operasjonen.

Jeg får se hva som skjer her. Og her skjer to ting samtidig. Du ser på en transaksjons-ID-lås i den første raden som låser seg selv. Og hun blokkerer seg selv for å få folk til å vente.

Hvis du ser på 6. linje, er det samme oppføring som den første. Og derfor er transaksjon 699 blokkert. 700 er også selvlåsende. Og så på nederste rad ser du at vi venter på at 699 skal fullføre operasjonen.

Låser opp Postgres Lock Manager. Bruce Momjian

Og i lock_type, tuple ser du tall.

Låser opp Postgres Lock Manager. Bruce Momjian

Du kan se det er 0/10. Og dette er sidetallet, og også forskyvningen av denne raden.

Låser opp Postgres Lock Manager. Bruce Momjian

Og du ser det blir 0/11 når vi oppdaterer.

Låser opp Postgres Lock Manager. Bruce Momjian

Men i virkeligheten er det 0/10, fordi det er ventetid på denne operasjonen. Vi har muligheten til å se at dette er serien jeg venter på å få bekreftet.

Låser opp Postgres Lock Manager. Bruce Momjian

Når vi har bekreftet det og trykket commit, og når oppdateringen er ferdig, er det dette vi får igjen. Transaction 700 er den eneste låsen, den venter ikke på noen andre fordi den ble begått. Den venter ganske enkelt på at transaksjonen skal fullføres. Når 699 går tom, venter vi ikke på noe lenger. Og nå sier transaksjon 700 at alt er bra, at den har alle låsene den trenger på alle tillatte bord.

Låser opp Postgres Lock Manager. Bruce Momjian

Og for å gjøre det hele enda mer komplisert, lager vi et annet syn, som denne gangen vil gi oss et hierarki. Jeg forventer ikke at du forstår denne forespørselen. Men dette vil gi oss et klarere syn på hva som skjer.

Låser opp Postgres Lock Manager. Bruce Momjian

Dette er et rekursivt syn som også har et annet avsnitt. Og så bringer det alt sammen igjen. La oss bruke dette.

Låser opp Postgres Lock Manager. Bruce Momjian

Hva om vi gjør tre samtidige oppdateringer og sier at raden nå er tre. Og vi endrer 3 til 4.

Låser opp Postgres Lock Manager. Bruce Momjian

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

Låser opp Postgres Lock Manager. Bruce Momjian

Og så vil jeg endre 4 til 5. Og 5 til 6, og 6 til 7. Og jeg vil stille opp en rekke personer som venter på at denne ene transaksjonen skal avsluttes.

Låser opp Postgres Lock Manager. Bruce Momjian

Og alt blir klart. Hva er den første raden? Dette er 702. Dette er transaksjons-IDen som opprinnelig satte denne verdien. Hva står skrevet i Granted-spalten min? Jeg har merker f. Dette er mine oppdateringer som (5, 6, 7) ikke kan godkjennes fordi vi venter på at transaksjons-ID 702 skal avsluttes. Der har vi blokkering av transaksjons-ID. Og dette resulterer i 5 transaksjonelle ID-låser.

Og hvis du ser på 704, på 705, er ingenting skrevet der ennå, fordi de ikke vet hva som skjer ennå. De skriver rett og slett at de ikke aner hva som skjer. Og de vil bare legge seg fordi de venter på at noen skal bli ferdige og vekkes når det er mulighet for å bytte rad.

Låser opp Postgres Lock Manager. Bruce Momjian

Slik ser det ut. Det er tydelig at de alle venter på 12. linje.

Låser opp Postgres Lock Manager. Bruce Momjian

Dette er hva vi så her. Her er 0/12.

Låser opp Postgres Lock Manager. Bruce Momjian

Så når den første transaksjonen er godkjent, kan du se her hvordan hierarkiet fungerer. Og nå blir alt klart. De blir alle rene. Og de venter faktisk fortsatt.

Låser opp Postgres Lock Manager. Bruce Momjian

Her er hva som skjer. 702 forplikter seg. Og nå får 703 denne radlåsen, og så begynner 704 å vente på at 703 skal forplikte seg. Og 705 venter på dette også. Og når alt dette er fullført, rydder de seg opp. Og jeg vil påpeke at alle stiller opp. Og dette ligner veldig på en situasjon i en trafikkork når alle venter på den første bilen. Den første bilen stopper og alle stiller seg opp i en lang rekke. Så beveger den seg, så kan neste bil kjøre frem og få blokken sin osv.

Låser opp Postgres Lock Manager. Bruce Momjian

Og hvis dette ikke virket komplisert nok for deg, så skal vi nå snakke med deg om vranglås. Jeg vet ikke hvem av dere som har møtt dem. Dette er et ganske vanlig problem i databasesystemer. Men vranglås er når en økt venter på at en annen økt skal gjøre noe. Og i dette øyeblikket venter en annen økt på at den første økten skal gjøre noe.

Og for eksempel hvis Ivan sier: "Gi meg noe," og jeg sier: "Nei, jeg vil bare gi det til deg hvis du gir meg noe annet." Og han sier: "Nei, jeg vil ikke gi det til deg hvis du ikke gir det til meg." Og vi havner i en fastlåst situasjon. Jeg er sikker på at Ivan ikke vil gjøre dette, men du forstår meningen med at vi har to personer som ønsker å få noe, og de er ikke klare til å gi det bort før den andre personen gir dem det de ønsker. Og det er ingen løsning.

Og i hovedsak må databasen din oppdage dette. Og så må du slette eller lukke en av øktene, for ellers vil de forbli der for alltid. Og vi ser det i databaser, vi ser det i operativsystemer. Og alle steder hvor vi har parallelle prosesser kan dette skje.

Låser opp Postgres Lock Manager. Bruce Momjian

Og nå skal vi installere to vranglåser. Vi setter 50 og 80. I den første raden oppdaterer jeg fra 50 til 50. Jeg får transaksjonsnummer 710.

Låser opp Postgres Lock Manager. Bruce Momjian

Og så vil jeg endre 80 til 81, og 50 til 51.

Låser opp Postgres Lock Manager. Bruce Momjian

Og slik vil det se ut. Så 710 har en rad blokkert, og 711 venter på bekreftelse. Vi så dette da vi oppdaterte. 710 er eieren av serien vår. Og 711 venter på at 710 skal fullføre transaksjonen.

Låser opp Postgres Lock Manager. Bruce Momjian

Og det står til og med på hvilken rad vranglåsene oppstår. Og her begynner det å bli rart.

Låser opp Postgres Lock Manager. Bruce Momjian

Nå oppdaterer vi 80 til 80.

Låser opp Postgres Lock Manager. Bruce Momjian

Og det er her vranglåsene begynner. 710 venter på svar fra 711, og 711 venter på 710. Og dette vil ikke ende godt. Og det er ingen vei utenom dette. Og de vil forvente svar fra hverandre.

Låser opp Postgres Lock Manager. Bruce Momjian

Og det vil bare begynne å forsinke alt. Og det ønsker vi ikke.

Låser opp Postgres Lock Manager. Bruce Momjian

Og Postgres har måter å legge merke til når dette skjer. Og når dette skjer, får du denne feilmeldingen. Og fra dette er det klart at en slik og en slik prosess venter på en DELINGSLÅS fra en annen prosess, dvs. som er blokkert av 711-prosessen. Og den prosessen ventet på at en DELINGSLÅS skulle gis på en slik og en transaksjons-ID og ble blokkert av en slik og en slik prosess. Derfor er det en fastlåst situasjon her.

Låser opp Postgres Lock Manager. Bruce Momjian

Er det treveis vranglås? Er det mulig? Ja.

Låser opp Postgres Lock Manager. Bruce Momjian

Vi legger inn disse tallene i en tabell. Vi endrer 40 til 40, vi blokkerer.

Låser opp Postgres Lock Manager. Bruce Momjian

Vi endrer 60 til 61, 80 til 81.

Låser opp Postgres Lock Manager. Bruce Momjian

Og så bytter vi 80 og så bom!

Låser opp Postgres Lock Manager. Bruce Momjian

Og 714 venter nå på 715. 716. venter på 715. Og ingenting kan gjøres med det.

Låser opp Postgres Lock Manager. Bruce Momjian

Det er ikke lenger to personer her, det er allerede tre personer her. Jeg vil ha noe fra deg, denne vil ha noe fra en tredje person, og den tredje personen vil ha noe fra meg. Og vi ender opp i en treveis ventetid fordi vi alle venter på at den andre personen skal fullføre det de trenger å gjøre.

Låser opp Postgres Lock Manager. Bruce Momjian

Og Postgres vet på hvilken rad dette skjer. Så det vil gi deg følgende melding, som viser at du har et problem der tre innganger blokkerer hverandre. Og det er ingen begrensninger her. Dette kan være tilfelle der 20 oppføringer blokkerer hverandre.

Låser opp Postgres Lock Manager. Bruce Momjian

Det neste problemet er serialiserbart.

Låser opp Postgres Lock Manager. Bruce Momjian

Hvis spesiell serialiserbar lås.

Låser opp Postgres Lock Manager. Bruce Momjian

Og vi går tilbake til 719. Utgangen er ganske normal.

Låser opp Postgres Lock Manager. Bruce Momjian

Og du kan klikke for å gjøre transaksjonen fra serialiserbar.

Låser opp Postgres Lock Manager. Bruce Momjian

Og du innser at du nå har en annen type SA-lås - det betyr serialiserbar.

Låser opp Postgres Lock Manager. Bruce Momjian

Låser opp Postgres Lock Manager. Bruce Momjian

Og så har vi en ny type lås kalt SARieadLock, som er en seriell lås og lar deg legge inn serier.

Låser opp Postgres Lock Manager. Bruce Momjian

Og du kan også sette inn unike indekser.

Låser opp Postgres Lock Manager. Bruce Momjian

I denne tabellen har vi unike indekser.

Låser opp Postgres Lock Manager. Bruce Momjian

Så hvis jeg setter inn tallet 2 her, så har jeg en 2. Men helt på toppen setter jeg inn ytterligere 2. Og du kan se at 721 har en eksklusiv lås. Men nå venter 722 på at 721 skal fullføre operasjonen fordi den ikke kan sette inn 2 før den vet hva som vil skje med 721.

Låser opp Postgres Lock Manager. Bruce Momjian

Og hvis vi gjør deltransaksjoner.

Låser opp Postgres Lock Manager. Bruce Momjian

Her har vi 723.

Låser opp Postgres Lock Manager. Bruce Momjian

Og hvis vi lagrer punktet og deretter oppdaterer det, får vi en ny transaksjons-ID. Dette er et annet atferdsmønster du må være klar over. Hvis vi returnerer dette, forsvinner transaksjons-IDen. 724 drar. Men nå har vi 725.

Så hva prøver jeg å gjøre her? Jeg prøver å vise deg eksempler på uvanlige låser du kan finne: enten det er serialiserbare låser eller SAVEPOINT, er dette forskjellige typer låser som vil vises i låstabellen.

Låser opp Postgres Lock Manager. Bruce Momjian

Dette er opprettelsen av eksplisitte (eksplisitte) låser, som har pg_advisory_lock.

Låser opp Postgres Lock Manager. Bruce Momjian

Og du ser at blokkeringstypen er oppført som rådgivende. Og her står det "rådgivende" i rødt. Og du kan blokkere slik samtidig med pg_advisory_unlock.

Låser opp Postgres Lock Manager. Bruce Momjian

Og avslutningsvis vil jeg gjerne vise deg en ting til som er helt fantastisk. Jeg lager en annen visning. Men jeg vil slå sammen pg_locks-tabellen med pg_stat_activity-tabellen. Og hvorfor vil jeg gjøre dette? Fordi dette vil tillate meg å se og se alle de nåværende øktene og se nøyaktig hva slags låser de venter på. Og dette er ganske interessant når vi setter sammen låstabellen og spørringstabellen.

Låser opp Postgres Lock Manager. Bruce Momjian

Og her lager vi pg_stat_view.

Låser opp Postgres Lock Manager. Bruce Momjian

Og vi oppdaterer raden etter én. Og her ser vi 724. Og så oppdaterer vi raden vår til tre. Og hva ser du her nå? Dette er forespørsler, det vil si at du ser hele listen over forespørsler som er oppført i venstre kolonne. Og så på høyre side kan du se blokkeringene og hva de skaper. Og det kan være mer oversiktlig for deg slik at du ikke trenger å gå tilbake til hver økt hver gang og se om du trenger å bli med eller ikke. De gjør det for oss.

En annen funksjon som er veldig nyttig er pg_blocking_pids. Du har sikkert aldri hørt om henne. Hva gjør hun? Det lar oss fortelle at for denne økten 11740 hvilke spesifikke prosess-IDer den venter på. Og du kan se at 11740 venter på 724. Og 724 er helt på topp. Og 11306 er din prosess-ID. I hovedsak går denne funksjonen gjennom låsebordet ditt. Og jeg vet at det er litt komplisert, men du klarer å forstå det. I hovedsak går denne funksjonen gjennom denne låsetabellen og prøver å finne hvor denne prosess-IDen er gitt låsene den venter på. Og den prøver også å finne ut hvilken prosess-ID prosessen som venter på låsen har. Så du kan kjøre denne funksjonen pg_blocking_pids.

Og dette kan være veldig nyttig. Vi la kun til denne i versjon 9.6, så denne funksjonen er bare 5 år gammel, men den er veldig, veldig nyttig. Og det samme gjelder den andre forespørselen. Det viser nøyaktig hva vi trenger å se.

Låser opp Postgres Lock Manager. Bruce Momjian

Det var dette jeg ville snakke med deg om. Og som jeg forventet brukte vi opp all tid fordi det var så mange sklier. Og lysbildene er tilgjengelige for nedlasting. Jeg vil takke deg for at du er her. Jeg er sikker på at du vil like resten av konferansen, tusen takk!

spørsmål:

For eksempel, hvis jeg prøver å oppdatere rader, og den andre økten prøver å slette hele tabellen. Så vidt jeg forstår skal det være noe som en intensjonslås. Er det noe slikt i Postgres?

Låser opp Postgres Lock Manager. Bruce Momjian

La oss gå tilbake til begynnelsen. Du husker kanskje at når du gjør noe, for eksempel når du gjør en SELECT, utsteder vi en AccessShareLock. Og dette forhindrer at bordet faller. Så hvis du for eksempel ønsker å oppdatere en rad i en tabell eller slette en rad, kan ikke noen slette hele tabellen samtidig fordi du holder denne AccessShareLock over hele tabellen og over raden. Og når du er ferdig, kan de slette den. Men mens du endrer noe direkte der, vil de ikke kunne gjøre det.

La oss gjøre det igjen. La oss gå videre til sletteeksemplet. Og du ser hvordan det er en eksklusiv lås på raden over hele bordet.

Dette vil se ut som låseksklusivt, ikke sant?

Ja, det ser ut som det. Jeg forstår hva du snakker om. Du sier at hvis jeg gjør en SELECT så har jeg en ShareExclusive og så gjør jeg den Row Exclusive, blir det et problem? Men overraskende nok er ikke dette noe problem. Dette ser ut til å øke låsegraden, men i hovedsak har jeg en lås som forhindrer sletting. Og nå, når jeg gjør denne låsen kraftigere, forhindrer den fortsatt sletting. Så det er ikke sånn at jeg skal opp. Det vil si at det forhindret det fra å skje når det var på et lavere nivå også, så når jeg hever nivået, forhindrer det fortsatt tabellen i å bli slettet.

Jeg forstår hva du snakker om. Det er ingen låseskaleringssak her, der du prøver å gi opp en lås for å introdusere en sterkere. Her øker det bare denne forebyggingen over hele linja, så det skaper ingen konflikt. Men det er et godt spørsmål. Tusen takk for at du spør om dette!

Hva må vi gjøre for å unngå en fastlåst situasjon når vi har mange økter, et stort antall brukere?

Postgres merker automatisk fastlåste situasjoner. Og den vil automatisk slette en av øktene. Den eneste måten å unngå død blokkering på er å blokkere folk i samme rekkefølge. Så når du ser på søknaden din, er det ofte årsaken til vranglås... La oss forestille oss at jeg vil blokkere to forskjellige ting. En applikasjon låser tabell 1, og en annen applikasjon låser 2, og deretter tabell 1. Og den enkleste måten å unngå vranglås på er å se på applikasjonen din og prøve å forsikre deg om at låsingen skjer i samme rekkefølge på tvers av alle applikasjoner. Og dette eliminerer vanligvis 80% av problemene, fordi alle slags mennesker skriver disse søknadene. Og hvis du blokkerer dem i samme rekkefølge, støter du ikke på en fastlåst situasjon.

Tusen takk for prestasjonen! Du snakket om vakuum fullt, og hvis jeg forstår det riktig, forvrenger vakuum full rekkefølgen på poster i separat lagring, slik at de holder gjeldende poster uendret. Hvorfor tar vakuum full eksklusiv låstilgang og hvorfor er det i konflikt med skriveoperasjoner?

Det er et godt spørsmål. Årsaken er at vakuum fullt tar bordet. Og vi lager egentlig en ny versjon av tabellen. Og bordet blir nytt. Det viser seg at dette blir en helt ny versjon av bordet. Og problemet er at når vi gjør dette, vil vi ikke at folk skal lese det fordi vi trenger at de skal se den nye tabellen. Og så dette kobles til det forrige spørsmålet. Hvis vi kunne lese samtidig, ville vi ikke kunne flytte den og lede folk til et nytt bord. Vi må vente på at alle er ferdige med å lese denne tabellen, og derfor er det i hovedsak en låseeksklusiv situasjon.
Vi sier bare at vi låser fra begynnelsen fordi vi vet at vi helt på slutten vil trenge en eksklusiv lås for å flytte alle til det nye eksemplaret. Så vi kan potensielt løse dette. Og vi gjør det på denne måten med samtidig indeksering. Men dette er mye vanskeligere å gjøre. Og dette er veldig knyttet til det forrige spørsmålet ditt om låseksklusiv.

Er det mulig å legge til tidsavbrudd for låsing til Postgres? I Oracle kan jeg for eksempel skrive "velg å oppdatere" og vente 50 sekunder før jeg oppdaterer. Det var bra for søknaden. Men i Postgres må jeg enten gjøre det med en gang og ikke vente i det hele tatt, eller vente til en stund.

Ja, du kan velge en tidsavbrudd på låsene dine, på låsene dine. Du kan også gi en no way-kommando, som vil... hvis du ikke umiddelbart kan få tak i låsen. Derfor enten en låsetid eller noe annet som lar deg gjøre dette. Dette gjøres ikke på syntaktisk nivå. Dette gjøres som en variabel på serveren. Noen ganger kan dette ikke brukes.

Kan du åpne lysbilde 75?

Ja.

Låser opp Postgres Lock Manager. Bruce Momjian

Og spørsmålet mitt er følgende. Hvorfor forventer begge oppdateringsprosessene 703?

Og dette er et flott spørsmål. Jeg forstår forresten ikke hvorfor Postgres gjør dette. Men da 703 ble opprettet, ventet den 702. Og når 704 og 705 dukker opp, virker det som om de ikke vet hva de forventer fordi det ikke er noe der ennå. Og Postgres gjør det på denne måten: når du ikke kan få en lås, skriver den "Hva er vitsen med å behandle deg?", fordi du allerede venter på noen. Så vi lar det bare henge i luften, det vil ikke oppdatere det i det hele tatt. Men hva skjedde her? Så snart 702 fullførte prosessen og 703 mottok låsen, kom systemet tilbake. Og hun sa at nå har vi to personer som venter. Og så la oss oppdatere dem sammen. Og la oss indikere at begge venter.

Jeg vet ikke hvorfor Postgres gjør dette. Men det er et problem som heter f…. Det virker for meg som om dette ikke er et begrep på russisk. Dette er når alle venter på ett slott, selv om det er 20 myndigheter som venter på slottet. Og plutselig våkner de alle samtidig. Og alle begynner å prøve å reagere. Men systemet gjør det slik at alle venter på 703. For de venter alle, og vi skal umiddelbart stille dem i kø. Og hvis det dukker opp en ny forespørsel som ble generert etter dette, for eksempel 707, vil det bli tomhet igjen.

Og det virker for meg som om dette er gjort slik at vi kan si at på dette stadiet venter 702 på 703, og alle de som kommer etter det vil ikke ha noen oppføring i dette feltet. Men så snart den første servitøren går, får alle de som ventet i det øyeblikket før oppdateringen samme token. Og så tror jeg dette er gjort slik at vi kan behandle i orden slik at de blir riktig bestilt.

Jeg har alltid sett på dette som et ganske merkelig fenomen. Fordi her, for eksempel, lister vi dem ikke opp i det hele tatt. Men det virker på meg som at hver gang vi gir en ny lås, ser vi på alle de som er i ferd med å vente. Så stiller vi dem alle sammen. Og så kommer en ny som kommer inn først i køen når neste person er ferdig behandlet. Veldig godt spørsmål. Tusen takk for spørsmålet ditt!

Det virker for meg som det er mye mer logisk når 705 forventer 704.

Men problemet her er følgende. Teknisk sett kan du vekke den ene eller den andre. Og så vil vi våkne den ene eller den andre. Men hva skjer i systemet? Du kan se hvordan 703 helt øverst har blokkert sin egen transaksjons-ID. Slik fungerer Postgres. Og 703 er blokkert av sin egen transaksjons-ID, så hvis noen ønsker å vente, vil de vente på 703. Og i hovedsak fullføres 703. Og først etter at den er fullført, våkner en av prosessene. Og vi vet ikke nøyaktig hva denne prosessen vil være. Så behandler vi alt gradvis. Men det er ikke klart hvilken prosess som vekkes først, fordi det kan være hvilken som helst av disse prosessene. I hovedsak hadde vi en planlegger som sa at vi nå kan vekke noen av disse prosessene. Vi velger bare en tilfeldig. Så begge må noteres fordi vi kan vekke begge.

Og problemet er at vi har CP-uendelighet. Og derfor er det ganske sannsynlig at vi kan vekke den senere. Og hvis vi for eksempel vekker den senere, vil vi vente på den som nettopp mottok blokken, så vi bestemmer ikke hvem som skal vekkes først. Vi skaper rett og slett en slik situasjon, og systemet vil vekke dem i en tilfeldig rekkefølge.

Det er artikler om låser av Egor Rogov. Se, de er også interessante og nyttige. Temaet er selvfølgelig fryktelig komplekst. Tusen takk, Bruce!

Kilde: www.habr.com

Legg til en kommentar