Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1051 connectés 

 


 Mot :   Pseudo :  
 
 Page :   1  2  3
Page Suivante
Auteur Sujet :

[Oracle] plsql : COMMIT dans une boucle FOR ?

n°1661964
MagicBuzz
Posté le 21-12-2007 à 15:40:43  profilanswer
 

Reprise du message précédent :
Et moi je te conseille de lire la documentation.
http://msdn2.microsoft.com/fr-fr/library/ms187373.aspx
 
Avant de dire des conneries, refais mon jeu de test...
Si tu utilises correctement les table hint, tu peux parfaitement faire ce que tu veux.
 
C'est pas parceque SQL Server fonctionne d'une certainement manière par défaut qu'il ne sait pas travailler autrement.
 
Au lieu de me parler de formateur superman qui vous a montré comment planter sql server 2005 en 2 temps 3 mouvements, reposte jeu de requêtes, et on en reparlera.
C'est pas parcequ'un formateur sais pas se servir du produit sur lequel il vous forme que le produit est mauvais. Si à chaque fois que j'ai fait des formations je devais croire ce que m'ont dit les formateurs, je certifierais comme morticus qu'Oracle ne supporte des sous-requête que dans la clause WHERE, qu'il ne supporte pas le full outer join et surtout qu'il est impossible d'avoir deux index uniques sur une même table (sisi, fait l'avoir entendu en formation pour le croire).
 
Alors ton formateur, il est bien gentil, mais désolé si je ne me fie pas une seconde à une simple déclaration d'un gars qui n'a absolument jamais travaillé de sa vie sur l'outils (ben ouais, quand on est formateur, on exploite pas l'outil, sinon tous les profs d'autoécole seraient des champions de formule 1 pas vrai ?).

mood
Publicité
Posté le 21-12-2007 à 15:40:43  profilanswer
 

n°1661994
leguru2007
Posté le 21-12-2007 à 16:12:58  profilanswer
 

En fait cher Monsieur MagicBuzz,
Vous pouvez très bien paramétrer le niveau d'isolation avec SQL SERVER
qui en compte 4 : Read Uncommitted, Read Committed, et les autres. Le seul niveau qui guarantit la cohérence du système c'est le READ COMMITTED (c'est l'option par defaut heureusement d'ailleurs...) et là le système vous impose les verrous exclusifs sur les transactions comme je l'ai expliqué dans l'une de mes interventions.  
Evidemment pour pouvez aussi le configurer  en mode READ UNCOMMITTED pour simuler le comportement d'un système comme ORACLE mais à la différence d'Oracle qui reconstruit la "donnée avant" à l'aide du segment UNDO, SQL SERVER vous fournit la donnée en modification et non commitée !.... Disons le système s'en fout dans ce cas de toutes les règles du paradigme ACID. en particulier le I (Isolation).
Dans ce niveau d'isolation READ UNCOMMITTED , vous pouvez très bien faire votre test là votre système SQL SERVER ne fonctionne plus vraiment comme un SGBD digne ce nom.  J'espère que tu comprends pourquoi.
BONNE CHANCE

n°1662007
MagicBuzz
Posté le 21-12-2007 à 16:31:31  profilanswer
 

parfaitement d'accord sur ce point, mais là j'ai jamais dit le contraire.
 
ceci dit, pour moi lire les lignes "dans le passé" durant leur mise à jour au sein d'une transaction, ça peut être tout aussi grave que ne pas être capable de les lire du tout dans certains cas. mais effectivement, c'est plutôt vécu comme une limitation.
 
non, moi je ne parle pas de ça.
 
je parle simplement du fait que si je fais :
 
"update matable where val = 1"
 
alors je peux tout à fait faire tout ce que je veux sur toutes les lignes où "val <> 1" depuis une autre session, sans jamais rencontrer le moindre lock, contrairement à ce qui était dit dans le post auquel je répondais avec mon exemple.

n°1662029
leguru2007
Posté le 21-12-2007 à 17:17:17  profilanswer
 

