Ir para conteúdo
Fórum Script Brasil
  • 0

Commit x IBX


DiabloX3

Pergunta

Nada com "commit" encontrado no pesquisar.

Problema é o seguinte agora moçada.

Trabalho com Firebird 1.5 com IBX e Delphi7. Utilizo componentes da palheta IBX e estou com problemas na hora de gravar os dados.

Aconteceu que temos um sistema num notebook. Lá tem o botão gravar, cancelar, sair etc ... Quando clico no gravar ele tem a rotina para fazer o commit no banco e mostrar mensagem de sucesso. Porém depois de vários pedidos feitos e gravados, o cliente desligou o note com a tela do sistema aberta e para minha supresa nada foi realmente gravado. Em um outro teste fiz a mesma coisa e fechei o sistema, aí sim os dados forem efetivamente gravados. Qual o problema entre fechar o sistema ou não? Eu acreditava que o Commit era essencial para a gravação dos dados mas não foi isso que observei.

Realizando o teste na mão, observei que enquanto gravo uma venda, sem fechar o sistema, vou no IBX e abro a tabela de Vendas e o pedido não está lá.

O que acontece nesse caso? Como resolver?

Abaixo o codigo do gravar

procedure TfrmPedido.btnGravarClick(Sender: TObject);

begin

  if (edtCodCliente.Text <> '') and (cmbPrazoPgto.Text <> '') and (rdgCondPgto.ItemIndex <> -1) and (rdgTipoEnt.ItemIndex <> -1) then
  begin
   IBTransMobili.StartTransaction;
   qryAltPedido.ParamByName('P_COD').AsInteger := StrToInt(lblCodVenda.Caption);
   qryAltPedido.ParamByName('P_TOTAL').AsFloat := qryTotal.FieldByName('TOTAL').AsFloat;
   qryAltPedido.ParamByName('P_CLI_COD').AsInteger := StrToInt(edtCodCliente.Text);
   qryAltPedido.ParamByName('P_OBS').AsString := memObs.Text;
   qryAltPedido.ParamByName('P_PAR_CP_CODIGO').AsInteger := cmbPrazoPgto.KeyValue;
   qryAltPedido.ParamByName('P_TOTAL').AsFloat := qryTotal.FieldByName('TOTAL').AsFloat;

   qryAltBackupPed.ParamByName('P_COD').AsInteger := StrToInt(lblCodVenda.Caption);
   qryAltBackupPed.ParamByName('P_TOTAL').AsFloat := qryTotal.FieldByName('TOTAL').AsFloat;
   qryAltBackupPed.ParamByName('P_CLI_COD').AsInteger := StrToInt(edtCodCliente.Text);
   qryAltBackupPed.ParamByName('P_OBS').AsString := memObs.Text;
   qryAltBackupPed.ParamByName('P_PAR_CP_CODIGO').AsInteger := cmbPrazoPgto.KeyValue;
   qryAltBackupPed.ParamByName('P_TOTAL').AsFloat := qryTotal.FieldByName('TOTAL').AsFloat;

   if rdgSit.ItemIndex = 0 then
   begin
    qryAltPedido.ParamByName('P_SIT').AsString := 'V';
    qryAltBackupPed.ParamByName('P_SIT').AsString := 'V';
   end
   else if rdgSit.ItemIndex = 1 then
   begin
    qryAltPedido.ParamByName('P_SIT').AsString := 'T';
    qryAltBackupPed.ParamByName('P_SIT').AsString := 'T';
   end
   else if rdgSit.ItemIndex = 2 then
   begin
    qryAltPedido.ParamByName('P_SIT').AsString := 'B';
    qryAltBackupPed.ParamByName('P_SIT').AsString := 'B';
   end;

   if rdgTipoEnt.ItemIndex = 0 then
   begin
    qryAltPedido.ParamByName('P_TIPO').AsString := 'URGENTE';
    qryAltBackupPed.ParamByName('P_TIPO').AsString := 'URGENTE';
   end
   else if rdgTipoEnt.ItemIndex = 1 then
   begin
    qryAltPedido.ParamByName('P_TIPO').AsString := 'NORMAL';
    qryAltBackupPed.ParamByName('P_TIPO').AsString := 'NORMAL';
   end
   else if rdgTipoEnt.ItemIndex = 2 then
   begin
    qryAltPedido.ParamByName('P_TIPO').AsString := 'PROGRAMADA';
    qryAltBackupPed.ParamByName('P_TIPO').AsString := 'PROGRAMADA';
   end
   else if rdgTipoEnt.ItemIndex = 3 then
   begin
    qryAltPedido.ParamByName('P_TIPO').AsString := 'TROCA/BONIF';
    qryAltBackupPed.ParamByName('P_TIPO').AsString := 'TROCA/BONIF';
   end;

   if rdgCondPgto.ItemIndex = 0 then
   begin
    qryAltPedido.ParamByName('P_CONDICOES').AsString := 'DINHEIRO';
    qryAltBackupPed.ParamByName('P_CONDICOES').AsString := 'DINHEIRO';
   end
   else if rdgCondPgto.ItemIndex = 1 then
   begin
    qryAltPedido.ParamByName('P_CONDICOES').AsString := 'CHEQUE';
    qryAltBackupPed.ParamByName('P_CONDICOES').AsString := 'CHEQUE';
   end
   else if rdgCondPgto.ItemIndex = 2 then
   begin
    qryAltPedido.ParamByName('P_CONDICOES').AsString := 'BOLETO';
    qryAltBackupPed.ParamByName('P_CONDICOES').AsString := 'BOLETO';
   end
   else if rdgCondPgto.ItemIndex = 3 then
   begin
    qryAltPedido.ParamByName('P_CONDICOES').AsString := 'OUTRO';
    qryAltBackupPed.ParamByName('P_CONDICOES').AsString := 'OUTRO';
   end
   else if rdgCondPgto.ItemIndex = 4 then
   begin
    qryAltPedido.ParamByName('P_CONDICOES').AsString := 'TROCA/BONIF';
    qryAltBackupPed.ParamByName('P_CONDICOES').AsString := 'TROCA/BONIF';
   end;

   qryAltPedido.ExecSQL;
   qryAltBackupPed.ExecSQL;
   IBTransMobili.Commit;

   Limpar(Sender as TObject);
   qryPrazoPgto.Close;
   mensagem := 'Pedido Gravado com Sucesso!';
   Application.MessageBox(Pchar(mensagem), 'Informação', MB_OK+MB_ICONINFORMATION);
   pn_geral.Enabled := False;
   btnNovo.SetFocus;

