sql >> Database >  >> RDS >> PostgreSQL

Deadlocks in PostgreSQL bij het uitvoeren van UPDATE

In PostgreSQL worden de rijen vergrendeld wanneer ze worden bijgewerkt -- de manier waarop dit feitelijk werkt, is dat elke tuple (versie van een rij) een systeemveld heeft met de naam xmin om aan te geven welke transactie die tuple heeft gedaan (door invoegen of bijwerken) en een systeemveld met de naam xmax om aan te geven bij welke transactie die tuple is verlopen (door bijwerken of verwijderen). Wanneer u gegevens opent, wordt elke tuple gecontroleerd om te bepalen of deze zichtbaar is voor uw transactie, door uw actieve "snapshot" te vergelijken met deze waarden.

Als u een UPDATE uitvoert en een tuple die overeenkomt met uw zoekvoorwaarden heeft een xmin die het zichtbaar zou maken voor uw snapshot en een xmax van een actieve transactie, het blokkeert en wacht tot die transactie is voltooid. Als de transactie die de tuple als eerste heeft bijgewerkt, wordt teruggedraaid, wordt uw transactie geactiveerd en wordt de rij verwerkt; als de eerste transactie wordt vastgelegd, wordt uw transactie geactiveerd en wordt actie ondernomen afhankelijk van het huidige isolatieniveau van de transactie.

Het is duidelijk dat een impasse het gevolg is van het feit dat dit gebeurt met rijen in verschillende volgorde. Er is geen vergrendeling op rijniveau in RAM die voor alle rijen tegelijkertijd kan worden verkregen, maar als rijen in dezelfde volgorde worden bijgewerkt, kunt u de cirkelvormige vergrendeling niet hebben. Helaas is de voorgestelde IN(1, 2) syntaxis garandeert dat niet. Verschillende sessies kunnen verschillende kostenfactoren actief hebben, een "analyse"-taak op de achtergrond kan de statistieken voor de tabel wijzigen tussen het genereren van het ene plan en het andere, of het kan een seqscan gebruiken en worden beïnvloed door de PostgreSQL-optimalisatie die een nieuwe seqscan veroorzaakt om deel te nemen aan een die al bezig is en "rond te lussen" om schijf-I/O te verminderen.

Als u de updates één voor één in dezelfde volgorde, in applicatiecode of met behulp van een cursor uitvoert, heeft u alleen maar eenvoudige blokkeringen, geen deadlocks. In het algemeen zijn relationele databases echter vatbaar voor serialisatiefouten, en het is het beste om ze te benaderen via een raamwerk dat ze herkent op basis van SQLSTATE en de volledige transactie automatisch vanaf het begin opnieuw probeert. In PostgreSQL heeft een serialisatiefout altijd een SQLSTATE van 40001 of 40P01.

http://www.postgresql.org/docs/current/interactive/mvcc-intro.html




  1. Tijdelijke tabellen maken in SQL

  2. Hoe mysql-tabelrijen in kolommen te transponeren

  3. Galera Cluster Cloud-aanbiedingen vergelijken:deel één Amazon AWS

  4. SQLite - Gegevens verwijderen