77 messaggi dal 16 maggio 2002
Salve,

mi sono accorto di una cosa molto fastidiosa che succede in una mia applicazione windows, non sono nemmeno sicuro che sia un problema di transazioni anzi, ma non essendo un amministratore di database chiedo a chi è più esperto di togliermi questo dubbio:

in pratica la mia applicazione esegue delle query su un database remoto ospitato in una società di hosting, usando solo store procedure in tutte le sue operazioni, ed effettua una serie di modifiche sul db remoto usando le transizioni da codice .net e non quelle t-sql delle store per intenderci...
in locale tutto perfetto mentre quando va in remoto succede una cosa strana, cioè quando l'applicazione esegue le modifiche sul db remoto esso risulta bloccato in lettura, cioè non si riesce a leggere i dati da un'altra applicazione fin quando non finisce l'aggiornamento la prima.
La colpa subito l'avevo data al livello di isolamento della transazione che usavo ma come ho già detto provando in locale non ho nessun blocco in lettura, questo succede solo quando uso il db in remoto.

Non è che magari quelli hanno un settaggio che mi crea questo problema tipo qualche limite sulle connessioni contemporanee o altro?
voglio essere sicuro prima prendere provvedimenti con loro...

Grazie
1.024 messaggi dal 19 dicembre 2003
Contributi | Blog
pipponet ha scritto:
Salve,

Non è che magari quelli hanno un settaggio che mi crea questo problema tipo qualche limite sulle connessioni contemporanee o altro?
voglio essere sicuro prima prendere provvedimenti con loro...



Il livello di isolamento non è possibile definirlo in maniera "server wide" o "database wide" ma soltanto a livello di connessione utilizzando gli opportuni comandi T-SQL o gli "equivalenti" da codice che il provider OLEDB o il driver ODBC traducono nel corrispondente T-SQL. E' altresì normale che qualora vi sia una modifica a dei dati i relativi record (in verità una "regione" ben più estesa) rimangono in stato di lock FINO AL TERMINE della transazione e non soltanto fino al termine della modifica. A questo riguardo dai un'occhiata al mio articolo su "Il controllo della concorrenza in SQL Server 7.0" (non ci sono differenze al riguardo in SQL Server 2000) pubblicato sul numero 34 del 7/2000 di Visual Basic Journal e che puoi leggere al link

http://italy.mvps.org/MVPs/lbianchi/art_IsolationLevel.htm

La differenza di comportamento che noti tra il "db locale" ed il "db remoto" immagino sia dovuta semplicemente ai diversi tempi necessari nei 2 casi a terminare le operazioni richieste. A meno di errori a livello di codice (una transazione che rimane aperta più del tempo necessario) non mi vengono in mente altre possibilità...

Ciao
77 messaggi dal 16 maggio 2002
Bene Luca grazie, speravo in una tua risposta...

premetto che non è un problema di differenze tra DB locale e remoto, mi ero confuso per motivi lunghi da spiegare..., cmq ho lo stesso problema in locale...

allora quello che ho fatto è usare ovviamente a livello di connessione come dici tu... e da codice ado.net le transizioni associando ad ognuna di esse l'esecuzione di più store procedure parametriche, in queste store non uso nessuna istruzione T-Sql che faccia riferimento a transazioni ed al loro livello di isolamento, perchè appunto volevo gestire tutto e solo da codice... il tutto funziona il problema è appunto la gestione dei blocchi sui dati evidentemente....
Da codice avevo inizialmente impostato il livello read committed, aspettandomi il blocco in lettura al massimo solo dei record interessati della tabella presa in considerazione (ricordo in questo caso che le tabelle considerate sono senza chiavi ne indici e per adesso essendo in fase di test con pochi dati) invece ho avuto un blocco dell'intera tabella, quindi ho provato e risolvere impostando read uncommitted e mi sono accorto che da codice non riesco ad impostare o cmq modificare il livello di isolamento della transizione, mi chiedo sarà perchè non uso query da codice ma uso store parametriche che non riesco ad assegnare il livello di isolamento da codice?
A questa domanda non ho avuto il tempo di rispondere per questioni di tempo... basterebbe fare un tentativo ad es.