*Aqui eu gravo em duas tabelas ao mesmo tempo por causa de uma outra rotina no sistema que exige isso.

Link para o comentário
Compartilhar em outros sites

15 respostass a esta questão

Posts Recomendados

  • 0

acho que já descobri pessoal. Só me confirmemse estou certo/se era isso mesmo. Eu tenho 1 IBTransction pra cada form e muitas Querys em cada form. Acontecia que essas querys não estavam ligadas a esse Transction desse form e sim a um outro Transction "Principal" vamos dizer assim (porque antes a gente usava 1 Transaction só para todos os form, mas isso não da muito certo).

Pelo menos eu iniciei uma venda, fui no banco e atualizei e ela já estava la começada. Quando finalizei, ainda com o sistema aberto atualizei o banco e lá estavam todos os dados daquela venda :)

Link para o comentário
Compartilhar em outros sites

  • 0

Vou mudar minha pergunta agora mas com o mesmo assunto.

Tenho uma aplicação Cliente/Servidor a qual utilizava apenas um IBTransaction para comitar todo o sistema. Porém isso não é viável para trabalhar com múltiplas janelas.

Por exemplo: Estou com um formulário de nota fiscal aberto com itens lançados na nota. Se precisar incluir um novo produto eu minimizo a tela de nota, abro o cadastro de produto e faço a inclusão. Porém desse jeito eu perco os itens lançados na nota pois na gravação o commit fecha tudo.

Qual a melhor saída para esse tipo de problema com esse tipo de aplicação Cliente/Servidor?

Abraços

Link para o comentário
Compartilhar em outros sites

  • 0
Por exemplo: Estou com um formulário de nota fiscal aberto com itens lançados na nota. Se precisar incluir um novo produto eu minimizo a tela de nota, abro o cadastro de produto e faço a inclusão. Porém desse jeito eu perco os itens lançados na nota pois na gravação o commit fecha tudo.

Qual a melhor saída para esse tipo de problema com esse tipo de aplicação Cliente/Servidor?

