Kann AUTO_INCREMENT sicher in einem BEFORE TRIGGER in MySQL verwendet werden

Die Postgres-Methode von Instagram zum Implementieren benutzerdefinierter IDs für Sharding ist großartig, aber ich benötige die Implementierung in MySQL.

So habe ich die Methode konvertiert, die am Ende dieses Blogs zu finden ist, hier:http: //instagram-engineering.tumblr.com/post/10853187575/sharding-ids-at-instagra

MySQL Version:

CREATE TRIGGER shard_insert BEFORE INSERT ON tablename
FOR EACH ROW BEGIN

DECLARE seq_id BIGINT;
DECLARE now_millis BIGINT;
DECLARE our_epoch BIGINT DEFAULT 1314220021721;
DECLARE shard_id INT DEFAULT 1;

SET now_millis = (SELECT UNIX_TIMESTAMP(NOW(3)) * 1000);
SET seq_id = (SELECT AUTO_INCREMENT FROM information_schema.TABLES WHERE TABLE_SCHEMA = "dbname" AND TABLE_NAME = "tablename");
SET NEW.id = (SELECT ((now_millis - our_epoch) << 23) | (shard_id << 10) | (SELECT MOD(seq_id, 1024)));
END

Die Tabelle sieht ungefähr so aus:

CREATE TABLE tablename (
    id BIGINT AUTO_INCREMENT,
    ...
)

Frage

Hier liegt ein Parallelitätsproblem vor. Wenn ich 100 Threads spawne und Inserts ausführe, erhalte ich doppelte Sequenzwerte, was bedeutet, dass zwei Trigger denselben Wert für auto_increment erhalten. Wie kann ich das beheben?

Ich habe versucht, eine neue Tabelle zu erstellen, z. "tablename_seq", mit einer Zeile, einem Zähler zum Speichern meiner eigenen Auto_Increment-Werte und anschließenden Aktualisierungen dieser Tabelle im TRIGGER. Das Problem ist jedoch, dass ich die Tabelle in einer gespeicherten Prozedur (Trigger) nicht SPERREN kann Genau das gleiche Problem, ich kann nicht garantieren, dass ein Zähler zwischen den Triggern eindeutig ist: (.

Ich bin ratlos und würde mich über tipps wirklich freuen!

Mögliche Lösung

MySQL 5.6 verfügt über UUID_SHORT (), das eindeutige inkrementelle Werte generiert, die garantiert eindeutig sind. In der Praxis zeigt sich beim Aufruf, dass jeder Aufruf den Wert +1 erhöht. Mit: SET seq_id = (SELECT UUID_SHORT ()); es scheint, das Parallelitätsproblem zu entfernen. Der Nebeneffekt davon ist, dass jetzt (ungefähr) nicht mehr als 1024 Einfügungen pro Millisekunde im gesamten System passieren können. Wenn mehr tun, ist es möglich, dass ein DUPLICATE PRIMARY KEY-Fehler auftritt. Die gute Nachricht ist, dass ich in Benchmarks auf meinem Computer ~ 3.000 Einfügungen / s mit oder ohne den Trigger bekomme, der UUID_SHORT () enthält, sodass es anscheinend überhaupt nicht langsamer wird.

Antworten auf die Frage(2)

Ihre Antwort auf die Frage