2016-04-29 14 views
0

Ich habe eine Tabelle 'klickt', wo ich den Datensatz jedes Mal hinzufügen, wenn Benutzer spezielle Zähler Skript click.php navigiert. Diese Tabelle hat keine Autoinkrement-Spalte. Sie hat transaction_id CHAR(32) als Primärschlüssel, der vor dem Einfügen eines neuen Datensatzes zufällig generiert wird. Jeder neue Datensatz hat die Spalte normalized=0.MYSQL: Deadlock mit einfachen Abfragen

Alle 3 Minuten Hintergrund Daemon startet eine Transaktion, liest alle neuen Klicks WHERE normalized=0 und gruppiert es in Tabelle stats. Die einzige Schreibabfrage für diese Tabelle ist UPDATE clicks SET normalized=1 WHERE normalized=0, die am Ende aller Verarbeitungen ausgeführt wird und dann die Transaktion festschreibt.

Problem ist, dass jedes Mal, wenn click.php während dieser Transaktion navigiert wird, kann das Skript nicht um einen neuen Datensatz ‚Klicks‘ hinzufügen und wird mit Fehler:

SQLSTATE[40001]: Serialization failure: 
1213 Deadlock found when trying to get lock; try restarting transaction 

    INSERT `clicks` 
    SET `transaction_id`='3520359d597ba05b635ff15feb334229', 
     `time`='2016-04-29 15:14:31', 
     ..., 
     `normalized`='0' 

Ich weiß, dass ich dieses Problem lösen kann mit LOCK TABLES, aber ich möchte nur wissen, warum dieser Deadlock auftritt.

UPD: Ich sehe folgenden Grund in SHOW ENGINE BDB STATUS-Ausgang:

*** (1) WAITING FOR THIS LOCK TO BE GRANTED: 
RECORD LOCKS space id 252763 page no 124 n bits 480 index `normalized` 
of table `tds`.`clicks` trx id C1329EF lock_mode X locks gap before 
rec insert intention waiting 

Antwort

0

(dies sollte ein Kommentar sein, aber seine lange und beteiligt)

Was ist die Transaktion Isolationsmodus?

Ich bin noch nie zuvor darauf gestoßen - vor allem, weil ich die Verwendung von Multi-Konto-Transaktionen vermeiden, z.

UPDATE clicks 
SET normalized=2 
WHERE normalized=0; 

INSERT INTO stats (transaction_id, clicks) 
SELECT transaction_id, COUNT(*) 
FROM clicks 
WHERE normalized=2 
GROUP BY transaction_id; 

UPDATE clicks 
SET transaction_id=1 
WHERE transaction_id=2; 

Es gibt Möglichkeiten, dies zu der Klicks Tabelle mit einem einzigen Update zu tun, wenn Sie eine separate Spalte und eine generierte Kennung für den Datensatz verwenden. Und wenn Sie dies von cron aus ausführen, sollten Sie diese wahrscheinlich in einen GET_LOCK() ... RELEASE_LOCK() - Zyklus einschließen, um Nebenläufigkeit zu verhindern. Obwohl das Modell die Nebenläufigkeit für die meisten Transaktionsmodelle unterstützt, ist es ein bisschen Leistung, wenn die Dinge bereits schlecht laufen.