Quindi se cosi fosse per eseguire più store parametriche in una transizione da sql server dovrei da codice chiamarne un sola passare tutti i parametri e poi sarà questa all'interno di una transizione chiamare le altre?
Non ci credo che sia l'unico modo...
cmq per adesso ho risolto usando nei tentativi di accedere ai dati bloccati with no lock, che alla fine diciamo che è quello che volevo ma voglio in ogni caso approfondire la cosa...

Luca passo a te la parola.... :-)

P.S. ovviamente ho letto il tuo buon articolo ma solo velocemente e cmq volevo approfondire di più...
1.024 messaggi dal 19 dicembre 2003
Contributi | Blog
pipponet ha scritto:
Bene Luca grazie, speravo in una tua risposta...



:-)


in queste store non uso nessuna istruzione T-Sql che faccia riferimento a transazioni ed al loro livello di isolamento, perchè appunto volevo gestire tutto e solo da codice...


...in ogni caso l'istruzione è all'interno di una transazione, sia essa avviata con un comando T-SQL e sia che venga iniziata da codice...


Da codice avevo inizialmente impostato il livello read committed,


...che rappresenta il default per SQL Server...


aspettandomi il blocco in lettura al massimo solo dei record interessati della tabella presa in considerazione (ricordo in questo caso che le tabelle considerate sono senza chiavi ne indici e per adesso essendo in fase di test con pochi dati) invece ho avuto un blocco dell'intera tabella,


...normale...


quindi ho provato e risolvere impostando read uncommitted e mi sono accorto che da codice non riesco ad impostare o cmq modificare il livello di isolamento della transizione,


...non hai considerato una cosa: il livello di isolamento READ UNCOMMITTED permette la LETTURA di dati in stato di lock (e "sporchi") ma non certamente la non applicazione di uno o più blocchi e qualora la transazione che sta modificato i dati venisse annullata, chi ha eseguito la lettura "read uncommitted" si ritrova ad aver visto delle informazioni che da un punto di vista logico non sono mai esistite. In ogni caso la modifica di dati comporta SEMPRE l'applicazione di un blocco di tipo ESCLUSIVO che durerà fino al TERMINE della transazione stessa...


mi chiedo sarà perchè non uso query da codice ma uso store parametriche che non riesco ad assegnare il livello di isolamento da codice?


...penso sia piuttosto perchè non hai ben chiaro il significato di lock, transazioni e livello di isolamento...


Quindi se cosi fosse per eseguire più store parametriche in una transizione da sql server dovrei da codice chiamarne un sola passare tutti i parametri e poi sarà questa all'interno di una transizione chiamare le altre?


No... eseguire una istruzione del tipo

================
BEGIN TRAN
EXEC sp1 @p1
EXEC sp2 @p2, @p3
EXEC sp3 @p4
COMMIT TRAN
================

equivale in tutto e per tutto a scrivere

================
BEGIN TRAN
EXEC spA @p1, @p2, @p3, @p4
COMMIT TRAN
================

dove spA richiama in sequenza sp1, sp2 e sp3. La domanda che devi porti è: "quali istruzioni devono essere eseguite come una unica unità di lavoro?" In questi casi si fa il tipico esempio della transazione bancaria. Tizio fa un bonifico a Caio di una somma X. Pertanto la duplice operazione che deve essere eseguita sarà

================
BEGIN TRAN
UPDATE contoTizio SET Importo = Importo - X
UPDATE contoCaio SET Importo = Importo + X
COMMIT TRAN
================

se Tizio mentre è allo sportello chiede anche un estratto conto e la domiciliazione di una bolletta, NON vado a racchiudere queste 2 operazioni nella stessa transazione, ma ne apro 3 in tutto. Questo per dirti che una transazione deve rappresentare l'unità minima in cui può essere scissa una attività pur mantenendo l'integrità logica dei dati. Se vado ad eseguire l'estratto conto e la domiciliazione della bolletta nella transazione del bonifico, non faccio altro che allungare i tempi di rilascio dei blocchi (e quindi potenzialmente altri utenti). In cambio quali vantaggi ho? Nessuno!


