Question

Nous utilisons beaucoup MySQL avec le moteur de stockage InnoDB et les transactions. Nous avons rencontré un problème: nous avons besoin d’un moyen agréable d’émuler les SEQUENCE d’Oracle dans MySQL. Les exigences sont:  - prise en charge de la concurrence  - sécurité des transactions  - performances maximales (minimisation des verrouillages et des blocages)

Peu nous importe que certaines des valeurs ne soient pas utilisées, c’est-à-dire que les trous dans l’ordre sont corrects. Il existe un moyen simple de résoudre ce problème en créant une table InnoDB distincte avec un compteur. Toutefois, cela signifie qu’elle prendra part à la transaction et introduira des verrous et l’attente. Je pense essayer une table MyISAM avec des serrures manuelles, d’autres idées ou de meilleures pratiques?

Était-ce utile?

La solution

Si l'incrémentation automatique ne convient pas à vos besoins, vous pouvez créer un mécanisme de séquence atomique avec n séquences nommées comme ceci:

Créez un tableau pour stocker vos séquences:

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

En supposant que vous ayez une ligne pour "foo" dans le tableau, vous pouvez obtenir de manière atomique le prochain identifiant de séquence comme ceci:

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

Aucun verrou requis. Les deux instructions doivent être exécutées dans la même session pour que la variable locale @next soit réellement définie lorsque la sélection a lieu.

Autres conseils

La indique comment procéder. Manuel MySQL :

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

Nous sommes une société de jeux à forte transaction et avons besoin de ce type de solutions pour nos besoins. L'une des caractéristiques des séquences Oracle était également la valeur d'incrément qui pouvait également être définie.

La solution utilise CLE DUPLICATE .

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

Pour obtenir le prochain index:

Résumé de ce qui suit avec une procédure stockée ou une fonction 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";

La colonne MySQL Identity de la table ne gérera-t-elle pas ce problème?

CREATE TABLE nom_table (    id INTEGER AUTO_INCREMENT PRIMARY KEY )

Ou cherchez-vous à l'utiliser pour autre chose que simplement insérer dans une autre table?

Si vous écrivez en utilisant également un langage procédural (au lieu de SQL uniquement), l’autre option consisterait à créer une table contenant un seul entier (ou un entier long) et une procédure stockée le verrouillant, sélectionnée dans il l'a incrémenté et déverrouillé avant de renvoyer la valeur.

(Remarque - incrémentez toujours avant de renvoyer la valeur - cela maximise les chances de ne pas obtenir de doublons s'il y a des erreurs - ou encapsule le tout dans une transaction.)

Vous l'appelez alors indépendamment de votre insertion / mise à jour principale (afin d'éviter toute capture dans les transactions créées automatiquement par le mécanisme d'appel), puis transmettez-le en tant que paramètre à l'endroit où vous souhaitez l'utiliser.

Parce que cela dépend du reste de ce que vous faites, cela devrait être rapide et éviter les problèmes de verrouillage. Même si vous avez constaté une erreur provoquée par le verrouillage (peu probable si vous surchargez la base de données), vous pouvez simplement l'appeler une deuxième / troisième fois.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top