Travamento pessmista com Delphi Firebird 1.5
Bom dia pessoal.
Algum tempo atras estive trocando umas ideias aqui no forum
sobre travamento pessimista. Estou desenvolvendo em Delphi 7
com dbExpress + Firebird 1.5. O travamento pessimista esta
ocorrendo normalmente com a sentenca SQL ´for update with lock´,
mas estou com o problema que qdo abro qualquer outra tabela
com SQLQuery + DataSetProvider + ClientDataSet a tabela que
estava com o travamento perde a trava e só recupera caso
execute o comando novamente ou dê um refresh.
O driver que estou utilizado é o do Interbase(dbExpint.dll),
sinceramente jah tentei de varias formas e é totalmente inviavel
ficar dando Refresh.
Espero que possam me ajudar e desde jah agradeco a atencao.
Algum tempo atras estive trocando umas ideias aqui no forum
sobre travamento pessimista. Estou desenvolvendo em Delphi 7
com dbExpress + Firebird 1.5. O travamento pessimista esta
ocorrendo normalmente com a sentenca SQL ´for update with lock´,
mas estou com o problema que qdo abro qualquer outra tabela
com SQLQuery + DataSetProvider + ClientDataSet a tabela que
estava com o travamento perde a trava e só recupera caso
execute o comando novamente ou dê um refresh.
O driver que estou utilizado é o do Interbase(dbExpint.dll),
sinceramente jah tentei de varias formas e é totalmente inviavel
ficar dando Refresh.
Espero que possam me ajudar e desde jah agradeco a atencao.
Andrevinni
Curtidas 0
Respostas
Afarias
07/10/2004
o seu ´problema´ (pelo q posso perceber) é q quando a transação é fechada (commit ou rollback) o ´lock´ é perdido
em geral quando usamos ClientDataSets, as transações são realmente muito curtas (instantâneas) -- reveja seu procedimento e controle das transações.
T+
em geral quando usamos ClientDataSets, as transações são realmente muito curtas (instantâneas) -- reveja seu procedimento e controle das transações.
T+
GOSTEI 0
Andrevinni
07/10/2004
Mas nao posso colocar controle de transacao nessa rotina, achei
que essa rotina de travamento era totalmente independente e
que so perderia a trava no close do SQLQuery.
Vou dar um exemplo:
Tenho uma tela de contas a receber e toda vez que o usuario
for alterar o registro, acontece o travamento. Porém, nessa
mesma tela, qdo estiver inserindo ou alterando vc tem a opcao
de cadastrar e/ou selecionar clientes, condicoes de pagamentos
e outros cadastros.
Caso venha abrir uma transacao no inicio de uma alteracao terei
as informacoes dos cadastros concluidas somente no Commit e
assim nao daria certo pq preciso dos cadastros antes de terminar
a alteracao.
que essa rotina de travamento era totalmente independente e
que so perderia a trava no close do SQLQuery.
Vou dar um exemplo:
Tenho uma tela de contas a receber e toda vez que o usuario
for alterar o registro, acontece o travamento. Porém, nessa
mesma tela, qdo estiver inserindo ou alterando vc tem a opcao
de cadastrar e/ou selecionar clientes, condicoes de pagamentos
e outros cadastros.
Caso venha abrir uma transacao no inicio de uma alteracao terei
as informacoes dos cadastros concluidas somente no Commit e
assim nao daria certo pq preciso dos cadastros antes de terminar
a alteracao.
GOSTEI 0
Afarias
07/10/2004
|Mas nao posso colocar controle de transacao nessa rotina, achei
|que essa rotina de travamento era totalmente independente e
|que so perderia a trava no close do SQLQuery.
Quando a transação é fechada a query tb é -- no mais, a manipulação de registros em um SGBD sempre está associada a uma transação.
|Caso venha abrir uma transacao no inicio de uma alteracao terei
|as informacoes dos cadastros concluidas somente no Commit e
|assim nao daria certo pq preciso dos cadastros antes de terminar
|a alteracao.
não entendi nada! vc pode ter mais q 1 transação -- pode explanar melhor seu problema??
T+
|que essa rotina de travamento era totalmente independente e
|que so perderia a trava no close do SQLQuery.
Quando a transação é fechada a query tb é -- no mais, a manipulação de registros em um SGBD sempre está associada a uma transação.
|Caso venha abrir uma transacao no inicio de uma alteracao terei
|as informacoes dos cadastros concluidas somente no Commit e
|assim nao daria certo pq preciso dos cadastros antes de terminar
|a alteracao.
não entendi nada! vc pode ter mais q 1 transação -- pode explanar melhor seu problema??
T+
GOSTEI 0
Andrevinni
07/10/2004
Primeiramente gostaria de agradecer a prestatividade, eu realmente
estou precisando concluir esta rotina.
Sobre as transacoes entendi o que deve ser feito para que o travamento
nao se perca na abertura dos clients, jah adaptei para haja mais
de uma transacao. So que ainda estou com problema nos testes que venho realizando. A transacao deveria ser aberta antes ou depois que sentenca de travamento?
1) Caso abra a transacao antes do travamento
Neste caso quando o primeiro usuario tenta tenta travar o registro
o sistema procede normalmente. Jah no segundo usuario (aplicativo)
o sistema fica totalmente parado esperado ate q o primeiro
destrave o resgistro. Jah veriquei a propriedade WAITONLOCKS do
sqlConnection e esta FALSE.
2) Caso abra a transacao depois do travamento
Neste caso tenho que utilizar um Client + Datasetprovider + sqlQuery
para alterar o registro e outra sqlQuery para executar a sentenca
do travamento e so depois abro a transacao. So que ocorre o erro de
Dead Lock ao aplicar os dados do Client pq o registro foi travado
depois.
estou precisando concluir esta rotina.
Sobre as transacoes entendi o que deve ser feito para que o travamento
nao se perca na abertura dos clients, jah adaptei para haja mais
de uma transacao. So que ainda estou com problema nos testes que venho realizando. A transacao deveria ser aberta antes ou depois que sentenca de travamento?
1) Caso abra a transacao antes do travamento
Neste caso quando o primeiro usuario tenta tenta travar o registro
o sistema procede normalmente. Jah no segundo usuario (aplicativo)
o sistema fica totalmente parado esperado ate q o primeiro
destrave o resgistro. Jah veriquei a propriedade WAITONLOCKS do
sqlConnection e esta FALSE.
2) Caso abra a transacao depois do travamento
Neste caso tenho que utilizar um Client + Datasetprovider + sqlQuery
para alterar o registro e outra sqlQuery para executar a sentenca
do travamento e so depois abro a transacao. So que ocorre o erro de
Dead Lock ao aplicar os dados do Client pq o registro foi travado
depois.
GOSTEI 0
Afarias
07/10/2004
|A transacao deveria ser aberta antes ou depois que sentenca de
|travamento?
a 1a. transação?? não há como executar nada no IB ou FB antes da abertura de uma transação :D
|Jah no segundo usuario (aplicativo) o sistema fica totalmente parado
|esperado ate q o primeiro destrave o resgistro.
Mude o parâmetro da transação de WAIT para NOWAIT, assim o usuário receberá uma exceção informando do travamento do registro
|Jah veriquei a propriedade WAITONLOCKS do
|sqlConnection e esta FALSE.
Como não tenho conhecimento de DBX não posso dizer se esta é a forma correta de proceder ou se há algum outro problema
|2) Caso abra a transacao depois do travamento
|Neste caso tenho que utilizar um Client + Datasetprovider + sqlQuery
|para alterar o registro e outra sqlQuery para executar a sentenca {...}
eu acho q vc deve avaliar bem o uso de ClientDataSets nesse seu processo. ClientDataSets são tabelas de memórias -- vc sempre vai estar trabalhando com registros totalmente independentes de transaçào -- a transação de ´recuperação´ destes registros pode ter sido fechada a séculos! as alterações entào (ApplyUpdates) podem estar sendo aplicadas (o q é a situação normal) em outra transação!
estude bem a situação q vc está e como funciona clientDataSets para ver se eles são uma boa opção e COMO aplicá-los de forma correta para esse seu caso.
uma das grandes funções de ClientDataSets é justamente manter extremanente curtas as transações e evitar ao máximo (ou totalmente) a possibilidade de registros bloqueados -- exatamente o oposto do q vc quer.
T+
|travamento?
a 1a. transação?? não há como executar nada no IB ou FB antes da abertura de uma transação :D
|Jah no segundo usuario (aplicativo) o sistema fica totalmente parado
|esperado ate q o primeiro destrave o resgistro.
Mude o parâmetro da transação de WAIT para NOWAIT, assim o usuário receberá uma exceção informando do travamento do registro
|Jah veriquei a propriedade WAITONLOCKS do
|sqlConnection e esta FALSE.
Como não tenho conhecimento de DBX não posso dizer se esta é a forma correta de proceder ou se há algum outro problema
|2) Caso abra a transacao depois do travamento
|Neste caso tenho que utilizar um Client + Datasetprovider + sqlQuery
|para alterar o registro e outra sqlQuery para executar a sentenca {...}
eu acho q vc deve avaliar bem o uso de ClientDataSets nesse seu processo. ClientDataSets são tabelas de memórias -- vc sempre vai estar trabalhando com registros totalmente independentes de transaçào -- a transação de ´recuperação´ destes registros pode ter sido fechada a séculos! as alterações entào (ApplyUpdates) podem estar sendo aplicadas (o q é a situação normal) em outra transação!
estude bem a situação q vc está e como funciona clientDataSets para ver se eles são uma boa opção e COMO aplicá-los de forma correta para esse seu caso.
uma das grandes funções de ClientDataSets é justamente manter extremanente curtas as transações e evitar ao máximo (ou totalmente) a possibilidade de registros bloqueados -- exatamente o oposto do q vc quer.
T+
GOSTEI 0