Dopo aver elaborato correttamente i dati di una sessantina di dipendenti, il
programma si interrompe e segnala il seguente messaggio di errore:
[DBNetLib][Server sql inesistente o accesso negato]
Dopo la segnalazione di errore, il programma riprende a funzionare e termina
correttamente.
L'errore si verifica se il programma viene eseguito attraverso la rete,
mentre non si verifica se viene eseguito sulla macchina che fa da server
SQL.
In ufficio non si riesce a riprodurre l'errore, nemmeno su un VirtualPC con
pochissime risorse; anche l'esecuzione in rete non pare che dia problemi.
Presso il cliente, l'errore non si manifesta sempre, ma quasi e, quando si
verifica, lo fa sullo stesso dipendente, ma non sempre nello stesso punto di
programma (una volta, leggendo dalla tabella A, un'altra volta leggendo
dalla tabella B, una terza volta leggendo dalla tabella C...). Il comune
denominatore � l'apertura di un recordset per leggere dati da una tabella
del db.
Aggiungendo una semplice msgbox al codice, prima dell'elaborazione del
dipendente incriminato, l'errore non si verifica.
Mi era venuto in mente che potevano rimanere recordset aperti e che il
programma, per qualche motivo, arrivasse ad esaurire qualche risorsa.
In effetti, ho trovato nel codice alcuni recordset aperti e non chiusi; li
ho chiusi e impostati a Nothing al termine di ogni procedura.
Mi aspettavo di vedere qualche miglioramento, ma il comportamento del
programma � rimasto esattamente lo stesso: si ferma sempre nello stesso
modo, sullo stesso dipendente, facendo le stesse cose che un attimo prima e
un attimo dopo sembrano funzionare perfettamente.
Qualcuno sa darmi qualche suggerimento?
Ciao!
Alex
> Un'applicazione VB (della quale gi� scrissi in altro 3d) esegue un
> lungo ciclo di letture e scritture su un db SQL Server. Il programma �
> installato su centinaia di macchine con le pi� varie configurazioni e
> sembra funzionare correttamente. Presso un solo cliente, si riscontra
> un'anomalia.
>
> Dopo aver elaborato correttamente i dati di una sessantina di
> dipendenti, il programma si interrompe e segnala il seguente messaggio
> di errore: [DBNetLib][Server sql inesistente o accesso negato]
>
> Dopo la segnalazione di errore, il programma riprende a funzionare e
> termina correttamente.
>
> L'errore si verifica se il programma viene eseguito attraverso la
> rete, mentre non si verifica se viene eseguito sulla macchina che fa
> da server SQL.
>
> In ufficio non si riesce a riprodurre l'errore, nemmeno su un
> VirtualPC con pochissime risorse; anche l'esecuzione in rete non pare
> che dia problemi.
>
hai usato gli stessi sistemi operativi, per riprodurre l'errore?
stesso patch level dei sistemi?
magari dal cliente hai sp2 e tu usi sp3, tanto per dire...
come ti colleghi al server? via netpipe?
provato con protocolli diversi?
> Presso il cliente, l'errore non si manifesta sempre, ma quasi e,
> quando si verifica, lo fa sullo stesso dipendente, ma non sempre nello
> stesso punto di programma (una volta, leggendo dalla tabella A,
> un'altra volta leggendo dalla tabella B, una terza volta leggendo
> dalla tabella C...). Il comune denominatore � l'apertura di un
> recordset per leggere dati da una tabella del db.
>
> Aggiungendo una semplice msgbox al codice, prima dell'elaborazione del
> dipendente incriminato, l'errore non si verifica.
>
[cut]
problemi di controllo dell'input?
qualche apice che fa scazzare il tutto?
le elaborazioni sono fatte tramite sql costruito dal codice oppure
tramite chiamate a stored procedures?
provato a cambiare metodo (da sql a sp o viceversa)?
--
Paolo opg
BE AWARE that this post uses a fake reply-to address
to contact me write to:
janickg ( at ) hotmail ( dot ) com
--
Riprodotto proprio un minuto fa il problema: si verifica se il server SQL �
un Windows 2003.
Alex
L'aleatorietᅵ ᅵ un indice importante.
Se tu stessi sbagliando una password, oppure non fossi autenticato NT
(a proposito, un errore come quello presuppone di concentrarsi sulla
sicurezza del SqlServer e sulla rete, e sono le uniche cose di cui non
parli), avresti il totale non funzionamento del software (sempre che il
software non usi credenziali diverse per operazioni diverse, nel qual
caso dovresti sapere tu).
Il fatto che in genere vada, ma che si fermi nel compiere una
determinata operazione su un determinato record, fa pensare a qualcosa
di collegato alla specifica elaborazione.
E sai solo tu cosa avvenga per ogni elemento da gestire. Ad esempio,
avvengono sempre le stesse cose per ciascun dipendente, o avvengono
cose diverse per dipendenti diversi? Se cosᅵ fosse, verificherei cosa
avviene per quel dipendente e che non avviene per gli altri.
O anche solo se per quel dipendente devono essere eseguite operazioni
piᅵ lunghe, potrebbe esserci un timeout, poi cerchi di riconnetterti ma
magari non hai attivato il persist-security-info, o cose del genere.
Purtroppo, oltre non si puᅵ dire senza sapere esattamente cosa avvenga
per quel dipendente.
Ciao
Alberto
--
Alessandro Bergonzoni: Il tempo vola e noi no. Strano sarebbe se noi
volassimo e il tempo no, il cielo sarebbe pieno di uomini con
l'orologio fermo.
Apertura della connessione al db:
Set cnn = New ADODB.Connection
cnn.Open StringConn, Uid, Pwd
Apertura del recordset:
StrSql = "Select * from..."
Set Rs = New ADODB.Recordset
Rs.ActiveConnection = cnn
Rs.CursorType = adOpenKeyset
Rs.LockType = adLockOptimistic
Rs.CursorLocation = adUseClient
Rs.Open StrSql
Messaggio di errore restituito:
[DBNETLIB][ConnectionOpen (Connect()).]Server SQL inesistente o accesso
negato.
> L'aleatoriet� � un indice importante.
> Se tu stessi sbagliando una password [...] avresti il totale non
> funzionamento del software
Infatti il programma, per un po', funziona correttamente.
> Il fatto che in genere vada, ma che si fermi nel compiere una determinata
> operazione su un determinato record, fa pensare a qualcosa di collegato
> alla specifica elaborazione.
> E sai solo tu cosa avvenga per ogni elemento da gestire. Ad esempio,
> avvengono sempre le stesse cose per ciascun dipendente, o avvengono cose
> diverse per dipendenti diversi? Se cos� fosse, verificherei cosa avviene
> per quel dipendente e che non avviene per gli altri.
> O anche solo se per quel dipendente devono essere eseguite operazioni pi�
> lunghe, potrebbe esserci un timeout, poi cerchi di riconnetterti ma magari
> non hai attivato il persist-security-info, o cose del genere.
In realt�, il programma non si ferma sempre nello stesso punto preciso: si
blocca sull'elaborazione dello stesso lavoratore (talvolta quello
successivo), ma non sempre nella stessa routine. Il programma, per ogni
lavoratore, legge dati da diverse tabelle, esegue delle elaborazioni, scrive
i risultati. L'errore si verifica di volta in volta durante la lettura di
una tabella diversa.
L'oggetto connection viene aperto solo una volta, all'inizio
dell'elaborazione, e viene chiuso una volta, al termine dell'esecuzione
(questo potrebbe essere fonte di problemi?).
Nel corso dell'elaborazione, diversi recordset vengono aperti e (se non mi
son perso qualcosa) chiusi.
Spero di essermi spiegato.
E' come se si esaurisse un determinato spazio per un numero limitato di
interrogazioni del database, superato il quale tutto si blocca; il gestore
dell'ipotetico spazio per le interrogazioni sfoltisce man mano la coda, ma
se la velocit� con cui vengono aperte connessioni al db � troppo veloce, la
coda finisce per saturarsi.
Se si rallenta l'elaborazione, la coda non si riempie; per lo stesso motivo,
dopo la segnalazione dell'errore, tutto riprende a funzionare: il gestore
delle connessioni al db, nel frattempo, � riuscito a svuotare la coda.
Finora, ci� che ho constatato � che l'errore sembra verificarsi solo se il
server SQL � Windows 2003.
Alex
In attesa di capire un po' meglio e di indagare sull'eventuale eccesso di
risorse sfruttate (e magari lasciate "appese") dal programma, per il
momento, mi pare di aver risolto impostando sui pc client le seguenti chiavi
di registro:
- MaxUserPort
- TcpTimedWaitDelay
http://www.sqlservermart.com/SQLServer.aspx
http://support.microsoft.com/kb/328476
Grazie moltissime a Paolo, Albe e a tutti per la disponibilit�.
Ciao!
Alex
Mettiamoci anche un SET davanti, cosᅵ stiamo piᅵ tranquilli e funziona
anche senza persist security...
Set Rs.ActiveConnection = cnn
> Rs.CursorType = adOpenKeyset
> Rs.LockType = adLockOptimistic
> Rs.CursorLocation = adUseClient
> Rs.Open StrSql
>
> Messaggio di errore restituito:
> [DBNETLIB][ConnectionOpen (Connect()).]Server SQL inesistente o accesso
> negato.
>
>> L'aleatorietᅵ ᅵ un indice importante.
>> Se tu stessi sbagliando una password [...] avresti il totale non
>> funzionamento del software
>
> Infatti il programma, per un po', funziona correttamente.
>
>> Il fatto che in genere vada, ma che si fermi nel compiere una determinata
>> operazione su un determinato record, fa pensare a qualcosa di collegato
>> alla specifica elaborazione.
>> E sai solo tu cosa avvenga per ogni elemento da gestire. Ad esempio,
>> avvengono sempre le stesse cose per ciascun dipendente, o avvengono cose
>> diverse per dipendenti diversi? Se cosᅵ fosse, verificherei cosa avviene
>> per quel dipendente e che non avviene per gli altri.
>> O anche solo se per quel dipendente devono essere eseguite operazioni piᅵ
>> lunghe, potrebbe esserci un timeout, poi cerchi di riconnetterti ma magari
>> non hai attivato il persist-security-info, o cose del genere.
>
> In realtᅵ, il programma non si ferma sempre nello stesso punto preciso: si
> blocca sull'elaborazione dello stesso lavoratore (talvolta quello
> successivo), ma non sempre nella stessa routine. Il programma, per ogni
> lavoratore, legge dati da diverse tabelle, esegue delle elaborazioni, scrive
> i risultati. L'errore si verifica di volta in volta durante la lettura di
> una tabella diversa.
> L'oggetto connection viene aperto solo una volta, all'inizio
> dell'elaborazione, e viene chiuso una volta, al termine dell'esecuzione
> (questo potrebbe essere fonte di problemi?).
Non ᅵ proprio cosᅵ, se non usi il Set.
Usando l'ActiveConnection come fai tu, in realtᅵ stai passando al nuovo
recordset NON il riferimento alla connection, ma la connectionstring, e
l'apertura del recordset arriva ad implicare l'apertura di una nuova
Connection implicita (tant'ᅵ che ti segnala un errore di apertura
connessione all'apertura di un recordset, il che, a prescindere, indica
che il problema non ᅵ nel recordset).
Ma la connectionstring che viene estratta dall'oggetto connectione
inglobata nell'oggetto recordset per la futura apertura della
connection implicita on-demand, ᅵ priva di password qualora non sia
specificato persist-security-info=true.
Poi Ado riesce spesso a farti funzionare tutto usando il connection
pooling.
> Nel corso dell'elaborazione, diversi recordset vengono aperti e (se non mi
> son perso qualcosa) chiusi.
> Spero di essermi spiegato.
> E' come se si esaurisse un determinato spazio per un numero limitato di
> interrogazioni del database, superato il quale tutto si blocca; il gestore
> dell'ipotetico spazio per le interrogazioni sfoltisce man mano la coda, ma se
> la velocitᅵ con cui vengono aperte connessioni al db ᅵ troppo veloce, la coda
> finisce per saturarsi.
> Se si rallenta l'elaborazione, la coda non si riempie; per lo stesso motivo,
> dopo la segnalazione dell'errore, tutto riprende a funzionare: il gestore
> delle connessioni al db, nel frattempo, ᅵ riuscito a svuotare la coda.
>
> Finora, ciᅵ che ho constatato ᅵ che l'errore sembra verificarsi solo se il
> server SQL ᅵ Windows 2003.
Forse con W2003 il connection pooling funziona in modo diverso, in
effetti ᅵ una cosa che la stessa MS ha 'deprecato' subito dopo averla
inventata.
Comunque vado a sentimento, io ho sempre evitato questo tipo di
approccio...
Alberto
--
Charles Baudelaire: C'ᅵ un solo modo di dimenticare il tempo:
impiegarlo.
> Mettiamoci anche un SET davanti, cos� stiamo pi� tranquilli e funziona
> anche senza persist security...
> Set Rs.ActiveConnection = cnn
Non ci avevo fatto proprio caso al fatto che mancava il "set".
L'arteriosclerosi galoppa! :-)
Comunque, ho provato a correggere la routine di apertura del recordset e
tutto va esattamente come prima: l'errore si ripresenta sulla macchina
virtuale con Win2003.
> [...]
> (tant'� che ti segnala un errore di apertura connessione all'apertura di
> un recordset, il che, a prescindere, indica che il problema non � nel
> recordset).
Vero.
> Ma la connectionstring che viene estratta dall'oggetto connectione
> inglobata nell'oggetto recordset per la futura apertura della connection
> implicita on-demand, � priva di password qualora non sia specificato
> persist-security-info=true.
> Poi Ado riesce spesso a farti funzionare tutto usando il connection
> pooling.
Questa non l'ho capita del tutto. Cio�, capisco fino a quando mi dici che la
stringa di connessione � priva di password, se non � specificato impostato a
"true" il parametro "persist security info".
Ok. Infatti, tempo fa, avevo riscontrato un problema dovuto proprio al fatto
che in alcuni punti del programma veniva aperta una nuova connection sulla
base di una stringa di connessione passata da un altro oggetto connection;
la stringa di connessione era priva di password e il programma non riusciva
ad aprire la nuova connessione. Del problema, per�, non ci siamo mai accorti
finch� non � arrivato Vista.
Quando dici che ado riesce a far funzionare tutto usando il connection
pooling, significa che lui si "ricorda" di aver gi� aperto quella
connessione a quel database e va a recuperarla dal pool di connessioni,
superando la mancanza di password nella nuova stringa di connessione?
Questo mi spiegherebbe un bel po' di cose.
> Forse con W2003 il connection pooling funziona in modo diverso, in effetti
> � una cosa che la stessa MS ha 'deprecato' subito dopo averla inventata.
S�? Cercher� di documentarmi. Tu hai sotto mano qualche articolo da
segnalarmi sull'argomento?
> Comunque vado a sentimento, io ho sempre evitato questo tipo di
> approccio...
Che ti devo dire...? Io sono senz'altro un ignorante, ma questo tipo di
approccio non me lo sono scelto io. :-)
Grazie ancora.
Alex