Threads x SQL
Boa tarde!
Montei uma thread que se passa o parâmetro um ClientDataSet para abrir.
Intúito: Enquanto o(s) ClientDataSet(s) esta sendo aberto mostrar uma
barra de progresso enganosa, só para a APP não parecer travada.
Até ai tudo bem, vi que FUNCIONA blz, agora percebi que as threads tem um recurso interessante, que é pausar, e continuar, verifiquei que se pode pausar uma busca, cancelar, e continuar quando desejado, mas...
1º Essas operações podem afetar de alguma forma a estabilidade do servidor de BD? (no caso firebird)
2º Podem Prejudicar a estabilidade da APP em si?
3º Pela lógica não, mas pode acontecer de alguma perda de dados pelo fato de pausar a SQL?
Agradeço a atenção.
Código da Thread:
Montei uma thread que se passa o parâmetro um ClientDataSet para abrir.
Intúito: Enquanto o(s) ClientDataSet(s) esta sendo aberto mostrar uma
barra de progresso enganosa, só para a APP não parecer travada.
Até ai tudo bem, vi que FUNCIONA blz, agora percebi que as threads tem um recurso interessante, que é pausar, e continuar, verifiquei que se pode pausar uma busca, cancelar, e continuar quando desejado, mas...
1º Essas operações podem afetar de alguma forma a estabilidade do servidor de BD? (no caso firebird)
2º Podem Prejudicar a estabilidade da APP em si?
3º Pela lógica não, mas pode acontecer de alguma perda de dados pelo fato de pausar a SQL?
Agradeço a atenção.
Código da Thread:
unit uTread;
interface
uses
Classes , dbclient , db , forms;
type
TOpenSQl = class(TThread)
private
dsForOpen : TdataSource;
qr : Tdataset;
procedure OpenCDS;
procedure connectDataSource;
procedure disconnectDataSource;
protected
procedure Execute; override;
public
constructor create(ds : TdataSource);
end;
implementation
uses Unit1;
{ Important: Methods and properties of objects in visual components can only be
used in a method called using Synchronize, for example,
Synchronize(UpdateCaption);
and UpdateCaption could look like,
procedure TOpenSQl.UpdateCaption;
begin
Form1.Caption := ´Updated in a thread´;
end; }
{ TOpenSQl }
procedure TOpenSQl.connectDataSource;
begin
dsForOpen.dataset := qr;
end;
constructor TOpenSQl.create(ds: TdataSource);
begin
inherited create(true);
dsForOpen := ds;
end;
procedure TOpenSQl.disconnectDataSource;
begin
qr := dsForOpen.dataset;
dsForOpen.dataset := nil;
end;
procedure TOpenSQl.Execute;
begin
Synchronize(disconnectDataSource);
OpenCDS;
Synchronize(connectDataSource);
{ Place thread code here }
end;
procedure TOpenSQl.OpenCDS;
begin
qr.open;
end;
end.Chapolin
Curtidas 0
Respostas
Dmalta
09/09/2006
Boa pergunta, Chapolin! :D
A princípio, já seria um problema deixar o usuário pausar a consulta porque vai manter uma transação aberta, e isso vai criar problemas inerentes a uma transação longa - desde o acúmulo de lixo no log de transações do servidor até o travamento de acesso concorrente de leitura e/ou gravação por outros usuários.
Outro ponto problemático é que não temos controle sobre a arquitetura de diversas camadas de interoperabilidade que fazem o acesso a dados: tem os componentes da VCL Delphi, frameworks de acesso a dados como Microsoft ADO, bibliotecas clientes nativas do banco de dados, middleware de conectividade (COM), middleware de rede (TCP/IP, sockets) do sistema operacional e tem o próprio gerenciador de banco de dados (FB, IB, MSSQL, Oracle...)
Como cada um desses irá se comportar à suspensão de uma query? Você pode testar e ver no que dá. De qualquer forma, eu não confiaria muito nesses testes, porque não temos como prever o comportamente dessas tantas ´caixas pretas´ que estão no caminho em situações específicas e comprometer a integridade da aplicação.
Por outro lado, alguns sistemas de BD têm suporte nativo ao [i:4ae2c56af1]cancelamento[/i:4ae2c56af1] de queries. Se for o caso, isso deve ser tranquilo. Suspender, no entanto, eu não conheço nenhum banco de dados ou middleware que dê suporte. No meu entender é totalmente [i:4ae2c56af1]anti-relacional[/i:4ae2c56af1], por causa do problema das transações.
A princípio, já seria um problema deixar o usuário pausar a consulta porque vai manter uma transação aberta, e isso vai criar problemas inerentes a uma transação longa - desde o acúmulo de lixo no log de transações do servidor até o travamento de acesso concorrente de leitura e/ou gravação por outros usuários.
Outro ponto problemático é que não temos controle sobre a arquitetura de diversas camadas de interoperabilidade que fazem o acesso a dados: tem os componentes da VCL Delphi, frameworks de acesso a dados como Microsoft ADO, bibliotecas clientes nativas do banco de dados, middleware de conectividade (COM), middleware de rede (TCP/IP, sockets) do sistema operacional e tem o próprio gerenciador de banco de dados (FB, IB, MSSQL, Oracle...)
Como cada um desses irá se comportar à suspensão de uma query? Você pode testar e ver no que dá. De qualquer forma, eu não confiaria muito nesses testes, porque não temos como prever o comportamente dessas tantas ´caixas pretas´ que estão no caminho em situações específicas e comprometer a integridade da aplicação.
Por outro lado, alguns sistemas de BD têm suporte nativo ao [i:4ae2c56af1]cancelamento[/i:4ae2c56af1] de queries. Se for o caso, isso deve ser tranquilo. Suspender, no entanto, eu não conheço nenhum banco de dados ou middleware que dê suporte. No meu entender é totalmente [i:4ae2c56af1]anti-relacional[/i:4ae2c56af1], por causa do problema das transações.
GOSTEI 0
Chapolin
09/09/2006
certo, me convenci que realmente pausar seria um ônus que pode custar muito caro.
E quanto a forma que estou fazendo para abrir a query dentro da thread, esta correto?
qual a regra para que eu deva chamar o método pelo syncronize?
pois se eu mandar o syncronize abrir o dataset, vai ficar travado pois é a thread principal que abre, jogando fora todo objetivo.
obrigado pela atenção!
E quanto a forma que estou fazendo para abrir a query dentro da thread, esta correto?
qual a regra para que eu deva chamar o método pelo syncronize?
pois se eu mandar o syncronize abrir o dataset, vai ficar travado pois é a thread principal que abre, jogando fora todo objetivo.
obrigado pela atenção!
GOSTEI 0
Dmalta
09/09/2006
Está certo, sim.
A regra para chamar [b:788ec29291]Synchronize[/b:788ec29291] é que deve ser usado sempre e somente quando quiser mexer com qualquer propriedade visual ou variável global na aplicação, porque isso seria entrar no ´domínio´ da thread principal do programa.
Essa unit faz Synchrinze quando conecta e quando disconecta do DataSource porque presume que objetos visuais, como um TDBGrid, estejam ligados a ele.
A regra para chamar [b:788ec29291]Synchronize[/b:788ec29291] é que deve ser usado sempre e somente quando quiser mexer com qualquer propriedade visual ou variável global na aplicação, porque isso seria entrar no ´domínio´ da thread principal do programa.
Essa unit faz Synchrinze quando conecta e quando disconecta do DataSource porque presume que objetos visuais, como um TDBGrid, estejam ligados a ele.
GOSTEI 0
Dmalta
09/09/2006
Outra coisa, adicione no método Create essa linha, para liberar automaticamente o objeto Thread da memória quando o dataset terminar de ser aberto:
FreeOnTerminate := True;
GOSTEI 0
Chapolin
09/09/2006
Ok, vou colocar esse código!
muito obrigado, e fica a dica pro pessoal que quizer usar esse esquema interessante
abraço!
muito obrigado, e fica a dica pro pessoal que quizer usar esse esquema interessante
abraço!
GOSTEI 0
Macario
09/09/2006
Ola.
Posso fazer uso dessa rotina para executar uma SP no MSSQL2000 via dbexpress?
[]´s
Posso fazer uso dessa rotina para executar uma SP no MSSQL2000 via dbexpress?
[]´s
GOSTEI 0