Visualizzazione dei risultati da 1 a 5 su 5
  1. #1

    [DELPHI - Firebird ] : Problemi con Transazioni

    Salve a tutti,
    ho un problema con un programma realizzato in Dephi che si collega con un database Firebird tramite i componenti ADO e quindi via ODBC.

    Il problema sorge perchè ho più client che si collegano al database e fanno delle transazioni su due tabelle in particolare; dopo un lasso di tempo imprecisato queste due tabelle risultano bloccate e di conseguenza si bloccano anche gli applicativi.
    Se però provo ad accedere a queste due tabelle utilizzando IBOConsole, quindi in maniera nativa, queste non risultano bloccate.
    Se invece faccio la prova del nove con SQLExplorer queste risultano ovviamente bloccate.

    Quindi Per sbloccare la situazione non mi resta che riavviare il server di firebird.

    Ho allora pensato di cambiare i collegamenti utilizzando invece dei componenti ADO, componenti DBExpress, ma qui si sono presentati problemi più gravi.

    Siccome la maggior parte delle interrogazioni e degli inserimenti l'applicativo li fa con dei Thread, quando due thread provano a fare una semplice SELECT, una delle due rimane bloccata!

    Allora mi sono chiesto se i componenti DBExplorer siano Thread-safe, ma su internet non ci sono risposte in merito.

    Consigli?
    "Due cose riempiono l’animo di ammirazione e venerazione sempre nuova e crescente, quanto piú spesso e piú a lungo la riflessione si occupa di esse: il cielo stellato sopra di me, e la legge morale in me..." Immanuel Kant

  2. #2
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,325
    I componenti dbExpress, ADO, ecc. non sono multithreading, ma non credo che questo sia la causa del tuo problema, a meno che tu non abbia utilizzato le stesse istanze (stessa SQLConnection, oppure stessa SQLQuery, ecc.) per più thread, e allora in tal caso avresti problemi ben peggiori.

    Il problema potrebbe essere dovuto al "transaction scope", cioè al tipo di "condivisione" che viene associato alle transazioni per quanto riguarda i dati modificati; ad esempio, è possibile bloccare una tabella impedendo l'accesso ad altre transazioni quando questa è interessata da operazioni eseguite all'interno di un'altra transazione, oppure consentire l'accesso ad una transazione ma senza avere la visibilità dei dati modificati da un'altra transazione separata, oppure consentire a due transazioni di vedere i "dati sporchi", cioè tutte le modifiche, anche quelle non confermate tramite commit.

    Fossi in te, cercherei un po' di documentazione relativa alle transazioni con ADO, o con dbExpress, verificando le opzioni possibili, gli effetti relativi e controllando quale degli scenari si adatta maggiormente all'architettura del tuo applicativo (che non conosco in dettaglio).

    Ciao!
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  3. #3
    Allora nel mio caso ho 5 thread dei quali solo 2 fanno transazioni.
    Quindi ho creato due SQLconnection una per ogni thread che fa transazioni, mentre agli altri thread gli passo SQLQry che sono collegati alla prima SQLconnection.
    In questa maniera con ADO non ho nessun problema immediato se non il blocco della connessione dopo un lasso di tempo imprecisato.

    Con DBexpress invece ho problemi sin da subito.


    Comunque il tipo di transazione di cui avrei bisogno è il primo che hai menzionato e con ADO in parte funzionava (fino quando non si bloccava).. una cosa da segnalare è che dava molti errori di Deadlock, se infatti due applicativi provavano a fare la transazione contemporaneamente sulla stessa tabella il primo la effettuava, mentre il secondo attendeva la fine della transazione del primo per darmi un errrore di deadlock... per aggirare il problema io facevo un ciclo che si completava solo quando la transazione riusciva ( gli errori li scriveva in una tabella di controllo ed erano sempre errori di deadlock).
    Eppure nella configurazione dell'ODBC gli avevo dato come opzione "Wait" per le transazioni!!
    "Due cose riempiono l’animo di ammirazione e venerazione sempre nuova e crescente, quanto piú spesso e piú a lungo la riflessione si occupa di esse: il cielo stellato sopra di me, e la legge morale in me..." Immanuel Kant

  4. #4
    Moderatore di Programmazione L'avatar di alka
    Registrato dal
    Oct 2001
    residenza
    Reggio Emilia
    Messaggi
    24,325
    Originariamente inviato da Whitecrowsrain
    Quindi ho creato due SQLconnection una per ogni thread che fa transazioni, mentre agli altri thread gli passo SQLQry che sono collegati alla prima SQLconnection.
    Non puoi condividere gli stessi oggetti tra più thread a meno che questi non siano thread-safe, e non lo sono, oppure proteggendone l'accesso con elementi di sincronizzazione (critical section, mutex, ecc.).

    Questa è senz'altro un'area in cui bisogna intervenire.

    Risolta questa, puoi passare ad analizzare altri problemi.
    MARCO BREVEGLIERI
    Software and Web Developer, Teacher and Consultant

    Home | Blog | Delphi Podcast | Twitch | Altro...

  5. #5
    Originariamente inviato da alka
    Non puoi condividere gli stessi oggetti tra più thread a meno che questi non siano thread-safe, e non lo sono, oppure proteggendone l'accesso con elementi di sincronizzazione (critical section, mutex, ecc.).

    Questa è senz'altro un'area in cui bisogna intervenire.

    Risolta questa, puoi passare ad analizzare altri problemi.
    Ok allora provo a modificare questo, cmq quando creo i thread gli passo gli oggetti SQLQuery per variabile:


    codice:
    var
      qry,qry1,qry2,qry3,qry4,qry5,qry6,qry7,qry8:TADOQuery;
      dbconnect1,dbconnect:TADOConnection;
    procedure TMain.avviaThread;
    begin
      qry.connection:=dbconnect;
      qry1.connection:=dbconnect;
      qry2.connection:=dbconnect;
      qry3.connection:=dbconnect1;
      qry4.connection:=dbconnect1;
      qry5.connection:=dbconnect1;
      qry6.connection:=dbconnect;
      qry7.connection:=dbconnect;
      qry8.connection:=dbconnect;
    
      dbconnect.connected:=true;
      dbconnect1.connected:=true;
    
      ThreadUno:=TThreadUno.create(qry,qry1,qry2,dbconnect,tpnormal);
      ThreadDue=TThreadUno.create(qry3,qry4,qry5,dbconnect1,tpnormal,);      
      ThreadTre:=TThreadTre.create(qry6,qry7,qry8,tpnormal);
    end;
    E' sbagliato?
    "Due cose riempiono l’animo di ammirazione e venerazione sempre nuova e crescente, quanto piú spesso e piú a lungo la riflessione si occupa di esse: il cielo stellato sopra di me, e la legge morale in me..." Immanuel Kant

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.