cmq per adesso ho risolto usando nei tentativi di accedere ai dati bloccati with no lock,


Pessima idea... :-(
Se per qualunque motivo una transazione venisse annullata, sai cosa significa?


che alla fine diciamo che è quello che volevo ma voglio in ogni caso approfondire la cosa...

Luca passo a te la parola.... :-)

P.S. ovviamente ho letto il tuo buon articolo ma solo velocemente e cmq volevo approfondire di più...


Ti suggerisco di leggere un po più attentamente l'articolo e di approfondire eventualmente alcuni attraverso il Book On Line di SQL Server. Ti faccio una domanda: stai gestendo eventuali errori nelle istruzioni transazionali che esegui?

Bye
77 messaggi dal 16 maggio 2002
Evidentemente mi sono espresso male... ti assicuro di non essere cosi scarso Luca :-), almeno in teoria sui database ( ricordo di aver preso 30 e lode in questa materia... non mi rispondere che evidentemente ero raccomandato pero'... ;-) ), io per ora sono in fase di test ed in particolare sto provando a vedere se riesco ad applicare la teoria come voglio io... cioè voglio gestire "tutto" manualmente provando a farlo sia da codice che da solo sql server.... per ora sto solo facendo delle prove di test tutto qui, senza rispettare per adesso la progettazione dal punto di vista logico della gestione dei dati in queste parte del progetto, che ho già fatto, che devo rileggere e che applichero' dopo aver bene capito come operare con i livelli di isolamento di sql server

Ovviamente gestisco gli errori... :-), del resto sarebbe troppo lungo spiegarti il progetto che è abbastanza complesso e questa è solo una minima parte di esso, pero' posso cmq dirti che a me della transazione che tra l'altro è nidificata con altre che fanno riferimento a connessioni di altri DB, interessa principalmente l'atomicità che ovviamente è garantita in ongi caso a prescindere dal tipo di isolamento, anche perchè l'applicazione che ha accesso a questi dati ( se non ricordo male dalla progettazione fatta e che non è messa in discussione... :-) ) non puo' fare modifiche ma solo visualizzare, cioè non partiranno da essa operazioni che richiederanno blocchi esclusivi o di aggiornamento, quindi letture fantasma o anche il caso di lettura di dati non permanenti e che quindi potrebbero essere annullati da un rollback... sono "accettabili" nel mio contesto, anche perchè nel 99% dei casi le stesse modifiche annullate saranno riprese poco dopo perchè all'interno di un evento automatizzato ma questo è un discorso che non importa in questa discussione..., non lo è aspettare che l'altra transazione finisca e rilasci i dati.
Quindi in questo caso usare il with no lock equivale ad usare il livello read uncommitted giusto? e credo che alla fine la cosa mi vada bene...

Del resto credo sia corretto dire che a prescindere dal livello di isolamento usato se si effettua una modifica dei dati per forza si avrà un blocco non condiviso che rimarrà tale fino alla fine della transazione per questione di atomicità della stessa diciamo...
quello invece che pensavo, e che cmq mi interessa approfondire ancora di più è il tipo di blocco di pagina, record e tabella, cioè pensavo che questo potesse dipendere anche dal livello di isolamento usato nella richiesta di blocchi esclusivi... mi sembra cosi non è e che forse non si puo' "forzare" sql server ad es. a fargli eseguire un blocco solo sui record da modificare e non sua una tabella ecc.
questo intendevo quando dicevo che mi iteressava approfondire ancora di piu' oltre al tuo buon articolo, perchè in quest'ultimo credo la cosa non sia trattata in modo approfondito, evidentemente perchè non era lo scopo dello stesso...

Quindi oltre alle correzioni delle cose dette sopra, ti chiedo di darmi qualche imput su quest'ultimo argomento, cioè se si puo' interferire manualemnte sulla quantità di record da bloccare, se ha senso farlo e quindi se conviene e se si in quali casi...

Ovviamente ti ringrazio per la tua gentilezza e pazienza....

Ciao
1.024 messaggi dal 19 dicembre 2003
Contributi | Blog
pipponet ha scritto:
Evidentemente mi sono espresso male... ti assicuro di non essere cosi scarso Luca :-), almeno in teoria sui database ( ricordo di aver preso 30 e lode in questa materia... non mi rispondere che evidentemente ero raccomandato pero'... ;-) ),


...non dico questo, ci mancherebbe altro, però conosco il "livello" di alcuni esami universitari... ;-)


e questa è solo una minima parte di esso, pero' posso cmq dirti che a me della transazione che tra l'altro è nidificata con altre che fanno riferimento a connessioni di altri DB,


A che cosa ti serve nidificare delle transazioni? Sai che scrivere

==========================
BEGIN TRAN
istruzione1
BEGIN TRAN
istruzione2
BEGIN TRAN
istruzione3
COMMIT TRAN
COMMIT TRAN
istruzione4
COMMIT TRAN
==========================

equivale in tutto e per tutto a scrivere

==========================
BEGIN TRAN
istruzione1
istruzione2
istruzione3
istruzione4
COMMIT TRAN
==========================

ed oltretutto rende (molto) più leggibile il codice e contribuisce ad evitare errori di "dimenticare" transazioni aperte...


non puo' fare modifiche ma solo visualizzare, cioè non partiranno da essa operazioni che richiederanno blocchi esclusivi o di aggiornamento, quindi letture fantasma o anche il caso di lettura di dati non permanenti e che quindi potrebbero essere annullati da un rollback...


...qualcuno che fa modifiche ci deve pur essere, altrimenti i blocchi esclusivi chi li applica? Mi sembra uno dei problemi che riscontri è proprio quello di problemi legati a questo tipo di blocchi, no? Ovviamente mi riferisco NON alla tua applicazione ma al complesso delle attività che vengono svolte sul database eventualmente anche da altre applicazioni che a questo punto sono loro a causare problemi...


Quindi in questo caso usare il with no lock equivale ad usare il livello read uncommitted giusto?


...esatto... ma io indagherei su come fanno quei blocchi esclusivi ad essere presenti e soprattutto ad essere così invasivi...


mi sembra cosi non è e che forse non si puo' "forzare" sql server ad es. a fargli eseguire un blocco solo sui record da modificare e non sua una tabella ecc.


Quello che devi tenere a mente sono principalmente i fattori legati all'efficienza e i blocchi impliciti. Poichè ogni blocco che viene applicato richiede delle risorse al sistema, è molto più efficiente gestire un solo blocco a livello di pagina piuttosto che talvolta diverse centinaia (o migliaia) di blocchi a livello di riga. Inoltre non dimenticarti che anche un blocco a livello di riga comporta l'applicazione di un blocco sulle risorse che contengono la riga. Se blocco in maniera esclusiva un record risulteranno implicitamente bloccate anche la pagina e la tabella che lo contengono in quanto non sarà possibile per altre connessioni/transazioni acquisire un blocco esclusivo sulla pagina/tabella in cui risulta bloccato un solo record. SQL Server gestisce autonomamente (e bene) il "lock escalation" basandosi su criteri di efficienza la granularità del blocco da applicare. Nelle versioni precedenti di SQL Server era possibile configurare (con la sp_configure) la "soglia" in base alla quale scalare il blocco alla risorsa superiore ma questa opzione finiva con il penalizzare pesantemente chi utilizzava in maniera impropria (e inadeguata) i valori di default. Non ho mai visto una modifica "sensata" di questo parametro di configurazione (e di scenari ne ho visti abbastanza) per cui non posso che condividere la scelta fatta dai progettisti MS...


questo intendevo quando dicevo che mi iteressava approfondire ancora di piu' oltre al tuo buon articolo, perchè in quest'ultimo credo la cosa non sia trattata in modo approfondito, evidentemente perchè non era lo scopo dello stesso...


...trattare l'argomento in maniera esaustiva avrebbe richiesto non un articolo ma un libro come ha fatto Kalen Delaney (l'autrice di "Inside SQL Server 2000") che ha pubblicato recentemente "Hands-On SQL Server 2000 : Troubleshooting Locking and Blocking" di cui puoi visualizzare una scheda al link

