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 .