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

INSERT ... SELECT, InnoDB und Sperren

Das ist richtig. Die Zeilen in der Tabelle, aus der gelesen wird, werden mit einer gemeinsamen Sperre (der SELECT ist implizit LOCK IN SHARE MODE ). Es gibt keine Möglichkeit, dies zu vermeiden. Es ist eine Art, worum Sie das System bitten:Kopieren Sie alle Zeilen, die einer Bedingung entsprechen. Die einzige Möglichkeit sicherzustellen, dass tatsächlich alle Zeilen der Bedingung entsprechen und dass sich diese Liste während oder unmittelbar nach der Ausführung dieser Anweisung nicht ändert, besteht darin, die Zeilen zu sperren.

Zur Klarstellung, warum Sie INSERT nicht ausführen können mit group_id = 2 :

Dies hat damit zu tun, dass Ihre Abfrage genau WHERE group_id = 3 AND created < '2014-01-04' erstellt wurde auf KEY group_id_created (group_id, created) . Um alle Zeilen zu suchen, die mit group_id = 3 AND created < '2014-01-04' erstellt haben der Index wird rückwärts durchlaufen, beginnend mit der ersten Zeile, die diese Bedingung überschreitet, die Obergrenze, die (3, '2014-01-14') ist und fortfahren, bis eine Zeile gefunden wird, die nicht der Bedingung entspricht, die seit created wurde hat keine Untergrenze ist die erste Zeile, in der group_id < 3 ist was natürlich group_id = 2 ist .

Das bedeutet, dass die erste Zeile mit group_id = 2 angetroffen wird ist auch gesperrt, das ist die Zeile mit dem höchsten created Wert. Dadurch wird INSERT unmöglich in die "Lücke" zwischen (2, MAX(created)) und (3, MIN(created)) (natürlich kein richtiges SQL, nur Pseudo-SQL), obwohl dies nicht speziell eine "Lückensperre" ist.