Pas de problème (pb), que du PowerBuilder (PB) ^^

Le forum (ô combien francophone) des utilisateurs de Powerbuilder.

Recherche rapide

Annonce

Certaines rubriques, dont des cours, sont uniquement visibles par les membres du forum ^^.
Dans la rubrique Liens & Références, vous avez accès à un sommaire de téléchargement, profitez-en !
Il existe maintenant un nouveau TOPIC "Votre CV en Ligne" accessible uniquement par demande.

#1 09-08-2010 08:38:27

sbouvetJD  
Chasseur d'y voir ?
Lieu: LYON
Date d'inscription: 29-03-2007
Messages: 185
Pépites: 147,483,921
Banque: 13,317,684,827,902,405
Site web

Gérer les deadlocks

Bonjour (de prime abord j'étais tenté de poster dans la partie BDD, mais il s'agit bien de coding PB, alors...)

Sous Powerbuilder 9 avec base de données SQL Server 2000, je souhaite gérer les deadlocks ; j'ai donc mis en place une bidouille de ce type, mais apparemment, le deadlock outrepasse la boucle :

Code: pb

If maDtw.Update(True, False) <> 1 Then
  ROLLBACK USING SQLCA;
  MessageBox(gAppNom, "L'erreur suivante s'est produite :~r" + SQLCA.SQLErrText, StopSign!, Ok!)
  return FALSE
End If

li_essai = 10

Do
  COMMIT USING SQLCA;
  If SQLCA.SQLDBCode <> 0 Then
    If li_essai = 0 Then
      ROLLBACK USING SQLCA;
      MessageBox(gAppNom, "Impossible d'enregistrer la transaction. Contactez le service informatique.", StopSign!)
      Return False
    End If
    lb_ok = False
    MessageBox(gAppNom, "Une erreur SQL est survenue :~r" + SQLCA.SQLErrText + ".~rL'opération va être retentée (" + String(li_essai) + ").", Exclamation!)
    li_essai --
      
    If maDtw.Update(True, False) <> 1 Then
      ROLLBACK USING SQLCA;
      MessageBox(gAppNom, "Erreur lors de la suppression de la liste de pilotage :~r" + SQLCA.SQLErrText, StopSign!, Ok!)
      return FALSE
    End If
  Else
    lb_ok = True
  End If  
Loop Until lb_ok

Dernière modification par sbouvetJD (09-08-2010 12:05:05)

Hors ligne

 

#2 09-08-2010 09:36:49

Yanis  
Modérateur
Lieu: paris
Date d'inscription: 16-06-2010
Messages: 349
Pépites: 665
Banque: 150

Re: Gérer les deadlocks

bonjour,

    Pour moi je vois plusieurs erreurs.
    Si ton erreur survient sur <If maDtw.Update(True, False) <> 1 Then> comme tu effectue un return False tu ne pourras jamais rentrer dans la boucle

    En deux quand tu rentre dans ta boucle tu effectue un commit lequel vas mettre le sqldbcode à 0 donc tu vas passer dans le else et tu remet ton booleen à true donc tu sort de la boucle.

Cdt
Yanis

Hors ligne

 

#3 09-08-2010 09:39:38

shahin  
Modérateur
Award: bf
Lieu: val de marne
Date d'inscription: 26-09-2006
Messages: 938
Pépites: 8,675,050,269
Banque: 16,218,225,127,617

Re: Gérer les deadlocks

Bonjour sbouvetJD,

Apparemment tu ne sais pas ce qu'est un deadlock, sinon tu n'aurai jamais écris ".. il s'agit bien de coding PB.."
Les deadlocks sont un problème complexe, et c'est pas avec une bidouille que tu vas t'en sortir.

La première chose à faire c'est de diagnostiquer.
Un deadlock ne se fait pas tout seul, il implique toujours au moins 2 transactions.
Tu trouveras l'info dans les logs de ton serveur SQL.
Quels sont les 2 programmes qui se sont interbloqués ?


Sur ta bidouille :
maDtw est parfois une datawindow, parfois un tableau de datawindow.
Combien de dw sont impliquées dans ta transaction ?
Si tu en as une seule, autant rester en autocommit


never let people work on more than one thing at once.

Hors ligne

 

#4 09-08-2010 10:56:24

sbouvetJD  
Chasseur d'y voir ?
Lieu: LYON
Date d'inscription: 29-03-2007
Messages: 185
Pépites: 147,483,921
Banque: 13,317,684,827,902,405
Site web

Re: Gérer les deadlocks

shahin :
Désolé pour le tableau de DTW, erreur de copier/coller sur le forum.
Un deadlock, dans mon cas, est apparemment l'accès concurrentiel à une ressource commune par au moins 3 points ; concrètement, notre applicatif (jusqu'à 16 postes en simultané, + triggers et tâches régulières annexes) effectue des UPDATE / DELETE sur une même table. C'est du moins la seule hypothèse qui nous a semblée plausible.

