Base de données en réseau qui cassent sans arret ! Help !!!!!!

cs_globule Messages postés 327 Date d'inscription mardi 8 octobre 2002 Statut Membre Dernière intervention 6 octobre 2010 - 26 avril 2005 à 13:53
gvr Messages postés 2 Date d'inscription jeudi 10 avril 2003 Statut Membre Dernière intervention 10 juin 2005 - 10 juin 2005 à 09:24
Bonjour





J’ai crée le petit programme si dessous qui rempli 5000 Champs dans une base (Access 2002, ADO 2.7)


La base est centralisée sur un seul poste (1 poste travail en local et l’autre accède à la base par une connexion réseau)





Si je place la base sur une machine peut puissante (P166) et que je fais tourner les 2 programmes (l’autre poste est beaucoup plus puissant) en même temps, le résultat sera un plantage du programme et la destruction de la base.


Je ne peux pas croire que ADO et Access ne soit pas capable de gérer ce problème de façon plus efficace.





Avez-vous une solution (je ne peux pas passer en client-serveur, ni changer de type de base de données). Existe-t-il une fonction avec ADO qui teste si la base est libre avant d’écrire dedans ?





For Cpt = 0 To 5500





Set MyRecordSet = New ADODB.Recordset


MyRecordSet.open "MaTABLE", AdoMyBase, adOpenKeyset, adLockOptimistic





Retour = MyRecordSet.AddNew





MyRecordSet.fields("Champ1").value = “TOTOTOTOTOTOTOTOTO”


MyRecordSet.fields("Champ2").value = “TATATATATATATATATA”





MyRecordSet.Update





' Fermeture du recordset


If (Not MyRecordSet Is Nothing) Then


If MyRecordSet.State = adStateOpen Then MyRecordSet.Close


Set MyRecordSet = Nothing


End If





Next

Config de test :
Poste 1 : P4 2800 XP Home Edition
Poste 2 : P166, W98B

9 réponses

inconnu974 Messages postés 13 Date d'inscription lundi 12 avril 2004 Statut Membre Dernière intervention 20 octobre 2009
26 avril 2005 à 15:32
Bonjour,

Je sais pas si j'ai bien compris le problème mais tu peux peut-être essayer de jouer sur l'accès concurrent dans ce cas il te suffirait de remplacer adLockOptimistic par adLockPestimistic (si ma mémoire est bonne)

Je suis pas très doué en programmation mais j'espère que ça pourra t'aider
0
cs_globule Messages postés 327 Date d'inscription mardi 8 octobre 2002 Statut Membre Dernière intervention 6 octobre 2010
26 avril 2005 à 15:51
C'est pire, la base case apres quelques secondes
0
cs_pluplu Messages postés 615 Date d'inscription mercredi 18 décembre 2002 Statut Membre Dernière intervention 4 juillet 2012
26 avril 2005 à 21:23
Difficile à dire, mais ce qui m'effraie c'est pas tellement le P166, mais surtout Win98 déjà en réseau iln'est pas très stable, mais si en plus il te manque un peu de mémoire, et c'est le scénario catastrophe, mieux vaut NT4 c'est plus sure.

Pascal Laurençon
0
cs_corsica Messages postés 147 Date d'inscription lundi 13 mai 2002 Statut Membre Dernière intervention 15 février 2010
26 avril 2005 à 23:03
For Cpt = 0 To 5500





Set MyRecordSet = New ADODB.Recordset


MyRecordSet.open "MaTABLE", AdoMyBase, adOpenKeyset, adLockOptimistic





Retour = MyRecordSet.AddNew





MyRecordSet.fields("Champ1").value = “TOTOTOTOTOTOTOTOTO”


MyRecordSet.fields("Champ2").value = “TATATATATATATATATA”





MyRecordSet.Update





' Fermeture du recordset


If (Not MyRecordSet Is Nothing) Then


If MyRecordSet.State = adStateOpen Then MyRecordSet.Close


Set MyRecordSet = Nothing


End If





Next

Là , si j'ai bien compris tu déclare 5500 fois un curseur et tu essayes d'insérer autant de fois un enregistrement dans ta table ...

J'ai l'impression que tu écroules ta base et ton micro avec une série de connexions en rafale ...