http://www.shareit.com/product.html?cart=1&productid=183645&affiliateid=&languageid=1&cookies=1&backlink=http://www.netimpress.com/Default.asp?&currencies=USD

e ti assicuro che anche in questo libro ci sono alcuni argomenti che meriterebbero di essere approfonditi :-)


Quindi oltre alle correzioni delle cose dette sopra, ti chiedo di darmi qualche imput su quest'ultimo argomento, cioè se si puo' interferire manualemnte sulla quantità di record da bloccare, se ha senso farlo e quindi se conviene e se si in quali casi...


La scelta più saggia da fare è quella di lasciar gestire a SQL Server la granularità del blocco sia in considerazione del fatto che "SQL Server ne sa più di noi" e sia perchè la scelta "automatica" si rivela in grado di rispondere ad eventuali (sicure) mutate esigenze. Ritengo inevitabile che le dimensioni e la distribuzione dei dati nella tabella nonchè il tipo di attività che verranno eseguite possano alterare in maniera significativa quelle che oggi potrebbero essere delle ottime scelte implementative. Il più delle volte i problemi del genere sono dovuti non a "impropria" gestione dei lock (e del livello di isolamento delle transazioni) ma piuttosto da errori a livello applicativo. Non mi riferisco soltanto a transazioni lasciate aperte per errore ma soprattutto a transazioni che vengono aperte e durano più del dovuto in quanto si attende l'elaborazione di un risultato, un calcolo da parte del client o, peggio, un input dell'utente, che fanno in modo che per tutto questo tempo (fino a che l'elaborazione termina oppure fino a che l'utente decide di riempire una input box) la transazione rimanga inutilmente aperta. Per quanto possibile le elaborazioni, gli input dell'utente e quant'altro possa interferire con il database server andrebbe eseguito PRIMA di avviare la transazione in maniera tale da farla andare a "palla di cannone" e SENZA alcuna interazione (umana o del client) dal BEGIN TRAN al COMMIT o ROLLBACK. Purtroppo questo è un aspetto in cui vale poco disegnare in maniera tecnicamente ineccepibile una applicazione di accesso ai dati se sullo stesso db lavora già una applicazione che fa il proprio comodo in barba a tutte le norme di buona progettazione...


Ovviamente ti ringrazio per la tua gentilezza e pazienza....
Ciao

...oooppsss...
Mentre scrivevo non mi accorgevo delle dimensioni del messaggio, spero solo che Daniele non mi ammonisca per questo... :-))
77 messaggi dal 16 maggio 2002
Scusami Luca riguardo il tuo esempio sulle nidificazioni delle transazioni dovrei essere ubriaco :-) per fare questo :

==========================
BEGIN TRAN
istruzione1
BEGIN TRAN
istruzione2
BEGIN TRAN
istruzione3
COMMIT TRAN
COMMIT TRAN
istruzione4
COMMIT TRAN
==========================

io mio caso è associare alcune "operazioni" ad una transizione in sql server ed altre alla "stessa" transizione ma non su DB sql server e quindi altri driver ed altra connessione, quindi cosi per capirci... o faccio il commit di tutte e 2 oppure se una va in rollback ci andrà anche l'altra in maniera tale che è come se fosse un unica transizione riguardo all'atomicià ovviamente... e che opera su DB diversi


Ritornando ai miei blocchi... :-)
per spiegarmi meglio, immagina per semplicità solo un'applicazione che lancia una transizione nella quale vengono fatte diverse operazioni tra le quali delle modifiche sui dati provocando dei blocchi sugli stessi(record o pagine o tabelle che siano...)
ora immaginiamo una diversa applicazione che legge solamente questi dati ma che non li puo' modificare, ora il blocco così invasivo è dovuto al tempo lungo di esecuzione della transizione della prima appl. che appunto tiene bloccati i dati fino al commit, del resto il blocco è inevitalbile e non dipende dal livello di isolamento perchè trattandosi di modifiche in ogni caso si avrebbe il blocco (cioè anche impostanto la transizione della prima appl. come read uncommitted si avrebbe giustamente lo stesso in caso di modifiche un blocco esclusivo di quei dati...) giusto?
Quindi per non impedire l'accesso ai dati alla secodna appl. non rimane altro che leggere pure i dati bloccati non ancora confermati ecc. usando with nolock e forse nemeno readpast perchè credo potrei avere lo stesso problema...
Tutto giusto?

