Ich habe Tabelle tt_users
die id
als Primärschlüssel und Spalten state
(CHAR (1)), kann die "x" oder "y" und state_position
(INT) sein. Für diese Spalten gibt es keine Indizes. Speichermodul ist innodb.MySQL - Deadlock gefunden, wenn sie versuchen zu sperren zu bekommen
state_positions muss immer in Folge sein, und es kann nie eine doppelte Position für einen bestimmten Zustand, das heißt, wenn ich 5 Benutzer mit state ‚x‘ haben, müssen ihre state_positions sein 1,2,3,4,5
Dies ist die Abfrage ich renne, die Deadlocks Ursachen:
insert into `tt_users` (`state`, `state_position`)
values ('x',
(SELECT MAX(state_position) AS maxStatePosition
FROM tt_users AS u2
WHERE u2.state='x') + 1
)
Zum Testen eingefügt ich eine große Anzahl an Benutzern gleichzeitig, und jedes Mal, wenn ich bekam die Deadlockfehler.
Ich habe diesen Beitrag gelesen - How to avoid mysql 'Deadlock found when trying to get lock; try restarting transaction' aber ich habe nicht verstanden, was ich mit meiner Abfrage tun sollte, um Deadlocks zu verhindern, wenn das überhaupt möglich ist, da die Antwort auf diese Frage - Working around MySQL error "Deadlock found when trying to get lock; try restarting transaction" - Deadlocks passieren kann, egal was .
Die einzige Art, wie ich es geschafft, dies, zur Arbeit zu kommen und konsequent arbeiten, ist diese (Sprache PHP):
PDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
Dann manuell die Tabellensperren und läuft meine Frage:
SET autocommit=0;
LOCK TABLES
tt_users WRITE,
tt_users AS u2 WRITE;
insert into `tt_users` (`state`, `state_position`)
values ('x',
(SELECT MAX(state_position) AS maxStatePosition
FROM tt_users AS u2
WHERE u2.state='x') + 1
);
COMMIT;
UNLOCK TABLES;
Und dann:
PDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
Mit dieser Methode, die ich den Code 4 mal gleichzeitig lief, jede Instanz inser 2500 Benutzer, ohne Probleme.
Ist dies der einzige Weg, um dies zum Laufen zu bringen, oder kann ich mit hundertprozentiger Sicherheit Deadlocks verhindern, ohne die Tabelle manuell sperren zu müssen?
UPDATE:
Pro @ wallyk Antwort, habe ich versucht, die folgenden:
1) die Abfrage in einer Transaktion Einlochen - Deadlock noch Fehler
2) Starten der Transaktion mit WITH CONSISTENT SNAPSHOT
, READ WRITE
, READ ONLY
. Alle 3 Optionen müssen PDO::setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
eingestellt werden. WITH CONSISTENT SNAPSHOT
und READ WRITE
gab mir immer noch Deadlock-Fehler, während READ ONLY
natürlich nicht einmal erlauben, dass ich die INSERT
ausführen.
So für den Moment scheint es manuell Sperren der Tabelle ist die einzige Sache, die funktioniert.
Danke, ich werde alle diese versuchen und mit Ergebnissen zurückkommen. – GTCrais
Aktualisierte Frage mit Ergebnissen, nachdem Sie Ihren Vorschlag ausprobiert haben. Leider hat es nicht funktioniert. – GTCrais