PostgreSQL:n sisäisten mekanismien toimintatapa mahdollistaa sen, että se on joissakin tilanteissa erittäin nopea ja toisissa taas hitaampi. Tänään tarkastelemme klassista esimerkkiä ristiriidasta tietokannan hallintajärjestelmän toiminnan ja kehittäjän toiminnan välillä: UPDATE vs. MVCC -periaatteet.
Lyhyt juoni :
Kun riviä muokataan UPDATE-komennolla, suoritetaan itse asiassa kaksi toimintoa: DELETE ja INSERT. linjan nykyinen versio xmax asetetaan UPDATE-komennon suorittaneen tapahtuman numeroksi. Sitten se luodaan uusi versio samalla rivillä; sen xmin-arvo vastaa edellisen version xmax-arvoa.
Jonkin ajan kuluttua tämän tapahtuman valmistumisesta vanha tai uusi versio, riippuen COMMIT/ROOLBACK, tullaan tunnistamaan kuolleet tuplet ohittaessa VACUUM taulukon mukaan ja tyhjennetty.

Mutta tämä ei tapahdu heti, vaan ongelmia "kuolleiden" kanssa voidaan saada hyvin nopeasti - toistuvilla tai suuressa pöydässä ja hieman myöhemmin kohtaavat tilanteen, jossa .
#1: Tykkään liikutella sitä
Oletetaan, että liiketoimintalogiikkamenetelmäsi on käynnissä ja yhtäkkiä huomaa, että sen on päivitettävä kenttä X jossakin tietueessa:
UPDATE tbl SET X = <newX> WHERE pk = $1;Sitten suorituksen edetessä se huomaa, että myös Y-kenttä on päivitettävä:
UPDATE tbl SET Y = <newY> WHERE pk = $1;...ja sitten on vielä Z – miksi vaivautua pieniin asioihin?
UPDATE tbl SET Z = <newZ> WHERE pk = $1;Kuinka monta versiota tästä merkinnästä meillä on nyt tietokannassa? Kyllä, neljä! Yksi niistä on ajan tasalla, ja kolme pitää siivota [auto]VACUUM-komennolla.
Älä tee niin! Käytä sitä! kaikkien kenttien päivittäminen yhdellä pyynnöllä — lähes aina metodin logiikkaa voidaan muuttaa näin:
UPDATE tbl SET X = <newX>, Y = <newY>, Z = <newZ> WHERE pk = $1;#2: Käyttö ON ERILLISTÄ KUIN, Luke!
Joten halusit silti (esimerkiksi skriptiä tai muunninta käytettäessä). Ja skriptiin lisätään jotain tällaista:
UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2;Tämän muotoinen pyyntö kohtaa melko usein, ja lähes aina ei uuden tyhjän kentän täyttämiseksi, vaan joidenkin tietovirheiden korjaamiseksi. olemassa olevien tietojen oikeellisuutta ei oteta lainkaan huomioon – mutta turhaan! Eli merkintä on kirjoitettu uudelleen, vaikka se sisältäisi juuri sen, mitä halusin – mutta miksi vaivautua? Korjataanpa se:
UPDATE tbl SET X = <newX> WHERE pk BETWEEN $1 AND $2 AND X IS DISTINCT FROM <newX>; Monet ihmiset eivät ole tietoisia tällaisen upean operaattorin olemassaolosta, joten tässä on lunttilappu IS DISTINCT FROM ja muita loogisia operaattoreita avuksi:

...ja hieman monimutkaisten operaatioiden suorittamisesta ROW()-lausekkeet:

#3: Tunnistan rakkaani… estämällä
He ovat käynnistämässä kaksi identtistä rinnakkaista prosessia, joista jokainen yrittää merkitä tallennuksen ”keskeneräiseksi”:
UPDATE tbl SET processing = TRUE WHERE pk = $1;Vaikka nämä prosessit suorittaisivat itsenäisiä tehtäviä saman tunnuksen sisällä, toinen asiakas "lukitaan" tässä pyynnössä, kunnes ensimmäinen tapahtuma on suoritettu.
Ratkaisu nro 1: tehtävä supistuu edelliseen tehtävään
Lisätään se vielä uudestaan IS DISTINCT FROM:
UPDATE tbl SET processing = TRUE WHERE pk = $1 AND processing IS DISTINCT FROM TRUE;Tässä muodossa toinen kysely ei yksinkertaisesti muuta mitään tietokannassa; kaikki on jo "niin kuin sen pitäisi olla" – joten estoa ei tapahdu. Sovellusalgoritmi käsittelee sitten sen, että tietuetta "ei löytynyt".
Ratkaisu nro 2: neuvoa-antavat lukot
Tämä on iso aihe erilliselle artikkelille, josta voit lukea siitä lisää. .
Ratkaisu nro 3: tyhmiä puheluita
Mutta juuri näin pitäisi käydä sinulle. samanaikainen työskentely saman tietueen kanssaTai ehkä esimerkiksi mokasit asiakaspuolen liiketoimintalogiikan kutsualgoritmit? Mutta jos ajattelet asiaa...
Lähde: will.com
