Unofficial Content

Controle de Concorrência
 
Muitos problemas ocorrem durante o controle de concorrência. Para que você consiga entender o funcionamento e resolver este problema, é aconselhável a leitura de todo este documento.
O Controle de concorrência não é nada mais que controlar duas ou mais pessoas acessando a mesma informação ao mesmo tempo.
Para efetuar este controle são utilizados comandos e funções específicas de cada banco de dados e cada qual tem um funcionamento próprio.
Desta forma, o processo é executado no servidor de banco de dados e é um bloqueio real do registro. Uma vez bloqueado este registro não pode mais ser alterado ou visualizado por nenhum outro processo, seja GeneXus ou não.
Este funcionamento é próprio da base de dados e não existe como impedir. O que pode ser e é feito pelo GeneXus é a redução do tempo de duração do mesmo.
O bloqueio é notado quando na rede quando outros computadores simplesmente param de responder, emitindo mensagens ou não, ficando estático.
Esta parada não é uma parada proposital do GeneXus. Qualquer outra aplicação, GeneXus ou não e até mesmo uma simples consulta SQL ficará parada sem resposta.
Isto se deve ao fato de que durante o processo de gravação, o controle de concorrência bloqueia o registro. Este procedimento é claro, pois se alguém está alterando algo, é melhor esperar a pessoa acabar de gravar para que as informações recuperadas sejam as informações finais pós-atualização.
Este é o funcionamento do controle de concorrência utilizado pelo Banco de Dados, mas o GeneXus utiliza de formas diferentes para controlar as concorrências: Conversacional e Pseudo-Conversacional
Tipo de Bloqueio: Conversacional
Mensagem: Record in use by another - O registro esta sendo utilizado
Quando uma transação, por exemplo, entra em modo de atualização (Logo após sair do Atributo Chave na transação), existe o bloqueio da informação para que ninguém altere. Uma vez o registro bloqueado, ninguém mais pode alterar estas informações.
Este é o tipo de bloqueio Conversacional do GeneXus. Ao iniciar uma alteração, os dados são bloqueados e ninguém mais pode acessar.
Imagine então um usuário que entra em uma transação e inicia uma alteração e vai almoçar sem sair do modo de update. Todos os processos que dependem desta informação serão bloqueados, nenhuma mensagem será exibida e tudo ficará parado esperando que o usuário saia do modo de update.
Objetos do GeneXus: Todos, principalmente Transações.
Tempo de Vida do Bloqueio: Depois de sair do atributo chave em transação até a confirmação ou não dos dados.
Mensagem de erro ao acessar duas transações simultaneamente: Record in use by another - O registro esta sendo utilizado


 
Tipo de Bloqueio: Pseudo-Conversacional
Mensagem: <Tabela> was changed. - <Tabela> foi modificada.
Para evitar o problema da concorrência Conversacional, onde simplesmente pelo fato de entrar em modo Update o registro é bloqueado, permanecendo neste estado até a confirmação ou cancelamento do modo parando assim toda a aplicação, foi criado o tipo de concorrência pseudo-conversacional.
Neste controle não existe o bloqueio após a saída do(s) atributo(s) chave(s). O bloqueio é feito somente após a confirmação da gravação dos dados (antes da regra After(Confirm) ou On AfterValidate) e sua duração é muito curta, ficando bloqueado o registro somente durante o tempo de gravação efetiva.
Seguindo este raciocínio, fica claro que como o registro não está bloqueado, outra pessoa pode alterar as informações do registro ao mesmo tempo, pois este não se encontra bloqueado.
Para evitar que ocorra perda de dados, o GeneXus lê os dados no momento em que você entra em modo update na transação e compara estes com os dados que estão gravados na base de dados antes da gravação efetiva dos dados. Se estes estiverem alterados, uma mensagem será exibida: <Tabela> was changed. - <Tabela> foi modificada.
Objetos do GeneXus: Transações.
Tempo de Vida do Bloqueio: Somente durante a gravação dos dados.
Mensagem de erro ao acessar duas transações simultaneamente: <Tabela> was changed. - <Tabela> foi modificada.
Perguntas Freqüentes:
P: O problema não está ocorrendo em transações e sim em procedures. Tem alguma coisa a ver?
R: Entenda que isso não é válido somente para Transações, mas para qualquer outra operação. Um ?For Each?, por exemplo, em uma procedure ou uma consulta em uma WorkPanel. Estes objetos ficarão sem poder acessar os dados e parados enquanto aquela transação não sair do modo de update.
P: Minha procedure fica parada por vários minutos, chegando a horas.
R: Sim. O GeneXus gera códigos de forma a não emitir erros caso se encontre um registro bloqueado. Um ?For Each? pode ficar várias horas aguardando que um registro seja desbloqueado. Entenda que o problema não está na procedure e sim no objeto que está segurando o bloqueio. Este deve ser resolvido.
P: Coloquei meu controle de concorrência como Pseudo-Conversacional e mesmo assim está sendo exibida a mensagem ?Record in use by another - O registro esta sendo utilizado? e esta é para concorrência Conversacional e não Pseudo.
R: Esta transação tem 2 níveis. Ao confirmar uma alteração no primeiro nível, indo para o segundo nível, o primeiro nível é bloqueado como se fosse concorrência Conversacional, bloqueando o mesmo até a confirmação de toda a transação.


 
Caso nenhuma alteração seja feita no primeiro nível, não é feito nenhum bloqueio. Para resolver este problema, não permita a edição do primeiro nível em uma transação de dois níveis.
P: Coloquei o controle de concorrência como para Pseudo-Conversacional e mesmo assim o sistema está sendo bloqueado. Estou utilizando SQL Server 2000.
R: O SQL Server 2000 bloqueia os registros por página e isso é um problema. Uma página é uma coleção de registros e não um único registro. Para resolver o problema, você deve diminuir a compatibilidade para versão 7.0, tanto no SQL Server como no GeneXus, parar e reiniciar o SQL Server. Somente irá funcionar após reiniciar o SQL Server.
Em ambiente Web não é necessário diminuir a compatibilidade, pois dificilmente um processo conseguirá bloquear por mais de 1 minuto um registro. O bloqueio em páginas é muito mais rápido que o bloqueio de registros.
Porém, com o GeneXus 8.0 não é necessário mais diminuir a compatibilidade do banco de dados. A ARTech alterou os códigos gerados para que estes bloqueios por página não ocorram mais.
Para alterar a compatibilidade no SQL Server:
- Abra o Enterprise Manager
- Abra Console Root / Microsoft SQL Servers / <Servidor SQL onde está o Banco> / Databases / <Banco de Dados>
- Clique com o direito sobre o Banco de Dados
- Aba Options / Compatibility Level
- Coloque como 70.
Nota: É necessário PARAR o serviço do SQL Server ao menos, sem dar boot.
P: Estou utilizando Access. Como devo proceder?
R: O Access só faz bloqueios por página e não existe como alterar.
P: Mesmo sem ninguém acessando o sistema eu recebo a mensagem ?<Tabela> was changed. - <Tabela> foi modificada.?.
R: Provavelmente você está rodando uma procedure dentro de uma regra ou evento sobre uma das tabelas da transação para atualizar os dados. Ao gravar os dados, o GeneXus nota que a procedure alterou os dados e emite a mensagem. Tente, em vez de gravar na base de dados, receber os dados via parâmetro e deixar que a transação os grave. Neste caso a Procedure deve ter como Parm variáveis InOut ou somente Out e o call na transação para a procedure ter atributos. Os valores retornados ficarão armazenados dentro dos atributos.
P: Minha transação para de funcionar e fica aguardando algo acontecer e não sei o que é.
R: Provavelmente seu bloqueio é Conversacional e você está chamando uma procedure que grava ou lê os dados da mesma. Como o registro está bloqueado, sua procedure fica aguardando a liberação. Você precisa alterar o funcionamento para que sua procedure seja executada em outro momento.
P: Qual a diferença entre uma transação e uma procedure no que diz respeito ao bloqueio?
R: Comandos ?For Each? não possuem concorrências distintas. Eles são sempre Conversacionais. Um ?For Each? em toda a tabela será encarado como leitura e não haverá bloqueio algum. Um ?For Each? com pelo menos a gravação de 1 atributo, o ?For Each? irá


 
bloquear os dados, pois entende que irá ser feita a gravação. Este bloqueio será feito em todos os registros que forem iguais a ?Start From? e ?Loop While? na especificação, sendo desconsiderado os filtros ?Constrains?. Se não existir ?Start From? e ?Loop While?, o bloqueio será em toda a tabela durante todo o tempo de execução do ?For Each?.
Para resolver este problema, separe e crie um ?For Each? dentro de uma Sub somente para gravar os dados.
P: As vezes o sistema todo para de funcionar, ficando travado.
R: Entendendo todos os conceitos acima, você vai ter de descobrir quem está bloqueando o seu sistema. Você pode encontrar isso dentro do seu Servidor de Base de Dados, como SQL Server, Oracle, etc. Outra forma de descobrir é gerando um Log com o Utilitário ?GeneXus DB Activity Trace?, que se encontra em ?Iniciar / Programas / GeneXus x.x/ GeneXus Utilities?.
Descobrindo quem está bloqueando o seu sistema, você precisa alterar a forma de trabalho para resolver a mesma.
P: Como funciona o controle de concorrência em ambientes Web?
R: Somente como Pseudo-Conversacional. Os dados são validados em transações durante a gravação dos mesmos e não existe o problema de dois níveis em uma transação, porém, uma procedure muito demorada pode parar todo o sistema.
Em ambiente Web, a vida dos objetos é muito curta e os bloqueios também. Dificilmente os dados são bloqueados.
P: Transaction (Process ID 999) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.
R: O Deadlock é um pouco complexo. Existem casos onde o bloqueio é feito sobre duas tabelas ao mesmo tempo e nenhum dos dois casos podem ser resolvidos.
Imagine a seguinte seqüência:
Processo 1 - Bloquear Tabela A
Processo 2 - Bloquear Tabela B
Processo 1 - Bloquear Tabela B
- Neste ponto o processo 1 fica aguardando o término do processo 2, pois o mesmo já está bloqueando a tabela.
Processo 2 - Bloquear Tabela A
- É gerado um Deadlock, pois não tem mais como resolver os bloqueios e o sistema ficaria parado eternamente.
O Deadlock é gerado pelo SQL Server e NÃO pelo GeneXus. Não existem maneiras de evitar este erro. Ele vai ocorrer sempre que houver casos de bloqueios cíclicos. O que você deve fazer é entender e resolver todas as chamadas, de forma que não sejam mais bloqueados os dados.
O processo que sofre o Deadlock é eleito pelo SQL Server com base nas informações alteradas no banco de dados. Aquele que tiver gravado menos informações no banco de dados será o eleito.
Existem casos bem mais complexos que o exemplificado e que podem envolver uma quantidade grande de processos e alguns ou todos sofrerão Deadlock ao mesmo tempo.


 
Este documento não tem por objetivo resolver seu problema e sim ajudar você a entender. A solução é sua, pois cada problema tem uma solução específica e que se adequará as suas necessidades de negócio.
 
Artech do Brasil
Last update: February 2024 | © GeneXus. All rights reserved. GeneXus Powered by Globant