Trabalhe com o componente PageControl da paleta Win32 ... o formulário da nota fica em uma aba e o de produtos em outra .. e os dois ficam em um unico form. O commit deverá ser dado em um botão OK somente quando finalizar a operação.

abraço

Link para o comentário
Compartilhar em outros sites

  • 0

Não é possível assim Jhonas. A tela de produtos é o cadastro de produtos. Eu estou vendendo e quero incluir um item. Minimizo a tela de vendas, abro o cadastro (outro form), insiro, gravo, fecho. Volto a nota e pesquiso o produto e ele precisa estar lá sem que tenha sumido todos os itens que eu estava vendendo.

Eu tenho nota entrada, nota saida e outros forms de inserção de itens. Não é viavel criar um pagecontrol para cada um deles e ter os produtos lá. Tem q puxar tudo do Form de cadastro sem inteferência de um no outro.

abraço

Link para o comentário
Compartilhar em outros sites

  • 0
Não é viavel criar um pagecontrol para cada um deles e ter os produtos lá. Tem q puxar tudo do Form de cadastro sem inteferência de um no outro.

Não fale... Não é viavel ... eu já fiz dessa maneira e funciona muito bem ... é tudo uma questão de mudar a lógica de funcionamento

Pode ficar tranquilo que não ocorrerá interferencia deles. Se puder perder um tempo voce vai descobrir que dá pra fazer.

abraço

Link para o comentário
Compartilhar em outros sites

  • 0

Deixa eu ver se eu entendi. No sistema eu tenho um menu com cadastros. São 12 ao todo incluindo clientes, produtos, fornecedores, etc...

Em cada formulário que eu possa precisar de informações desses cadastros, como nota fiscal (nosso exemplo) eu preciso ter 12 TabSheet? Já que não sei qual cadastro ele pode querer modificar e inserir na nota.

Link para o comentário
Compartilhar em outros sites

  • 0
Deixa eu ver se eu entendi. No sistema eu tenho um menu com cadastros. São 12 ao todo incluindo clientes, produtos, fornecedores, etc...

Em cada formulário que eu possa precisar de informações desses cadastros, como nota fiscal (nosso exemplo) eu preciso ter 12 TabSheet? Já que não sei qual cadastro ele pode querer modificar e inserir na nota.

Exatamente ... e voce verá que fica mais facil fazer o controle ( a lógica fica um pouco diferente mas muito pratico )

abraço

Link para o comentário
Compartilhar em outros sites

  • 0

Eu tenho uma outra solução Jhonas.

Criei um IBTransaction para cada form. Nesse componente serão ligadas as querys de update (insert, delete, update) desse form e as de select estão ligados a um outro transaction.

Como as de select são de pesquisa eu descobri a opção Read_Commited no IBTransaction.

Agora eu pergunto: Estou trabalhando com 1 Trans para pesquisa com Read_commited e vários Trans para updates, 1 em cada form. Tem gente que diz para retirar a opção nowait da propriedade, outros para deixar. Eu já li sobre isolamentos no firebasebr mas não entendi muito bem se devo deixar ou não. Quero saber isso e tambem se apenas no meu transaction de leitura (select) preciso ter essa opção read_commited ativada

abraços

Link para o comentário
Compartilhar em outros sites

  • 0

Se pudesse me postar algumas imagens do seu sistema pra ver como fica seria bom. Me parece muito estranho a princípio. Queria ver alguns exemplos.. se não der, paciência.

Eu não tenho como postar uma imagem aqui .... me de o seu email que te envio

em um de meus sistemas estou usando 18 TabSheets sem problemas e sem confusão ... e todos fazem parte da mesma Ordem de Serviços

Tem gente que diz para retirar a opção nowait da propriedade, outros para deixar. Eu já li sobre isolamentos no firebasebr mas não entendi muito bem se devo deixar ou não. Quero saber isso e tambem se apenas no meu transaction de leitura (select) preciso ter essa opção read_commited ativada

Eu costumo usar assim:

read_committed

rec_version

sobre a opção nowait veja:

O algoritmo para uma transação sem espera (NoWait) seria (usando um pseudo-código

Pascal):

Repeat

StartTransaction

Try

Update;

Resposta := idOK;

Except

