Just test it !
Just test it !
Résultat du test :
Cela fonctionne parfaitement !
Pour exemple voici le code que j'utilise
Merci tout le monde
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5 SET AUTOCOMMIT=0; SET @id = (SELECT max(sequence)+1 FROM Table1 where lieu=1 for update) ; INSERT INTO Table1 (sequence,lieu) VALUES (@id,1) ; COMMIT;
Cette façon de faire est particulièrement catastrophique pour la montée en charge.
En effet, pour assurer le calcul du MAX il faut verrouiller la table intégralement afin de s'assurer que personne ne va ni modifier, ajouter ou supprimer une ligne, ni lire la table en parallèle et donc obtenir la même valeur. Bref, lors de la montée en charge cette solution va bloquer de plus en plus de processus concurrent, jusqu'à devenir un point de contention dramatique....
J'ai déjà expliqué à de multiples reprise dans mes papier que la MAX + 1 était une hérésie et qu'il existait une technique fiable, ultra rapide et indolore d'un point de vue de performances quelque soit la volumétrie de la table.
Donnez vous au moins la peine de lire la chose :
http://sqlpro.developpez.com/cours/clefs/
A +
Je ne pense pas que tu aies besoin du FOR UPDATE, qui va verrouiller inutilement toutes les lignes où lieu = 1.
Beh si l'avantage duest d'etre certain d'obtenir que le max(sequence)+1 soit unique.
Code : Sélectionner tout - Visualiser dans une fenêtre à part FOR UPDATE
Oula SQLpro .....
J'ai l'impression d'etre un élève qui se fait gronder par son professeur parcequ'il dormait en cours !
Code : Sélectionner tout - Visualiser dans une fenêtre à part J'ai déjà expliqué à de multiples reprise dans mes papier
Désole de ne pas avoir trouver ton tuto ...
Je vais quand meme le lire.
Cette requête "incrément MAX + 1" dans developpez.net
http://www.google.fr/search?as_q=inc...s=&safe=images
remonte 367 pages...
La même dans developpez.com :
http://www.google.fr/search?hl=fr&as...chercher&meta=
remonte le papier que j'ai écrit en 2e position.
D'où l'utilité des moteurs de recherche !
A +
Aprés lecture de ton article, je ne me retrouve absoluement pas dans les problèmes que tu exposes. Mon cas est spécifique et je ne l'ai pas exposé en entier dans ce post, vu que ce n'était pas le but de celui-ci.
Il est vrai que le fait d'adjoindre une table secondaire pourrait faciliter la monté en charge, mais c'est une action qui peut faite plus tard.
Merci quand meme pour ton article.
SQLPro... je te trouve trés agressifs dans tes messages.
Pour ne pas enchérir dans une polémique qui n'existe pas de mon coté, je met ce post en résolu.
Merci à tout le monde pour son aide.
La requête est exécutée de manière atomique, il n'y a donc pas d'écart entre le moment où le max() + 1 est exécuté et celui où l'insertion est faite.
Ton FOR UPDATE n'aura pour effet que de verrouiller des lignes qui n'ont pas besoin de l'être.
Enfin, mettre une clé unique est le moyen absolu de t'assurer de l'unicité...
ok, je comprend ce que tu veux dire Antoun.
Pourtant si je fais des essais avec deux clients et que je ne met pas "For Update" je me retrouve avec la meme valeur de max(sequence)+1
Je ne peux pas mettre ce champ dans une clef unique, vu que justement il ne l'est pas, il recommence à zéro pour chaque nouveau lieu.
(Ma clef primaire est un champ auto_increment de ma table)
Vois l'essai que je fais
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 Client 1 :START TRANSACTION; Client 2 :START TRANSACTION; Client 1 : SELECT max(sequence) FROM TABLE WHERE lieu=1 résultat = 5 Client 2 : SELECT max(sequence) FROM TABLE WHERE lieu=1 résultat = 5 Client 1 : Insert .... Client1: COMMIT; Client 2:Insert .... Client 2 : COMMIT;
Tu dois poser une clé unique sur la combinaison (lieu, sequence).
Code : Sélectionner tout - Visualiser dans une fenêtre à part ALTER TABLE machin ADD UNIQUE KEY (lieu, sequence) ;
ok j'ai compris..
Je met donc un petit résolu.
Merci encore une fois à tout le monde.
Ceci dit, pour aller dans le sens de SQLpro, c'est une dénormalisation dont l'intérêt reste à prouver. Tu pourrais ne pas stocker du tout ce numéro de séquence et le calculer dynamiquement ainsi :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 SELECT lieu, T1.id, COUNT(*) AS sequence FROM machin T1 INNER JOIN machin T2 ON T1.lieu = T2.lieu AND T1.id >= T2.id GROUP BY lieu, T1.id
Non Autoun, le problème est particulier et je ne peux pas faire autrement.
La requête que tu as fait n'a pas du tout le même but que ce que je cherche à faire.
Après je comprend tout à fait que cette dénormalisation puisse en choquer plus d'un, mais dans des cas particuliers, on ne peut pas toujours la suivre.
Par contre je suis entièrement d'accord avec SQLPro, l'ajout d'une seconde table pour gérer les compteurs est une très bonne idée. J'avais déjà eu l'idée avant, et le fait que dans son article, il soutienne cette théorie me conforte dans la mise en place d'un tel système.
Autrement l'aide que vous m'avez apporté et la solution que j'ai mise en place me convient tout à fait, même si elle a comme inconvénient majeur la monté en charge.
Merci
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager