sql >> Databáze >  >> RDS >> PostgreSQL

Zámek a transakce v postgresu, které by měly zablokovat dotaz

Chování, které popisujete, je normální a očekávané v jakékoli transakční relační databázi.

Pokud vám PostgreSQL ukázal hodnotu edited pro první SELECT bylo by to špatné – říká se tomu „špinavé čtení“ a v databázích je to špatná zpráva.

PostgreSQL by mohl čekat na SELECT dokud se nepotvrdíte nebo nevrátite zpět, ale nevyžaduje to standard SQL, neřekli jste mu, že chcete čekat, a nemusí čekat z jakéhokoli technického důvodu, takže vrátí data, která jste požadovali pro okamžitě. Koneckonců, dokud to není potvrzeno, update existuje pouze druh – stále se to může nebo nemusí stát.

Pokud by zde PostgreSQL vždy čekal, pak byste se rychle dostali do situace, kdy by s databází mohlo v jednu chvíli cokoliv dělat pouze jedno připojení. Není to hezké pro výkon a ve většině případů je to zcela zbytečné.

Pokud chcete počkat na souběžnou UPDATE (nebo DELETE ), použijete SELECT ... FOR SHARE . (Uvědomte si však, že to nebude fungovat pro INSERT ).

Podrobnosti:

SELECT bez FOR UPDATE nebo FOR SHARE klauzule nebere žádné zámky na úrovni řádku. Vidí tedy cokoli, co je aktuální potvrzený řádek, a není ovlivněn žádnými transakcemi během letu, které by mohly tento řádek upravovat. Koncepty jsou vysvětleny v sekci MVCC v dokumentech . Obecnou myšlenkou je, že PostgreSQL je copy-on-write, s verzováním, které mu umožňuje vrátit správnou kopii na základě toho, co transakce nebo příkaz mohl „vidět“ v době, kdy začal – co PostgreSQL nazývá „snímek“.

Ve výchozím nastavení READ COMMITTED snímky izolace se pořizují na úrovni příkazů, takže pokud SELECT řádek, COMMIT změna z jiné transakce a SELECT opět uvidíte různé hodnoty i v rámci jedné transakce. Můžete použít SNAPSHOT izolace, pokud nechcete vidět změny provedené po zahájení transakce, nebo SERIALIZABLE izolace pro přidání další ochrany proti určitým druhům vzájemných závislostí transakcí.

Viz kapitola o izolaci transakcí v dokumentaci .

Pokud chcete SELECT chcete-li čekat na potvrzení probíhajících transakcí nebo vrácení změn ve vybraných řádcích, musíte použít SELECT ... FOR SHARE . Tím se zablokuje zámek přijatý UPDATE nebo DELETE dokud se transakce, která zámek vzala, nevrátí zpět nebo se potvrdí.

INSERT je však jiný - n-tice prostě neexistují pro jiné transakce, dokud se nepotvrdí. Jediný způsob, jak čekat na souběžné INSERT s je vzít EXCLUSIVE zámek na úrovni tabulky, takže víte, že nikdo jiný nemění tabulku, když ji čtete. Obvykle to znamená, že máte v aplikaci problém s návrhem – vaší aplikaci by to nemělo být zajímavé pokud existují nepotvrzené insert je stále v letu.

Viz kapitolu o explicitním zamykání v dokumentaci .



  1. jak získat čas načítání v milisekundách nebo mikrosekundách v mysql

  2. efektivní způsob, jak otestovat, zda existuje řádek tabulky

  3. obnovení mysql do jiné databáze

  4. ověření schématu pole django postgresql json