Yanis :
Si l'ordre d'update me retourne une erreur (duplicate key par exemple ou non respect d'une clef étrangère), j'effectue immédiatement mon rollback.
En fait je pensais que le COMMIT USING SQLCA me retournerait un DBCODE <> 0 si le serveur provoque une erreur comme un deadlock, mais d'après ce que vous semblez me dire, c'est l'UPDATE() qui me retourne l'info ?

Hors ligne

 

#5 09-08-2010 11:34:10

Yanis  
Modérateur
Lieu: paris
Date d'inscription: 16-06-2010
Messages: 349
Pépites: 665
Banque: 150

Re: Gérer les deadlocks

Salut,

    Je pense que dans le cas d'un deadlock ton UPDATE doit te retourner une erreur. Dans ce cas il serait possible de tester le sqldbcode = 1205 ( je crois que c'est la valeur retourné en cas de deadlock ) à ce moment là j'exécuterai la boucle. ( en n'effectuant pas de commit au départ comme tu l'as fait )

   Si la fonction update ne te retourne pas d'erreur ( ce qui pour moi serait un bug ) je testerai la valeur du sqlcode pour savoir si une erreur est survenue et si oui je testerai le sqldbcode ( 1205) pour savoir si j'avais un deadlock.


Cdt
Yanis

Hors ligne

 

#6 09-08-2010 12:04:48

sbouvetJD  
Chasseur d'y voir ?
Lieu: LYON
Date d'inscription: 29-03-2007
Messages: 185
Pépites: 147,483,921
Banque: 13,317,684,827,902,405
Site web

Re: Gérer les deadlocks

Je vous ai présenté une version simplifiée de mon problème, car, en fait, lorsque je simule un deadlock et que j'exécute mon code au pas à pas, c'est bien sur la ligne du COMMIT que le deadlock est provoqué. En effet, dans mon commit, j'ai plusieurs datawindows que j'UPDATE() (ce qui déclenche update ou delete selon le cas) + SQL Embedded. A chaque tentative d'UPDATE(), si l'ordre est <> 1, je retourne le message d'erreur DB associé. Lorsque je tente le COMMIT, c'est donc ma transaction qui est deadlockée, et qui peut comporter donc plusieurs ordres SQL. Je me dois donc de retenter l'ensemble de ma transaction et non pas seulement l'update de maDtw. Pour dire, je stocke mon embedded dans un tableau de chaîne et je retente les ordres par un

Code: pb

PREPARE SQLSA FROM :ls_sql USING SQLCA;
EXECUTE SQLSA USING :ll_temp;

Hors ligne

 

#7 09-08-2010 12:45:11

Yanis  
Modérateur
Lieu: paris
Date d'inscription: 16-06-2010
Messages: 349
Pépites: 665
Banque: 150

Re: Gérer les deadlocks

salut,
   Est tu sur que c'est ton commit qui reçoit ton deadlock. (Je n'ai jamais vu celà )
   Explication.  Un verrou ( lock ) est posé  par les ordres de maj Insert, Update, delete  ou avec 1 ordre select en  fonction du niveau d'isolation. Si l'ordre sql ne peut aboutir ( enregistrement en cours de modif par exemple ) et que celui qui te bloque essaye d'atteindre une ligne que toi tu bloque alors il y a deadlock. Si tous tes ordres sont bien passés ( ce que tu semble indiqué ) le commit est là pour retirer les verrous

   Est tu sur qu'avant de faire le commit ton sqldbcode n'était pas déjà <> 0 ( j'ai déjà eu un cas mais je ne me souvient plus lequel ou le sqlcode était à 0 tout s'est bien passé et que le sqldbcode n'avait pas été réinitialisé par l'objet transaction).

Cdt
Yanis

Hors ligne

 

#8 09-08-2010 13:26:04

sbouvetJD  
Chasseur d'y voir ?
Lieu: LYON
Date d'inscription: 29-03-2007
Messages: 185
Pépites: 147,483,921
Banque: 13,317,684,827,902,405
Site web

Re: Gérer les deadlocks

Merci, je vais tenter de déporter ma solution au niveau de l'update.

Hors ligne

 

#9 10-08-2010 07:18:22

sbouvetJD  
Chasseur d'y voir ?
Lieu: LYON
Date d'inscription: 29-03-2007
Messages: 185
Pépites: 147,483,921
Banque: 13,317,684,827,902,405
Site web

Re: Gérer les deadlocks

Me conseillez-vous, du coup, un programming du type :

Code: pb

ll_essai = 10

Do
  If maDtw.Update(True, False) <> 1 Then
    ll_sqldbcode = SQLCA.SQLDBCode 
    ROLLBACK USING SQLCA;
    If sqldbcode = 1205 Then  // DBCode POUR DEADLOCK
      If ll_essai = 0 Then
        MessageBox("", "Impossible d'enregistrer, verrou")
        Return 1
      Else
        MessageBox("", "Verrou temporaire, autre tentative")
        ll_essai --
      End If
    Else
      MessageBox("", "L'erreur suivante s'est produite :~r" + SQLCA.SQLErrText)
      Return 1
    End If
  End If