Non mais tu ne comprends pas. Tu arrive à faire ton test parce que tu paramètre ton système de sorte à contourner les règles de fonctionnement d'un SGBD.  
Si tu reste dans le mode de fonctionnement par defaut (je précise qui est le seul qui guarantit le "read consistency" du paradigme ACID) tu ne pourras pas faire ce test. J'espère qu'on se comprend. parce que toute la page est vérrouillée de façon exclusive aussi bien pour les lignes en modification que pour les autres. Maintenant parlons de ce que tu appelle lecture des lignes "dans le passé". Pour faire simple je dirai : Ce n'est pas parce que je modifie une ligne que je vais effectivement valider ma modification puisque je peux decider à tout moment de faire marche arrière. mais pendant ce temps dois-je empêcher les autres sessions de travailler ? Pour ORACLE le choix est clair C'est NON. donc tant que je n'ai pas effectivement validé mes modifications elles ne seront pas propagées dans les autres sessions. C'est le fameux "I" de ACID. Et la logique voudrait qu'elles (les autres sessions) continue de voir les données telles étaient avant ma modif jusqu'à ce que je me decide de les valider.... La mise en oeuvre d'un tel choix n'est pas aisé surtout qu'il rend plus complexe le traitement d'une LMD avec la sauvegarde de la donnée avant, la copie des modif apportées aux données UNDO dans le redo log buffer, celle des données effectivement à modifier aussi dans le vecteur redo, la copie du redo log buffer sur disque avec le fast commit etc... Et pendant toutes ces phases, si la machine crash, que doit faire le système ??? Comment faire pour rendre le système performant avec une telle architecture plus complexe ???
Je ne passe pas que ORACLE ait fait le choix d'une architecture aussi complexe pour le plaisir d'emmerder ces developpeurs !!!! C'est donc à l'origine que ORACLE a marqué la diiérence avec les autres... Dommage qu'avec SQL SERVER on ne va pas au fond dans la connaissance du système. Je te conseille quant même le livre de PAUL NIELSEN (SQL SERVER 2005 La BIBLE)  
A++

n°1662080
MagicBuzz
Posté le 21-12-2007 à 18:40:31  profilanswer
 

Pour travailler à la fois avec Oracle et SQL Server, je suis tout à fait d'accord en ce qui concerne le fait que SQL Server ne sais pas fournir "l'ancienne version" de la ligne durant sa modification dans une transaction depuis une transaction tièrce.
C'est absolument vrai, et à moins de faire des bidouilles de contournement à la main, il n'y a aucun moyen de passer outre.
 
Moi, tout ce que je dis, c'est que pour les lock, ils se font à la ligne.
Et si c'est effectivement des "pages" ou "blocks", alors SQL Server se débrouille pour ne mettre dedans que les lignes modifiées par la transaction, les autres restent parfaitement disponibles contrairement à ce que tu dis.
 
Voici un exemple simple, avec une base crée avec les options par défaut, et comme tu peux voir, aucun hint demandant à passer outre le fonctionnement par défaut :
 

Code :
  1. CREATE TABLE personne
  2. (
  3.  id int NOT NULL PRIMARY KEY,
  4.  label varchar(50) NOT NULL
  5. );
  6.  
  7. INSERT INTO personne (id, label) VALUES (1, 'MagicBuzz');
  8. INSERT INTO personne (id, label) VALUES (2, 'leguru2007');


 
Session 1 :

Code :
  1. begin tran
  2.  
  3. UPDATE personne SET label = 'grmpf' WHERE id = 1


 
Session 2

Code :
  1. begin tran
  2.  
  3. UPDATE personne SET label = 'plop' WHERE id = 2


 
Il ne se produit aucun lock.
 
Par contre, si depuis la session 2 je tente de toucher (lecture ou écriture) la ligne id=1 sans hint, alors jesuis locké, et inversement depuis la session 1 sur la ligne id=2.
 
Donc page, block ou ce que tu veux, seules les lignes impactées par la transaction sont verrouillées.
 
 
En revanche, la transaction est aveugle.
 
En effet, en repartant des données initiale :
 
Session 1 :

Code :
  1. begin tran
  2.  
  3. UPDATE personne SET label = 'plop' WHERE label = 'leguru2007'


 
Session 2 :

