sql >> Database >  >> RDS >> PostgreSQL

Bug in PostgreSQL-vergrendelingsmechanisme of verkeerd begrip van het mechanisme

Er is geen bug, en ik denk niet dat je iets verkeerd begrijpt; je mist gewoon een paar stukjes van de puzzel.

Externe sleutels worden intern geïmplementeerd met behulp van vergrendeling op rijniveau; vanaf Postgres 8.1 en tot 9.2, telkens wanneer u de referentietabel bijwerkt (apples in dit geval), wordt er een query gestart die SELECT FOR SHARE . doet op de tabel waarnaar wordt verwezen (trees ). Zodat SELECT FOR UPDATE in de eerste transactie blokkeert de SELECT FOR SHARE van de referentiële integriteit voor de tweede transactie. Dit is de oorzaak van het blok in het tweede commando.

Nu hoor ik je schreeuwen:"Wacht! Hoe komt het dat het op het tweede commando blokkeert en niet op het eerste? De uitleg is eigenlijk heel simpel -- dat is gewoon omdat er een eenvoudige optimalisatie is die de interne SELECT FOR SHARE overslaat wanneer de sleutel niet wordt gewijzigd. Dit is echter simplistisch omdat als u een tuple een tweede keer bijwerkt, deze optimalisatie niet wordt geactiveerd omdat het moeilijker is om de oorspronkelijke waarden op te sporen. Vandaar de blokkade.

Je vraagt ​​je misschien ook af waarom ik zei dat dit maximaal 9.2 is --- wat is er met 9.3? Het belangrijkste verschil is dat het in 9.3 SELECT FOR KEY SHARE gebruikt , wat een nieuw, lichter slotniveau is; het zorgt voor een betere gelijktijdigheid. Als u uw voorbeeld in 9.3 probeert en ook de SELECT FOR UPDATE . wijzigt om SELECT FOR NO KEY UPDATE (wat een lichtere modus is dan SELECT FOR UPDATE dat zegt dat je misschien de tuple gaat bijwerken, maar je belooft de primaire sleutel niet te wijzigen en belooft deze niet te verwijderen), je zou moeten zien dat het niet blokkeert. (U kunt ook een UPDATE proberen op de rij waarnaar wordt verwezen en als u de primaire sleutel niet wijzigt, wordt deze ook niet geblokkeerd.)

Dit 9.3-spul is geïntroduceerd door een patch van ondergetekende als http://git.postgresql.org/gitweb/?p=postgresql.git;a=commit;h=0ac5ad5134f2769ccbaefec73844f8504c4d6182 en ik denk dat het een behoorlijk coole hack was (het commit-bericht heeft wat meer details, als je om dat soort dingen geeft). Maar pas op, gebruik geen versies ouder dan 9.3.4 omdat die patch zo enorm complex was dat een paar serieuze bugs onopgemerkt bleven en we pas onlangs hebben opgelost.




  1. De 'volgende' rij selecteren met specifieke criteria in MySQL

  2. Is er een equivalent voor sp_getapplock, sp_releaseapplock in oracle?

  3. Een alias gebruiken voor de localhost-server in MySQL

  4. Een getal opmaken als valuta in MariaDB