Eine einzelne Anweisung wie diese funktioniert genauso mit MyISAM oder InnoDB, mit einer Transaktion oder mit autocommit = ON. Es blockiert genug, um die Abfrage durchzuführen, wodurch die andere Verbindung blockiert wird. Wenn Sie fertig sind, wird die andere Verbindung fortgesetzt. In allen Fällen wird die Spalte bald um 11 dekrementiert.
Ein dritter Benutzer kann sehen, dass der Wert um 0 oder 4 oder 7 oder 11 dekrementiert wird. Die "sehr genaue Zeit" ist nicht wirklich möglich, da zu einem bestimmten Zeitpunkt bei der Ausführung jeder Anweisung eine Single-Threaded-Sperre aktiviert / gesetzt / was auch immer ist . Das heißt, sie werden serialisiert werden, nur so schnell , dass man es nicht sehen kann.
InnoDB sperrt nur Zeilen, keine Tabellen. (OK, DDL-Anweisung macht mutigere Sperren.)
Interessanter wird eine Transaktion, die zwei Dinge ändert oder die spürbar viel Zeit in Anspruch nimmt:
Absichtsfall: Einzelstück, aber Zeit in Anspruch:
BEGIN;
SELECT something;
think about it for a while
UPDATE that something;
COMMIT;
Die Auswahl muss folgendermaßen geschrieben werden:
SELECT something FOR UPDATE;
Dies sagt anderen Verbindungen "Ich beabsichtige, die Zeile zu aktualisieren; bitte vermasseln Sie mich nicht". (Ich spreche dieses Beispiel an, weil viele Neulinge diese Subtilität vermissen.)
Deadlock-Fall: Mit 2 Dingen herumspielen:
BEGIN; -- in one connection
UPDATE thing_1;
UPDATE thing_2;
COMMIT;
BEGIN; -- in another connection, at the "exact same time"
UPDATE thing_2;
UPDATE thing_1;
COMMIT;
Dies ist das klassische Beispiel für einen Deadlock - jeder greift nach einer Sache und greift dann nach der anderen. Es ist klar, dass es nicht zum Laufen gebracht werden kann. Eine Transaktion wird beendet. der andere vervollständigt. Daher müssen Sie nach Fehlern suchen, damit Sie sie entdecken können.
Die normale Reaktion auf einen Deadlock besteht darin, die gesamte fehlgeschlagene Transaktion erneut abzuspielen. Bis dahin wird die andere Verbindung nicht stören und sollte ohne Probleme fortgesetzt werden. (OK, eine weitere Verbindung könnte einen weiteren Deadlock verursachen.)
Verzögerungsfall: Wenn die beiden Verbindungen mehrere Dinge in derselben Reihenfolge erfassen, kann eine verzögert werden, bis die andere beendet ist. Damit dies nicht "ewig wartet", gibt es eine Standardeinstellung von 50 Sekunden innodb_lock_wait_timeout
. Ihr einfaches Paar UPDATEs
ist tatsächlich ein Beispiel für diesen Fall. Man wird sofort fertig sein; der andere bleibt stehen, bis der erste fertig ist.
Beachten Sie, wie ein Deadlock (in einigen Fällen) in eine Verzögerung umgewandelt werden kann, indem Sie die Dinge, die Sie berühren, konsequent anordnen.
autocommit = 1: Mit dieser Einstellung und ohne Aufruf BEGIN
ist jede Anweisung effektiv:
BEGIN;
your statement
COMMIT;
autocommit = 0: Dies ist ein Problem, das darauf wartet, passiert zu werden. Wenn Sie eine Schreibabfrage ausführen, BEGIN
wird implizit a generiert. Es liegt jedoch in Ihrer Verantwortung, eventuell etwas herauszugeben COMMIT
. Wenn Sie dies nicht tun, werden Sie sich fragen, warum Ihr System hängen bleibt. (Ein weiterer häufiger Fehler für Neulinge.) Mein Rat: "Niemals verwenden =0
".