Base de données en réseau qui cassent sans arret ! Help !!!!!!
cs_globule
Messages postés327Date d'inscriptionmardi 8 octobre 2002StatutMembreDernière intervention 6 octobre 2010
-
26 avril 2005 à 13:53
gvr
Messages postés2Date d'inscriptionjeudi 10 avril 2003StatutMembreDernière intervention10 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 ?
inconnu974
Messages postés13Date d'inscriptionlundi 12 avril 2004StatutMembreDernière intervention20 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
cs_pluplu
Messages postés615Date d'inscriptionmercredi 18 décembre 2002StatutMembreDerniè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.
cs_globule
Messages postés327Date d'inscriptionmardi 8 octobre 2002StatutMembreDerniè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.
gvr
Messages postés2Date d'inscriptionjeudi 10 avril 2003StatutMembreDernière intervention10 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 ?
cs_globule
Messages postés327Date d'inscriptionmardi 8 octobre 2002StatutMembreDerniè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)
cs_pluplu
Messages postés615Date d'inscriptionmercredi 18 décembre 2002StatutMembreDerniè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.
gvr
Messages postés2Date d'inscriptionjeudi 10 avril 2003StatutMembreDernière intervention10 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
'---------------------------------------------------------
' 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