Loop Until SQLCA.SQLDBCode = 0
  
COMMIT USING SQLCA;

Hors ligne

 

#10 10-08-2010 07:35:59

Yanis  
Modérateur
Lieu: paris
Date d'inscription: 16-06-2010
Messages: 349
Pépites: 665
Banque: 150

Re: Gérer les deadlocks

Salut,

   je ne me baserais pas sur le sqldbcode pour finir ma boucle

Code: pb

boolean    lb_fin
ll_essai = 10

Do
  If maDtw.Update(True, False) = 1 Then
      lb_fin = true
  Else  
    ll_sqldbcode = SQLCA.SQLDBCode

    // Attention ici tu fais un rollback mais si tu as fait des MAJ
    // avec du sql embeded tu perd tes modif et tu continue à mettre à jour ta datawindow 
    // si tu as eu un dead lock sur la fonction update. ????? 

    ROLLBACK USING SQLCA;
    If sqldbcode = 1205 Then  // DBCode POUR DEADLOCK
      If ll_essai = 0 Then
        MessageBox("", "Impossible d'enregistrer, verrou")
        Return 1
      Else
        MessageBox("", "Verrou temporaire, autre tentative")
        ll_essai --
      End If
    Else
      MessageBox("", "L'erreur suivante s'est produite :~r" + SQLCA.SQLErrText)
      Return 1
    End If
  End If
Loop Until lb_fin 
   
COMMIT USING SQLCA;

Hors ligne

 

#11 10-08-2010 09:33:58

sbouvetJD  
Chasseur d'y voir ?
Lieu: LYON
Date d'inscription: 29-03-2007
Messages: 185
Pépites: 147,483,921
Banque: 13,317,684,827,902,405
Site web

Re: Gérer les deadlocks

Par contre je n'arrive plus à générer un deadlock pour tests ? Il me semblait qu'à l'époque j'avais bidouillé une SP qui faisait un ROLLBACK, mais cela ne semble pas affecter mon problème. Dans mon hypothèse, on a la configuration suivante :

POSTE_1 UPDATE sur maTABLE (enr. N°1)
POSTE_2 UPDATE sur maTABLE (enr. N°2)
POSTE_1 DELETE sur maTABLE (enr N°1)
POSTE_2 DELETE SUR maTABLE (enr N°2) -> DEADLOCK

C'est possible ? Sachant qu'UPDATE et DELETE passent en deux maDtw.Update() différents, et son COMMITés à la fin si tout va bien.

Dernière modification par sbouvetJD (10-08-2010 09:39:29)

Hors ligne

 

#12 10-08-2010 09:49:11

Yanis  
Modérateur
Lieu: paris
Date d'inscription: 16-06-2010
Messages: 349
Pépites: 665
Banque: 150

Re: Gérer les deadlocks

Pour moi un rollback n'a jamais généré de dealock au contraire puisqu'il enlève les lock posés dans la base par ta proc

Si tu veut faire un deadlock, je te conseille de prendre un outil tel que ISQL
     1 > Tu met à jour avec ISQL  ( tu dois choisr le bon enregistrement qui doit bloquer ton appli ) (tu n'es pas obligé de faire des modif tu peut faire un update avec les mêmes valeurs que celle contenue en base)
     2 > Tu met à jour avec ton appli ( elle doit au moins mettre à jour une ligne et se retrouver bloquer par le verrou poser avec ISQL
     3 > Tu essaye de mettre à jour avec ISQL l'enregistrement qui a été mis à jour par ton appli

Là tu as un cas de deadlock

Hors ligne

 

#13 10-08-2010 14:01:51

sbouvetJD  
Chasseur d'y voir ?
Lieu: LYON
Date d'inscription: 29-03-2007
Messages: 185
Pépites: 147,483,921
Banque: 13,317,684,827,902,405
Site web

Re: Gérer les deadlocks

Question, à part cependant : le SQLCA.SQLErrText n'est-il pas réinitialisé après le ROLLBACK ? Dois-je le stocker ?

Code: pb

If maDtw.Update(True, False) <> 1 Then
  ErrMsg = SQLCA.SQLErrText
  ROLLBACK USING SQLCA;
  Messagebox("", ErrMsg) // Peut-on mettre directement Messagebox("", SQLCA.SQLErrText)
End If

Hors ligne

 

#14 10-08-2010 14:08:33

Yanis  
Modérateur
Lieu: paris
Date d'inscription: 16-06-2010
Messages: 349
Pépites: 665
Banque: 150

Re: Gérer les deadlocks

je pense que tu as tout intérêt à le récupérer avant ton rollback

Hors ligne

 

Pied de page des forums

Propulsé par FluxBB 1.2.22