sql >> Database >  >> RDS >> PostgreSQL

Predicaatvergrendeling in PostgreSQL 9.2.1 met serialiseerbare isolatie

Van de Transaction Isolation pagina:

Een EXPLAIN op die SELECT kan je vertellen wat het queryplan is, maar als de tabel klein (of leeg!) is, zal PostgreSQL vrijwel zeker een sequentiële scan kiezen in plaats van naar de index te verwijzen. Dit veroorzaakt een predikaatslot op de hele tafel, waardoor de serialisatie mislukt wanneer een andere transactie iets met de tafel doet.

Op mijn systeem:

isolation=# EXPLAIN SELECT * from mydevice where cid = 1;
                        QUERY PLAN                        
----------------------------------------------------------
 Seq Scan on mydevice  (cost=0.00..23.38 rows=5 width=46)
   Filter: (cid = 1)
(2 rows)

Je zou kunnen proberen een index toe te voegen en deze te dwingen die te gebruiken:

isolation=# CREATE INDEX mydevice_cid_key ON mydevice (cid);
CREATE INDEX
isolation=# SET enable_seqscan = off;
SET
isolation=# EXPLAIN SELECT * from mydevice where cid = 1;
                                    QUERY PLAN                                    
----------------------------------------------------------------------------------
 Index Scan using mydevice_cid_key on mydevice  (cost=0.00..8.27 rows=1 width=46)
   Index Cond: (cid = 1)
(2 rows)

Dit is echter niet de juiste oplossing. Laten we even een back-up maken.

Serializable is bedoeld om te garanderen dat transacties precies hetzelfde effect hebben als wanneer ze na elkaar worden uitgevoerd, ondanks het feit dat u deze transacties eigenlijk gelijktijdig uitvoert. PostgreSQL heeft geen oneindige bronnen, dus hoewel het waar is dat het predikaatvergrendelingen plaatst op gegevens waartoe uw zoekopdracht daadwerkelijk toegang heeft, kan 'gegevens' meer betekenen dan 'teruggegeven rijen'.

PostgreSQL kiest ervoor om serialisatiefouten te markeren wanneer het denkt dat er een probleem is, niet wanneer het zeker is. (Vandaar hoe het rijvergrendelingen generaliseert naar paginavergrendelingen.) Deze ontwerpkeuze veroorzaakt valse positieven, zoals die in uw voorbeeld. Valse positieven zijn niet ideaal, maar het heeft geen invloed op de juistheid van de isolatiesemantiek.

De foutmelding is:

ERROR:  could not serialize access due to read/write dependencies among transactions
DETAIL:  Reason code: Canceled on identification as a pivot, during commit attempt.
HINT:  The transaction might succeed if retried.

Die hint is de sleutel. Uw toepassing moet serialisatiefouten opvangen en de hele bewerking opnieuw proberen . Dit is waar wanneer SERIALIZABLE is in het spel -- het garandeert seriële correctheid ondanks gelijktijdigheid, maar het kan dat niet doen zonder de hulp van uw toepassing. Anders gezegd, als u daadwerkelijk gelijktijdige wijzigingen aan het doen bent, is de enige manier waarop PostgreSQL aan de isolatievereisten kan voldoen, door uw toepassing te vragen zichzelf te serialiseren. Dus:



  1. voeg alle rijen kolommen samen in een enkele kolom van samengevoegde tabel

  2. chmod mislukt:EPERM (bewerking niet toegestaan) in Android?

  3. Hoe IDENTITY_INSERT in- en uitschakelen met SQL Server 2008?

  4. Live zoeken met Codeigniter Mysql