Frage

Wir verwenden MySQL mit InnoDB und Transaktionen viel, und wir haben auf ein Problem stoßen: Wir brauchen eine nette Art von Oracle-Sequenzen in MySQL zu emulieren. Die Anforderungen sind:  - Parallelität Unterstützung  - Transaktionssicherheit  - max Leistung (dh Minimierung Sperren und Deadlocks)

Wir interessieren uns nicht, wenn einige der Werte nicht verwendet werden, das heißt Lücken in Folge sind ok. Es gibt eine einfache Möglichkeit, das archieve durch eine separate InnoDB-Tabelle mit einem Zähler zu schaffen, aber dies bedeutet, dass es Teil der Transaktion statt und wird Sperre einführen und warten. Ich denke eine MyISAM-Tabelle mit manueller Sperren, um zu versuchen, irgendwelche anderen Ideen oder Best Practices?

War es hilfreich?

Lösung

Wenn die automatische Erhöhung nicht gut genug für Ihre Bedürfnisse ist, können Sie eine unteilbare Sequenz Mechanismus schaffen, mit n genannt Sequenzen wie folgt aus:

Erstellen Sie eine Tabelle Ihre Sequenzen zu speichern:

CREATE TABLE sequence (
  seq_name varchar(20) unique not null,
  seq_current unsigned int not null
);

Angenommen, Sie eine Zeile für ‚foo‘ haben in der Tabelle können Sie atomar die nächste Sequenz-ID wie diese:

UPDATE sequence SET seq_current = (@next := seq_current + 1) WHERE seq_name = 'foo';
SELECT @next;

Keine Sperren erforderlich. Beiden Aussagen müssen in derselben Sitzung ausgeführt werden, so dass die lokale Variable @next tatsächlich definiert, wenn das Auswahl passiert.

Andere Tipps

Der richtige Weg, dies zu tun, ist in der MySQL-Handbuch :

UPDATE child_codes SET counter_field = LAST_INSERT_ID(counter_field + 1);
SELECT LAST_INSERT_ID();

Wir sind ein High-Transaktion Gaming-Unternehmen und brauchen diese Art von Lösungen für unsere Bedürfnisse. Eines der Merkmale von Oracle-Sequenzen war auch der Inkrementwert, der auch eingestellt werden.

Die Lösung verwendet DUPLICATE KEY.

CREATE TABLE sequences (
  id BIGINT DEFAULT 1,
  name CHAR(20),
  increment TINYINT,
  UNIQUE KEY(name)
);

Um den nächsten Index zu erhalten:

Zusammenfassung des folgend mit einer gespeicherten Prozedur oder einer Funktion sp_seq_next_val(VARCHAR):

INSERT INTO sequences (name) VALUES ("user_id") ON DUPLICATE KEY UPDATE id = id + increment;<br/>
SELECT id FROM sequences WHERE name = "user_id";

Wird nicht die MySQL Identitätsspalte auf dem Tisch damit umgehen?

TABLE table_name CREATE (    id INTEGER AUTO_INCREMENT PRIMARY KEY )

Oder suchen Sie es für etwas anderes zu verwenden als nur in einer anderen Tabelle einfügen?

Wenn Sie schreiben auch einen Verfahrenssprache (statt nur SQL), dann die andere Option wäre, eine Tabelle zu erstellen, eine einzelne ganze Zahl, die (oder Long-Integer-Wert) und eine gespeicherte Prozedur, die es gesperrt ist, ausgewählt aus es, erhöht sie und sperrte sie vor den Wert zurück.

(Hinweis - immer erhöhen, bevor Sie den Wert zurück - es die Chance nicht bekommen Duplikate maximieren, wenn es Fehler gibt -. Oder das Ganze in einer Transaktion wickeln)

Sie würden dann diese Haupt insert / update aufrufen unabhängig von Ihrem (damit es nicht in irgendwelchen Transaktionen automatisch durch den anrufenden Mechanismus geschaffen verfängt) und dann als Parameter übergeben, wo immer Sie wollen, es zu benutzen.

Weil es unabhängig vom Rest des Materials Sie tun es schnell sein sollte und Sperrprobleme vermeiden. Selbst wenn ein Fehler angezeigt hat, verursacht durch Sperren (unwahrscheinlich, es sei denn, Sie die Datenbank sind Überlastung) Sie könnte es nur nennen ein zweites / drittes Mal.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top