Code :
  1. begin tran
  2.  
  3. UPDATE personne SET label = 'cuicui' WHERE label = 'leguru2007'


=> Locké, logique, on ne sais pas si "leguru2007" existera toujours à la fin de la transaction de la session 1
 
Session 3 :

Code :
  1. begin tran
  2.  
  3. UPDATE personne SET label = 'grmpf' WHERE label = 'plop'


=> Locké, logique, on ne sais pas si "plop" existera à la fin de la transaction de la session 1
 
Session 4 :

Code :
  1. begin tran
  2.  
  3. UPDATE personne SET label = 'nerd' WHERE label = 'Harko'


=> Locké, pas logique, puisqu'on sait que quels que soient les résultats des transactions 1, 2 et 3, le label "Harko" n'existera jamais. Il y a un lock ici non pas de la table ou de la page, mais simplement de la valeur en cours de modification. Etant incapable de savoir quelle sera la valeur finale ni quelle était la valeur initiale, SQL Server est obligé d'attendre que les locks sur toutes les lignes soient relâchés.
 
C'est là toute la subtilité. Tant que le filtre porte sur des champs qui ne sont pas modifiés par une transaction, les locks n'entrent pas en collision tant qu'on travaille sur des lignes différentes. Par contre, dès qu'on filtre sur un champ en cours de modification, on a l'impression d'avoir un lock sur toute la table, mais ce n'est pas vrai, c'est juste qu'à ce stade, toutes les lignes en cours de modification étaient inconnues, on est incapable d'effectuer le filtre.
 
J'ai oublié de tester avec une 5° session, voir si la ligne avec id=1 est lockée par la 4° session, mais je ne pense pas.


Message édité par MagicBuzz le 21-12-2007 à 18:59:57
n°1662097
MagicBuzz
Posté le 21-12-2007 à 19:07:06  profilanswer
 

Sinon, le coup d'Oracle qui permet de jouer avec les "vieilles valeurs", c'est ennuyeux dans la mesure où :
 
Session 1 :

Code :
  1. UPDATE personne SET id = 3 WHERE id = 1;


 
Session 2 :

Code :
  1. UPDATE personne SET id = id + 1 WHERE id = (SELECT max(id) FROM personne);


 
En toute logique, la requête de la session 2 ne doit pas provoquer d'erreur puisqu'elle bosse dans une micro transaction et quele filtre semble parfaitement correct. Cependant, ici on va avoir un problème si on commit la première requête, puisqu'on va générer un doublon sur le primary key.
 
J'ai pas d'oracle sous la main pour tester, si t'en as un, je veux bien que tu dises ce que ça fait, tantôt si on commit la première session ou la seconde session en premier.
Je pense que la première session qui commit va faire planter l'autre quand elle voudra commiter à son tour (ça me semble logique).
Et là ça pose problème. Quand on commit, on s'attend à ce que vu que tout s'est bien passé, y'a pas de raison que le commit foire.
 
Dans ce cas précis, le choix fait par SQL Server est donc à mon avis le meilleur, puisque l'action de la seconde session dépend exclusivement de l'action de la première session, donc il faut mettre en attente la seconde requête tant qu'on ne sais pas quelle sera la valeur finale de id pour la première ligne.


Message édité par MagicBuzz le 21-12-2007 à 19:10:50
mood
Publicité
Posté le   profilanswer
 

 Page :   1  2  3
Page Suivante

Aller à :
Ajouter une réponse
 

Sujets relatifs
[Oracle] Execute Immediate ne fait rien ... ?[résolu]Boucle travaillant avec toutes les valeurs issues d'un formulaire
Un goto ou bien une boucle ! Comment faireBoucle sur formulaire
[resoluTRIGGER REPLICATION] replication de table sur deux bases repar[JAVA] Pb de connexion DB Oracle à partir d'une applet [Résolu]
comment faire défiler des images en boucle sur un site ?Passer une variable php->js dans une boucle
[Résolu][Oracle Text] chargement de fichiers / indexRécupération de variables en boucle
Plus de sujets relatifs à : [Oracle] plsql : COMMIT dans une boucle FOR ?


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR