Jump to content
Fivewin Brasil

Monitorar status de um campo


emotta

Recommended Posts

Pessoal, a pergunta é para quem manja de SQL (mais especificamente SQL SERVER)

Tenho uma rotina que fica esperando que determinado campo seja setado como "1". 

O que estou fazendo hoje é um WHILE e dentro do while fico verificando If FILE->STATUS = "1"  e se a condição for .T. ele processa. O que acontece é que isso sobrecarrega o banco de dados, coloquei uma espera de 1s então a cada minuto ele manda para o banco de dados 60 transações verificando o campo.

Eu gostaria de resolver isso enviando um SELECT para o banco de dados e que esse SELECT somente me retornasse quando tivesse um registro com STATUS = '1'. Enquanto nenhum registro fosse setado como '1' ele ficaria na espera. 

Alguem tem uma solução para este caso?

 

PS: Aumentar o tempo no laço nao vai adiantar pois eu preciso que assim que um registro tiver o status setado como "1" ele precisa iniciar o processo.

 

Link to comment
Share on other sites

 

criando um outra tabela relacionada com a tabela atual com o mesmo campo  STATUS... quando essa tabela receber registro vc pegaria o status e fazia o processo (select) com o ID da tabela nova apagando o registro depois do processo... verificando sempre (TIME) se tabela nova tem registro para fazer o select novamente 

Acredito q vc não entendeu...

Fazer o esquema todo eu já fiz e funciona perfeitamente...

O que desejo melhorar agora é a quantidade de requisições q ele faz ao banco de dados.

Cada vez a eu verifico o campo é uma requisição ao banco. Se eu faço uma vez por segundo sao 60 requisições.

Eu poderia aumentar o tempo de checagem mas aí perco agilidade.

Eu gostaria de fazer o seguinte: enviar um select ao banco de dados e ele me retorna só qdo tiver algum dado ou qdo der um tempo de tineout. Se eu conseguir isso o meu programa só vai executar uma transação para o sql.

 

Enfim sua sugestão não funciona oq eu teria q ficar monitorando do mesmo jeito.

 

Mais uma coisa: a solução para o caso tem q ser no sql, não pode ser em dbf, arquivo de semáforo ou QQ outra coisa q não seja via sql. É bem difícil explicar aqui o motivo.

Link to comment
Share on other sites

Bom dia.

Tenho uma rotina parecida, em que o sistema fica monitorando o banco de dados para verificar se é necessário desconectar o usuario.

Criei um timer que é visivel na aplicação inteira. ( Minha janela principal é um objeto publico.. ) e em um determinado intervalo de tempo o select é executado.

Se não me engano é a cada 30 segundos que o select é executado, sendo que o retorno é sempre de 1 registro.

Espero ter ajudado, qualquer coisa estamos ao dispor.

Abraço.

Link to comment
Share on other sites

Eroni, estou fazendo exatamente isso, com um temporizador tb... só que no meu caso é de 1s em 1s pois quando cai o registro para processar esse processamento precisa responder rápido.

O que você sugeriu cai no mesmo problema, de 30s em 30s ele precisa fazer uma requisição ao SQL para monitorar se tem algo a processar. 

Em resumo: Não posso aumentar o tempo para 30s pois pode acontecer do registro cair e demorar 30s para que a aplicação perceba esse registro e o processe. 

Mas obrigado pela tentativa, vou testar o link acima que encontrei ontem vamos ver. Se eu conseguir posto aqui a solução.

Link to comment
Share on other sites

o problema não é o tempo que ele leva pra processar... o problema que desejo resolver é a checagem constante na tabela verificando se tem algo. A solução seria aumentar o tempo que hoje de de 1s em 1s para 60s em 60s (por exemplo) mas se aumentar esse timer pode cair um registro para ser processado e ter uma demora de 60s para o programa perceber. Isso inviabilizaria o processo pois a resposta deve ser rápida. Hoje o codigo é assim:
 

While .t.

   If SRV->SRV_STATUS = "1"

      Processa(SRV->SRV_CODIGO)

  Endif

  ThreadSleep(1000)

EndDo

 

o problema é que ele fica chegando de 1s em 1s o registro e quando o campo STATUS fica como 1 ele processa o registro. Enquanto fica "0" ele fica no laço.

Em resumo: Tenho que ter uma resposta rápida quando o STATUS for setado como 1 e não quero que o sistema fique requisitando ao banco de dados verificando se o STATUS ficou 1.

 

 

Link to comment
Share on other sites

Exatamente, estou estudando como funciona isso que não é uma stored procedure normal, é um recurso diferente...estou estudando isso

Caso nao consiga vou implementar uma stored procedure convencional. A checagem de 1s em 1s continurá mas pelo menos não terá transito na rede

Link to comment
Share on other sites

Motta, blz ?
Creio que o Schedule possa resolver o seu problema ;)

https://docs.microsoft.com/pt-br/sql/ssms/agent/create-a-schedule?view=sql-server-ver15

-- creates a schedule named RunOnce.   
-- The schedule runs one time, at 23:30 on the day that the schedule is created.  
USE msdb ;  
GO  

EXEC dbo.sp_add_schedule  
    @schedule_name = N'RunOnce',  
    @freq_type = 1,  
    @active_start_time = 233000 ;  

GO

Link to comment
Share on other sites

Perdoem a minha "Santa Ignorância"...

Porque não setar uma variável ao invés do dB ?

Eu faço isso usando Timer para avaliar o valor de uma variável pública a cada segundo.

Sempre que algum usuário acessa determinado Campo e o Valida, altero o valor desta variável para executar outra rotina.

Ao final desta rotina. retorno o valor anterior desta varável.

Não sei se é isso, porém no meu caso funfa certinho.

Abraços.

Link to comment
Share on other sites

 

O que não estou entendendo é quem/que seta o valor para "1". Se for teu próprio programa porque não faz o tal SELECT quando faz o update de tua tabela para "1"?

Pelo que entendi ele monitora um determinado status, poderia ser S/N, ETC...

TIPO QUE FAÇO PARA VER SE CHEGOU NOVOS PEDIDOS PELA AUTOMAÇAO DE FORÇA DE VENDAS

 

Link to comment
Share on other sites

 

Vagner pelo que entendi ele vai executar as 23:30h certo? 

Não resolvi pq se a tabela tiver o status setado como '1' só vai processar as 23:30h

Teria que ser um SELECT que só me retorna quando tem algum registro ou se passa o timeout

 

Motta, não conheço a fundo o SQL, mas se não me engano você pode colocar no start a hora que vai começar o funcionamento e depois existem outros parâmetros onde você pode ficar monitorando como no caso do timer, mas creio que isso vá fazer também dar um consumo no banco, porém de qualquer maneira ele teria que ficar olhando o banco para ver através de uma function que você poderia fazer dentro do próprio banco junto ao schedule, não conheço muito o trigger porém se você setar para esse campo será que não daria ? qualquer mudança rodaria uma function ou um select. É somente uma ideia :D

Link to comment
Share on other sites

Pessoal agradeço muito todas as sugestões e idéias, infelizmente nenhuma foi possivel colocar em prática, muito mais pq eu não consegui explicar exatamente minha necessidade já que é muito complicado explicar o que preciso escrevendo, é uma situação bem inusitada.

Vou tentar explicar de uma outra maneira e dps vou dizer o que eu fiz e resolveu:

- Imagine que temos um cadastro de cliente e a cada cliente novo cadastrado, pode ser por qualquer terminal, temos que enviar um email de boas vindas. Então quando algum terminal cadastrar este cliente temos um campo chamado BOASVINDAS = "N".

- No servidor eu tenho um programa xHarbour sendo executando em background que fica dando select na tabela de clientes e no where BOASVINDAS = "N". Sempre que esse SELECT retornar algum cliente eu pego cada cliente e envio um email de boas vindas.

