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

Wie sperre ich eine InnoDB-Zeile, die noch nicht existiert?

Während die obige Antwort insofern wahr ist, als ein SELECT ... FOR UPDATE verhindert, dass gleichzeitige Sitzungen / Transaktionen denselben Datensatz einfügen, ist dies nicht die volle Wahrheit. Ich kämpfe derzeit mit dem gleichen Problem und bin zu dem Schluss gekommen, dass SELECT ... FOR UPDATE in dieser Situation aus folgendem Grund fast nutzlos ist:

Eine gleichzeitige Transaktion / Sitzung kann auch ein SELECT ... FOR UPDATE für denselben Datensatz- / Indexwert ausführen, und MySQL akzeptiert dies sofort (nicht blockierend) und ohne Fehler zu werfen. Sobald die andere Session das erledigt hat, kann natürlich auch Ihre Session den Datensatz nicht mehr einfügen. Weder Ihre noch die andere Sitzung / Transaktion erhalten Informationen über die Situation und glauben, dass sie den Datensatz sicher einfügen können, bis sie dies tatsächlich versuchen. Der Versuch, dann einzufügen, führt je nach Umständen entweder zu einem Deadlock oder zu einem Duplikat-Schlüssel-Fehler.

Mit anderen Worten, SELECT ... FOR UPDATE verhindert, dass andere Sitzungen die entsprechenden Datensätze einfügen, ABER selbst wenn Sie SELECT ... FOR UPDATE ausführen und die entsprechenden Datensätze nicht gefunden werden, besteht die Möglichkeit, dass Sie dies tatsächlich nicht können fügen Sie diesen Datensatz ein. IMHO, das macht die Methode "erst abfragen, dann einfügen" unbrauchbar.

Die Ursache des Problems liegt darin, dass MySQL keine Methode dazu wirklich anbietet nicht vorhandene Datensätze sperren. Zwei gleichzeitige Sitzungen / Transaktionen können gleichzeitig nicht existierende Datensätze "FOR UPDATE" sperren, was eigentlich nicht möglich sein sollte und die Entwicklung erheblich erschwert.

Die einzige Möglichkeit, dies zu umgehen, scheint die Verwendung von Semaphor-Tabellen oder das Sperren der gesamten Tabelle beim Einfügen zu sein. Weitere Informationen zum Sperren ganzer Tabellen oder zur Verwendung von Semaphor-Tabellen finden Sie in der MySQL-Dokumentation.

Nur meine 2 Cent ...