2009-10-21 6 views
0

Je lisais juste How to avoid a database race condition when manually incrementing PK of new row.Est-ce que cette requête me garantit une valeur PK «sans race»?

Il y avait beaucoup de bonnes suggestions comme avoir une table séparée pour obtenir les valeurs PK.

Je me demande donc si une requête comme ceci:

INSERT INTO Party VALUES(
    (SELECT MAX(id)+1 FROM 
     (SELECT id FROM Party) as x), 
'A-XXXXXXXX-X','Joseph') 

pourrait éviter les conditions de course?

L'ensemble de la déclaration est-il garanti atomique? Est-ce pas dans mysql? postgresql?

Répondre

2

Cela fonctionnerait sur les tables qui utilisent le verrouillage au niveau de la table (MyISAM), mais sur Innodb etc, cela pourrait bloquer ou produire des clés dupliquées, je pense, en fonction du niveau d'isolation utilisé.

Dans tous les cas, cela est une très mauvaise idée car cela ne fonctionnera pas bien dans le cas général, mais peut sembler fonctionner pendant le test de faible simultanéité. C'est une recette pour les ennuis.

Vous feriez mieux d'utiliser une autre table et d'y incrémenter une valeur; c'est plus susceptible d'être sans course/sans interblocage.

4

La meilleure façon d'éviter les conditions de concurrence lors de la création de clés primaires dans une base de données relationnelle est de permettre à la base de données de générer les clés primaires.

0

Non, vous avez toujours un problème, car si deux requêtes tentent d'incrémenter en même temps, il se peut que la sélection interne soit effectuée, puis une autre requête est traitée.

Votre meilleur pari, si vous voulez une garantie, si vous ne voulez pas que la base de données le fasse, c'est d'avoir une clé unique là-bas.

En cas d'erreur lors de l'insertion, relancez la requête et, une fois la clé primaire unique, elle fonctionnera.

Dans ce cas, le mieux est d'insérer d'abord seulement l'id et toutes les autres colonnes non nulles, puis de faire une mise à jour pour définir les colonnes NULL à tout ce qui est correct.

Questions connexes