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 .