sql >> Database >  >> RDS >> Mysql

Hoe worden innodb-tabellen vergrendeld wanneer de ON INSERT-trigger wordt verwerkt?

Over de gelijktijdigheidsproblemen, je hebt een 'easy' manier om gelijktijdigheidsproblemen in de 2e methode te voorkomen, voert u binnen uw transactie een selectie uit op de artikelregel (de For update is nu impliciet). Elke gelijktijdige invoeging op hetzelfde artikel zal niet in staat zijn om hetzelfde slot te verkrijgen en zal op u wachten.

Met de nieuwe standaard isolatieniveaus, zonder zelfs het serialisatieniveau in de transactie te gebruiken, ziet u geen gelijktijdige invoeging op de stemtafel tot het einde van uw transactie. Uw SUM moet dus coherent blijven of er coherent uitzien . Maar als een gelijktijdige transactie een stem invoegt op hetzelfde artikel en vóór u vastlegt (en deze 2e ziet uw invoeging niet), zal de laatste transactie die moet worden uitgevoerd de teller overschrijven en verliest u 1 stem. Voer dus een rijvergrendeling op artikel uit door een select before te gebruiken (en natuurlijk je werk doen in een transactie). Het is gemakkelijk te testen, open 2 interactieve sessies op MySQL en start transacties met BEGIN.

Als je de trigger gebruikt, zit je standaard in een transactie. Maar ik denk dat je ook de selectie in de artikeltabel moet uitvoeren om een ​​impliciete rijvergrendeling te maken voor gelijktijdige triggers die worden uitgevoerd (moeilijker te testen).

  • Vergeet de verwijderingstriggers niet.
  • Vergeet update-triggers niet.
  • Als je geen triggers gebruikt en code blijft, wees dan voorzichtig dat elke query voor invoegen/verwijderen/bijwerken op stemmen een rijvergrendeling moet uitvoeren op het corresponderende artikel vóór in de transactie. Het is niet zo moeilijk om er een te vergeten.

Laatste punt:maak moeilijkere transacties, voordat u de transactie start, gebruik:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

Op deze manier heeft u geen rijvergrendelingen nodig voor artikelen, MySQL zal detecteren dat een mogelijke schrijfactie op dezelfde rij plaatsvindt en de andere transacties blokkeren totdat u klaar bent. Maar gebruik niet iets dat u op basis van een eerder verzoek hebt berekend . De update-query wacht op een ontgrendeling van het slot op artikelen, wanneer het slot wordt vrijgegeven door de 1e transactie COMMIT het berekenen van SUM moet opnieuw worden gedaan om te tellen. De update-query moet dus de SUM . bevatten of voeg een toevoeging toe.

update articles set nb_votes=(SELECT count(*) from vote) where id=2; 

En hier zul je zien dat MySQL slim is, een deadlock wordt gedetecteerd als 2 transacties dit proberen te doen terwijl invoegen tegelijkertijd is gedaan. In serialisatieniveaus heb ik geen manier gevonden om een ​​verkeerde waarde te verkrijgen met:

   SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
   BEGIN;
       insert into vote (...
       update articles set nb_votes=(
         SELECT count(*) from vote where article_id=xx
       ) where id=XX;
    COMMIT;

Maar wees voorbereid op het afhandelen van een transactie die u opnieuw moet doen.



  1. Een globale tijdelijke tabel maken in Oracle

  2. MySQL OP DUPLICATE KEY invoegen in een audit- of logtabel

  3. ORA-22905 - bij het opvragen van een tabeltype met een select-instructie

  4. Draait de server op host localhost (::1) en accepteert hij TCP/IP-verbindingen op poort 5432?