Si mi avevano detto che il primo libro da te consigliato della Kalen Delaney fosse quasi la bibbia di sql server e l'autrice fosse tra le migliori esperte in circolazione, se non ricordo male è stato Dino Esposito a dirmelo, cmq tra i due libri quale consigli il primo non è più completo?
Si è già capito che non ho letto nessuno dei due... :-)

concordo su tutto il resto ed in particolare con il discorso di far andare a palla la transazione come dici tu... ovviamente non si deve interromperla per colpa di un'interazione da utente... ma la lentezza nel mio caso non è dovuta ovviamente a questo, ma al db remoto...

no come puo' Daniele ammonirti per questo farebbe sicuramente l'opposto... :-)
del resto questa discussione volendo si poteva pure farla in privato, ma come già sappiamo questo sarebbe stato in contrasto con lo spirito dei forum... potrebbe servire ad altri leggere tutto questo...

Grazie ancora

Ciao

1.024 messaggi dal 19 dicembre 2003
Contributi | Blog
pipponet ha scritto:
o faccio il commit di tutte e 2 oppure se una va in rollback ci andrà anche l'altra in maniera tale che è come se fosse un unica transizione riguardo all'atomicià ovviamente... e che opera su DB diversi


...quindi parliamo di una transazione DISTRIBUITA... allora il discorso ha un senso anche se questo tipo di esigenza inevitabilmente penalizza la concorrenza...

Quindi per non impedire l'accesso ai dati alla secodna appl. non rimane altro che leggere pure i dati bloccati non ancora confermati ecc. usando with nolock e forse nemeno readpast perchè credo potrei avere lo stesso problema...
Tutto giusto?


READPAST ha un comportamento ancora diverso. NOLOCK legge i dati come sono al momento della lettura (ma li legge); READPAST salta i dati su cui vi è un blocco. Entrambe queste soluzioni non sono accettabili se non in ambienti di tipo DSS (Decision Support System) dove si richiede una lettura di una grande quantità di dati a scopo di reportistica. In questo scenario su diverse centinaia di milioni di record saltarne qualche decina perchè bloccati non sposta i risultati finali. A seconda delle necessità in questo tipo di ambienti la soluzione è quella di "scalare orizzontalmente" aggiungendo nuove tabelle di sintesi, nuovi database o nuovi server da dedicare a questo tipo di attività.


Si mi avevano detto che il primo libro da te consigliato della Kalen Delaney fosse quasi la bibbia di sql server e l'autrice fosse tra le migliori esperte in circolazione, se non ricordo male è stato Dino Esposito a dirmelo, cmq tra i due libri quale consigli il primo non è più completo?
Si è già capito che non ho letto nessuno dei due... :-)


Sottoscrivo. INSIDE SQL SERVER rappresenta una guida che non può mancare nella biblioteca di un DBA (al pari di TRANSACT-SQL Programmazione Avanzata di Itzik Ben-Gan e Tom Moreau). Da non trascurare tuttavia il Book On Line di SQL Server che invece molto spesso è sottovalutato anche da utenti esperti...


del resto questa discussione volendo si poteva pure farla in privato, ma come già sappiamo questo sarebbe stato in contrasto con lo spirito dei forum... potrebbe servire ad altri leggere tutto questo...


Sottoscrivo anche questo. Talvolta degli utenti del newsgroup su SQL Server mi scrivono in privato ma puntualmente li invito a postare il quesito "in pubblico" dove oltre ad essere di aiuto per tutti, tutti possono dare il loro contributo... La forza delle community è soprattutto questa...

Bye

Torna al forum | Feed RSS

ASPItalia.com non è responsabile per il contenuto dei messaggi presenti su questo servizio, non avendo nessun controllo sui messaggi postati nei propri forum, che rappresentano l'espressione del pensiero degli autori.