Resposta := MessageBox(‘Repete?’ ….);

End;

Commit;

Until (Answer=idOK) Or (Answer=idNo);

/*Ok ou o usuário fará isso depois */

ou simplesmente use o modo de espera (wait). Neste caso, nós perderíamos a opção de

terminar a atualização e fazer outra coisa enquanto tentamos de novo.

Raramente ocorrem conflitos. Mesmo quando múltiplos usuários estão trabalhando com os

mesmos itens, conflitos poderiam ocorrer apenas no caso de um usuário ter feito mudanças

durante o intervalo de tempo entre o StartTransaction-Update, sem ter dado Commit. Mesmo

que isso tenha acontecido, nós apenas tentamos mais uma vez (em caso de NoWait) ou

aguardamos (Wait).

Os autores deste artigo tentam evitar o modo de espera porque requer muita atenção no

projeto de acesso aos dados onde múltiplos comandos de atualização vão ser executados

dentro da transação. Em sistemas complexos, a possibilidade de “deadlocks” é maior (as

mensagens de erro do IB/FB se referem a qualquer conflito de travamento como “deadlock”,

mesmo quando o conflito não é um deadlock propriamente dito).

2. Usuários estão competindo por algum recurso. Por exemplo, um vendedor pode reservar

alguns produtos para algum cliente para garantir disponibilidade. O registro é feito na tabela

de estoque antes dos produtos terem sido tirados do estoque físico. A solução é similar à

anterior, exceto que neste caso adiciona-se um trigger do tipo Before Update. Ele verifica se o

estoque disponível não está negativo e ajusta os dados no cliente. Se os produtos não

estiverem mais disponíveis, não há razão para proceder com a reserva.

3. A mudança requerida não pode ser feita incrementando ou decrementando uma quantidade

(por exemplo: quando os nomes de produtos são mudados), mas a probabilidade de conflito é

baixa. A lógica da aplicação irá provavelmente permitir ao usuário redigitar novos nomes sem

muita dificuldade. Para este caso, o nível de isolamento snapshot é o que atende melhor.

O usuário navega nos datasets, escolhe um registro para alterar e então o snapshot inicia;

o registro é relido (os dados na tela podem estar desatualizados em relação ao banco);

o registro é modificado com um controle visual e ocorre uma tentativa de gravação;

Neste caso, o conflito irá sempre ocorrer no modo nowait quando ocorrerem duas tentativas

simultâneas de alterar o mesmo registro, independentemente do fato de alguém ter dado

commit ou não. Se ocorrer conflito, uma das transações tem que ser desfeita (rollback). Se a

gravação envolve vários comandos SQL, você precisa desfazê-la, se for apenas um comando,

pode executar um commit, já que não houve nenhuma mudança dentro do banco de dados.

É por isso que neste caso nós recomendados executar commit, porque o rollback aumenta o

intervalo entre o OIT (oldest interesting transaction – transação significativa mais antiga) e o

OAT (oldest active transaction – transação ativa mais antiga) e o loop se repete.

Nestes casos, com o IBX e o FIBPlus, o conteúdo dos controles db-aware é perdido depois de

um commit/rollback, de forma que é desejável implementar algum tipo de cache de entrada na

aplicação cliente para preservar as mudanças dos dados do usuário em caso de haver algum

conflito.

Uma solução simples é usar componentes não db-aware para a entrada de dados do

usuário e então lançar os valores dentro de componentes db-aware. Em modo de espera

(Wait), o servidor vai aguardar a resolução da transação conflitante. Se for um rollback,

nossas alterações serão lançadas, se for um commit, iremos obter uma exceção de conflito de

travamento e resolvê-la da mesma forma que se estivéssemos em NoWait.

Os casos a seguir são exemplos de quando é necessário engolir a bola de sinuca (veja o

epigrama). Todas as abordagens descritas abaixo apresentam a desvantagem de permitir que

algum usuário irresponsável impossibilite seus colegas de trabalhar por um longo período.

Eis o motivo pelo qual nosso primeiro recurso deverá ser tentar formular a tarefa para funcionar

com as técnicas descritas acima, com algumas medidas adicionais para controlar o

comportamento do usuário, quando necessário.

abraço

Link para o comentário
Compartilhar em outros sites

  • 0

