Mysql
 sql >> Datenbank >  >> RDS >> Mysql

Wie werden innodb-Tabellen gesperrt, wenn der ON INSERT-Trigger verarbeitet wird?

Was die Nebenläufigkeitsprobleme angeht, haben Sie ein 'einfaches' Um Parallelitätsprobleme bei der zweiten Methode zu vermeiden, führen Sie in Ihrer Transaktion eine Auswahl in der Artikelzeile durch (die For update ist jetzt implizit). Jede gleichzeitige Einfügung für denselben Artikel kann diese Sperre nicht erhalten und wartet auf Sie.

Mit den neuen Standard-Isolationsstufen würden Sie bis zum Ende Ihrer Transaktion keine gleichzeitige Einfügung in der Abstimmungstabelle sehen, ohne die Serialisierungsstufe in der Transaktion zu verwenden. Ihre SUM sollte also kohärent bleiben oder wie kohärent aussehen . Aber wenn eine gleichzeitige Transaktion eine Stimme für denselben Artikel einfügt und vor Ihnen festschreibt (und diese zweite Transaktion Ihre Einfügung nicht sieht), überschreibt die letzte festzuschreibende Transaktion den Zähler und Sie verlieren 1 Stimme. Führen Sie also eine Zeilensperre für den Artikel durch, indem Sie vorher auswählen (und natürlich Ihre Arbeit in einer Transaktion erledigen). Es ist einfach zu testen, öffnen Sie 2 interaktive Sitzungen auf MySQL und starten Sie Transaktionen mit BEGIN.

Wenn Sie den Trigger verwenden, befinden Sie sich standardmäßig in einer Transaktion. Aber ich denke, Sie sollten auch die Auswahl in der Artikeltabelle durchführen, um eine implizite Zeilensperre für gleichzeitig ausgeführte Trigger zu erstellen (schwieriger zu testen).

  • Lösch-Trigger nicht vergessen.
  • Update-Trigger nicht vergessen.
  • Wenn Sie keine Trigger und keinen Stayin-Code verwenden, achten Sie darauf, dass jede Einfüge-/Lösch-/Aktualisierungsabfrage bei Abstimmungen eine Zeilensperre für den entsprechenden Artikel vor der Transaktion ausführt. Es ist nicht sehr schwer, einen zu vergessen.

Letzter Punkt:Machen Sie schwierigere Transaktionen, bevor Sie mit der Transaktion beginnen:

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

Auf diese Weise benötigen Sie keine Zeilensperren für Artikel, MySQL erkennt, dass ein potenzieller Schreibvorgang in derselben Zeile stattfindet, und blockiert die anderen Transaktionen, bis Sie fertig sind. Aber verwenden Sie nichts, was Sie aus einer früheren Anfrage berechnet haben . Die Aktualisierungsabfrage wartet auf eine Sperrfreigabe für Artikel, wenn die Sperre durch die 1. Transaktion COMMIT aufgehoben wird die Berechnung von SUM sollte erneut gezählt werden. Die Aktualisierungsabfrage sollte also den SUM enthalten oder fügen Sie etwas hinzu.

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

Und hier werden Sie sehen, dass MySQL schlau ist, ein Deadlock wird erkannt, wenn 2 Transaktionen dies versuchen, während gleichzeitig Einfügungen durchgeführt wurden. In Serialisierungsebenen habe ich keinen Weg gefunden, mit :

einen falschen Wert zu erhalten
   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;

Aber seien Sie darauf vorbereitet, fehlerhafte Transaktionen zu handhaben, die Sie wiederholen müssen.