- É preciso ser muito rápido, ou seja, assim que o cleinte é cadastrado em algum terminal o programa que está rodando no servidor tem que já mandar este email. Então o select que este programa faz no banco é de 1s em 1s pois sendo assim o tempo máximo para que o serviço envie o email ao novo cliente será de 1s.

- Fazendo este select de 1s em 1s eu envio 60 transações SQL ao banco por minuto. Considerando que por dia são poucos clientes cadastrados eu considero isso um desperdicio de processamento.

- Existem N possibilidades alternativas como por exemplo fazer o disparo do email por um JOB no SQL, fazer o envio do email no prórprio cadastro do cliente e N outras coisas que não vou explicar os motivos mas não poderei aplicar.

- Tem que ser desta forma ou seja, o programa rodando no servidor em background e que ele capture este novo cliente rapidamente, no máximo em 1s. Porem preciso que não se tenha este desperdicio de transações por minuto.

 

COMO EU RESOLVI:

- O meu programa em background executa uma STORED PROCEDURE e essa procedure retorna uma lista de codigos de clientes novos (BOAS VINDAS = "N") o meu programa envia o email pra cada novo cliente e seta nelas o BOAS VINDAS = "S"

- A stored procedure fica executando o select buscando clientes BOAS VINDAS = "N" quando tem algo ele retorna os dados para a aplicação e enquanto não tem ele fica em um while dentro da procedure.

- Fiz um contador para que quando der 1 minuto ele retorne vazio para a aplicação. Preciso fazer isso para que a aplicação não fica travada.

- Desta forma tenho apenas 1 requisição ao banco por minuto (STORED PROCEDURE).

 

** a situação acima foi apenas para explicar minha necessidade. O que estou precisando não é exatamente enviar email de boas vindas a novas clientes mas o exemplo acima ilucida exatamente o que preciso.

 

Exemplo da procedure:

CREATE OR ALTER PROCEDURE BuscaNovos
AS  
BEGIN
    SET NOCOUNT ON;  

	DECLARE @Contador INT
	SET @Contador = 1

	WHILE (SELECT COUNT(*) FROM TAB_CLI WHERE BOASVINDAS = 'N') = 0 and @Contador < 60
	BEGIN
	   WAITFOR DELAY '00:00:01';
	   SET @Contador = @Contador + 1 
	END
    
	SELECT * FROM TAB_CLI WHERE BOASVINDAS='N' 
END

 

Link to comment
Share on other sites

Alex, não resolve... Na explicação acima eu explico que o serviço para mandar o "boas vindas" está rodando no servidor e quem cadastra o cliente é uma estação qualquer. Se eu colocar na TRIGGER pra dar o boas vindas quem vai processar é o SQL e eu preciso que quem processe seja o serviço (xHarbour) que fica executando no servidor e esperando cair um cliente novo que ainda não teve o boas vindas enviado.

Trigger também foi meu primeiro pensamento mas que descartei logo de cara. Seria bem mais simples fazer por ele mas infelizmente não foi.

Mas obrigado pela ajuda, de certa forma as idéias sempre são aproveitadas !

 

vlwww

Link to comment
Share on other sites

 

Você se refere a isso Emotta?

 

 

Isso mesmo.... Mas o problema não era fazer, isso eu já tinha conseguido desde o inicio, a rotina já funcionava bem.

O problema era a quantidade de requisições ao banco de dados por minuto, eram muitas requisições feitas ao SQL desnecessariamente. Então em vez de fazer 1 select por segundo eu passei a executar uma stored procedure que só me retorna quando tive novidade ou quando der o tempo de 1 minuto informando que não teve novidade.

Mas a rotina do seu post é bem semelhante porem possivelmente ele faz um desperdício de processamento da mesma forma que eu estava fazendo (como não postou a forma que ele busca novos pedidos só da pra deduzir). O problema não era desenvolver a rotina e sim evitar esse desperdício.

 

vlwww ae

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...