Jhonas, vim procurar alguns topicos meus e este por exemplo, pode por como resolvido, estou usando o read_commited ai sem problemas e esta tudo certo

vi o email também, achei bem interessante e diferente ehehe

obrigado pelas soluções mais uma vez

*edit*

Unica dúvida que fiquei foi no caso de usar sem nada (igual voce) ou usar wait porque em ambos os casos dá certo aqui no projeto. se usar nowait ele da deadlock

voce optou por não usar nada por que?

eu li em alguns artigos a parte que eles usam alguma coisa normalmente ( ou wait ou no_wait) mas não falava nada sobre não usar nenhum dos dois.

abraço

Editado por DiabloX3
Link para o comentário
Compartilhar em outros sites

  • 0
voce optou por não usar nada por que?

Não usei o comando porque alterando as propriedades do TraceFlags do IBDatabase consigo um desempenho melhor

Na propriedade TraceFlags do IBDatabase mude as opções:

tfQPrepare = true

tfQExecute = true

tfQConnect = true

tfQTransact = true

tfQService = true

abraço

Link para o comentário
Compartilhar em outros sites

  • 0
huum, mas monitorar os eventos pelo SQLMonitor o que tem em comum com os isolamentos?

digo assim, para questao dos updates e possíveis conflitos ..

Leia este material... e se ainda estiver om dúvidas poste novamente .. ok ?

Veja a figura 7

http://www.activedelphi.com.br/print.php?sid=170

http://www.activedelphi.com.br/print.php?sid=314

Leia capitulo 5.3

http://www.copagril.com.br/jair/db.doc

abraço

Link para o comentário
Compartilhar em outros sites

  • 0
TIBSQLMonitor

Permite criar um log de todas as operações e instruções SQL que foram enviadas ao servidor. Como o aplicativo SQL Monitor não pode monitorar as intruções SQL enviadas pelos componentes Interbase(pois trabalha no nível da camada BDE), o desenvolvedor precisa usar este componente para monitorar e otimizar a aplicação cliente.

eu entendo que essas linhas parecem estar falando sobre coisas diferentes. Primeiro ele fala que o SQLMonitor monitora instruções definidas no TraceFlags do IBDataBase e depois fala que o SQLMonitor (deve ser de outra palheta) não tem acesso nativo ao Interbase então usa-se o IBSQLMonitor para otimizar. Mas o que seria esse otimizar se no começo ele fala que serve pra nós vermos só o que aconteceu quando demos um insert numa tabela?
//Obs: Atenção para atribuir o nivel de isolamento de Sua transação de dois clique em cima do IBTransaction1 e selecione de preferência o ReadCommited. //Achei importante frisar isto, pois não achei documentado em lugar nenhum.
aqui ele não comenta também sobre apagar a 3ª linha do Read_Commited e deixar sem nada, ao contrario, fala pra usar nowait.
Agora inclua na propriedade params do componente TRteste:

read_committed

rec_version

nowait

(Ou clique duplo em Trteste e escolha Read Committed. Pressione F1 para maiores

detalhes).

Repita o teste e observe que as alterações “comitadas” agora podem ser lidas devido ao parâmetro read_committed.

Quando rec_version é utilizado o conteúdo gravado pode ser lido, mesmo que existam outras transações pendentes.

Se fosse utilizado no_rec_version a transação esperaria até as outras transações pendentes efetuarem um commit ou rollback

na apostila também é freezado as duas primeiras linhas apenas - modo de leitura e o rec_version apenas. Ainda não consegui fazer uma associação de tudo isso. Não percebi o meu ganho em usar traceflags, ibsqlmonitor e qual modo de espera seria o mais correto (na vdd o por que de não ter nenhum, só read_commited e rec_version).

abraço

Link para o comentário
Compartilhar em outros sites

Participe da discussão

Você pode postar agora e se registrar depois. Se você já tem uma conta, acesse agora para postar com sua conta.

Visitante
Responder esta pergunta...

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emoticons são permitidos.

×   Seu link foi incorporado automaticamente.   Exibir como um link em vez disso

×   Seu conteúdo anterior foi restaurado.   Limpar Editor

×   Você não pode colar imagens diretamente. Carregar ou inserir imagens do URL.



  • Estatísticas dos Fóruns

    • Tópicos
      152,2k
    • Posts
      651,9k
×
×
  • Criar Novo...