Ne serais-t-il pas plus simple de faire comme ceci ?


Set MyRecordSet = New ADODB.Recordset


MyRecordSet.open "MaTABLE", AdoMyBase, adOpenKeyset, adLockOptimistic



For Cpt = 0 To 5500




Retour = MyRecordSet.AddNew





MyRecordSet.fields("Champ1").value = “TOTOTOTOTOTOTOTOTO”


MyRecordSet.fields("Champ2").value = “TATATATATATATATATA”





MyRecordSet.Update


Next



' Fermeture du recordset


If (Not MyRecordSet Is Nothing) Then


If MyRecordSet.State = adStateOpen Then MyRecordSet.Close


Set MyRecordSet = Nothing


End If









Et là , ce n'est plus 5500 connexions à ta base access mais 1 connexion et 5500 insert ...

( Je me trompe peut-être dans la syntaxe du code , ça fait un bon moment que j'ai laissé tomber le ADO , au pire adapte l'idée )




Life is Too Short ...
Enjoy Your Life ...
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
cs_globule Messages postés 327 Date d'inscription mardi 8 octobre 2002 Statut Membre Dernière intervention 6 octobre 2010
27 avril 2005 à 08:12
Merci, mais le but etait justement de tester la solidité des bases. Car ce probleme ce produit chez certains de mes clients (y compris avec NT).
Il faudrait que j'arrive a trouver un moyen de tester la disponibilité de la base avant d'ecrire dedant.
Existe t'il un moyen de traiter ce probleme avec un On error. Par exemple, si ca plante on recommence l'enregistrement.
0
gvr Messages postés 2 Date d'inscription jeudi 10 avril 2003 Statut Membre Dernière intervention 10 juin 2005
9 juin 2005 à 11:42
Bonjour globule,

J'ai le même problème depuis longtemps sur une base mdb partagée par seulement 3 postes. J'ai beaucoup cherché pour améliorer cela, en vain.
As tu solutionné ce problème ?
0
cs_globule Messages postés 327 Date d'inscription mardi 8 octobre 2002 Statut Membre Dernière intervention 6 octobre 2010
9 juin 2005 à 12:03
Non,

Il faut un reseau rapide (surtout pas de WIFI a 11 mb), et proscrire certains anti-virus. C'est un peu genant qu'en 2005 on ne trouve pas de moteur de base de données solide (sans parler des trucs monstrueux style SQL server)
0
cs_pluplu Messages postés 615 Date d'inscription mercredi 18 décembre 2002 Statut Membre Dernière intervention 4 juillet 2012
9 juin 2005 à 19:12
c'est un peu normal Access c'est pas du client/serveur losque l'on traite avec la BD on doit rapatrier l'ensemble des records, alors qu'avec SQL-server les requêtes peuvent êtres locale au serveur, et seul le resultat des requêtes transitent par le réseau, c'est donc un gain de temps appréciable.

Pascal Laurençon
0
gvr Messages postés 2 Date d'inscription jeudi 10 avril 2003 Statut Membre Dernière intervention 10 juin 2005
10 juin 2005 à 09:24
Après lecture du document intitulé "understanding microsoft jet locking" (qui traite de jet 3.5, mais jet 4.0 ne doit pas être sensiblement différent à ce sujet), j'ai enfin trouvé ce qui cloché dans mon programme. Les erreurs signalées était du type sql state 3218 "impossible de mettre à jour, actuellement vérouillée" ou 3260 "Impossible de mettre à jour actuellement verrouillé sur ordinateur <" MachineName "> par utilisateur <" UserName ">". Il ne s'agit pas de problème réseau, même si nous sommes dans le cas du partage d'une base mdb sur un réseau avec des tronçons BNC à 10 mb. Pour répondre à Pascal, l'utilisation de curseur coté serveur à l'ouverture de la connection est préférable pour limiter le trafic en direction du client.
Set DBTeinture = New ADODB.Connection
DBTeinture.Provider = "Microsoft.JET.OLEDB.4.0"
DBTeinture.Mode = adModeShareDenyNone
DBTeinture.Properties("Data Source") = NomDB$
DBTeinture.Properties("Jet OLEDB:Database Locking Mode") = 1
DBTeinture.Properties("Persist Security Info") = False
DBTeinture.CursorLocation = adUseServer
DBTeinture.Open
Notez l'utilisation de la propriété ("Jet OLEDB:Database Locking Mode") = 1 qui demande des locks au niveau ligne, et non au niveau page. Cela limite les conflits de lock, mais demande plus de travail au moteur jet.
Au niveau de la création des recordset, j'emploi systématiquement l'option adLockReadOnly pour les recordset en lecture seulement et adLockOptimistic (le niveau de lock le moins astreignant) pour les recordset en mise à jour. (Ceci n'est peut être pas adapté pour une database pour laquelle on souhaite une gestion "forte" des risques d'utlisation / mise à jour simultanée des enregistrements. Ce n'est pas mon cas.)

Mon erreur de conception était la suivante :

1) dbteinture.begintrans
.....

2) Rst.update ' Mise à jour des recordsets. le moteur jet pose un lock à cet instant, qui ne sera levé qu'à la fin de la transaction par committrans ou rollbacktrans. (Alors que je pensais que le lock se limitait au .update)

3) attente de validation ou d'annulation de la mise à jour par l'utilisateur par command button "valider" ou "annuler" : et c'est la que le lock peut rester indéfiniment et bloque les autres utilisateurs.

4) fin de la transaction par committrans ou rollbacktrans : le lock est levé ici.

Même si vous n'êtes pas dans ce cas d'erreur, je vous conseil la lecture des documents "understanding microsoft jet locking" (contenu dans le fichier jetutils.exe) et articles microsoft numéros 296264, 303528, 300216 qui donnent quelques éclaircissement sur la gestion des locks.

De plus il faut gérer les cas "normaux" de vérouillage en codant une gestion d'erreur de ce genre :

'---------------------------------------------------------
' DETERMINATION D'UN NOUVEAU NUMERO DE RECETTE
'---------------------------------------------------------
Function NouveauNumeroRecette() As Long


Dim RstTemp As ADODB.Recordset


On Error GoTo NNR_Failed


Do
DBRequete RstTemp, "Controle", adCmdTable, adLockOptimistic
With RstTemp
![Date Modification] = Format(Now, "dd/mm/yyyy hh:mm:ss") If !Recette 9999999 Then !Recette 1 Else !Recette = !Recette + 1
.Update
NouveauNumeroRecette = !Recette
.Close
Set RstTemp = Nothing
End With
DBRequete RstRecettes, "SELECT * FROM Recettes WHERE Recette=" + _
CStr(NouveauNumeroRecette) + ";", adCmdText, adLockOptimistic
Loop Until RstRecettes.RecordCount = 0

On Error GoTo 0

Exit Function

NNR_Failed:
Dim LockRetry As Integer


If GestionVerrou(LockRetry, "Détermination du numéro de recette : actuellement vérouillé par un autre utilisateur." + Err.Description) = vbYes Then Resume

DBErr "NouveauNumeroRecette" ' programme planté.


End Function
'---------------------------------------------------------
' GESTION DES VERROUS SUR DATABASE
'---------------------------------------------------------
Function GestionVerrou(LockRetry As Integer, msg As String) As Integer


If DBTeinture.Errors.Count > 0 Then
Select Case DBTeinture.Errors(0).SQLState

Case 3218, 3260 ' The record is locked.
LockRetry = LockRetry + 1
If LockRetry > 2 Then ' 3 tentatives
GestionVerrou = vbNo ' Pas de nouvelle tentative
Exit Function
End If
pause LockRetry ' augmente à chaque tentative
GestionVerrou = vbYes ' Une nouvelle tentative
Exit Function

End Select
End If

DBErr Screen.ActiveForm.Name + " " + Screen.ActiveControl.Name + " " + msg ' programme planté


End Function

'---------------------------------------------------------
' FAIRE UNE PAUSE
'---------------------------------------------------------
Sub pause(PauseTime)
Dim start, Finish, TotalTime
start = Timer ' Définit l'heure de début.
Do While Timer < start + PauseTime
DoEvents ' Donne le contrôle à d'autres processus.
Loop
End Sub

En espérant que cela puisse vous aider ...

Joel
0
Rejoignez-nous