Pular para o conteúdo
  • Este tópico contém 3 respostas, 2 vozes e foi atualizado pela última vez 6 anos, 1 mês atrás por Avatar de José Laurindo ChiappaJosé Laurindo Chiappa.
Visualizando 4 posts - 1 até 4 (de 4 do total)
  • Autor
    Posts
  • #109236
    Avatar de MottaMotta
    Participante

      Lock que previna SELECT

      A situação é seguinte :

      Uma aplicação ERP (Totvs) com diversas tabelas
      Todas estas tabelas usam como chave primária
      um campo padrão
      R_E_C_N_O_

      A aplicação (creio) cria um novo registro
      com um
      select max(R_E_C_N_O_)+1

      Preciso porém que uma package plsql
      crie registros em algumas destas tabelas
      mas ao concorrer com o ERP ocorrem erros
      de ORA-00001: restric?o exclusiva

      Minha pergunta é :
      Existe alguma síntaxe em que seja possível
      “lockar” o max(R_E_C_N_O_) no caso
      de uma tabela específica.

      A ideia é ter um “wait” e não permitir
      que a aplicação ERP e a package tenham
      o mesmo R_E_C_N_O_ futuro.

      Lembro que não tenho como mudar o ERP
      Tudo deveria ficar na package PLSQL

      E claro minimizando a possibilidade
      de DEADLOCKs

      #109241
      Avatar de José Laurindo ChiappaJosé Laurindo Chiappa
      Moderador

        Bom, primeiro eu bateria na cara de quem programou um SELECT MAX pra encontrar o último valor de uma coluna, IGNORANDO que o RDBMS é MULTIUSUÁRIO POR DEFINIÇÃO : nada impede que um segundo depois que vc obteve o valor do MAX alguma outra sessão vá lá na tabela e INSIRA um registro a mais, tornando INÚTIL o resultado do teu SELECT MAX…. É o caso TÍPICO para o qual foram INVENTADAS as sequences , elas te ASSEGURAM 100% que o valor recebido é ÚNICO, independente do que outras sessões fizerem… A DESVANTAGEM das sequences é que elas não te garantem uma sequência numérica Rigorosamente Contínua : cada número ofertado pela SEQUENCE é único MAS caches, rollbacks e algumas situações do tipo PODEM te dar números não exatamente contínuos, podem haver GAPs… Num caso assim, o procedimento Correto seria o sistema ter uma tabela onde se guarda o último valor e cada sessão/transação inserindo registros bloqueia essa tabela, ou coisa assim…

        Muito bem, isso posto E estando entendido que estamos GAMBIARRANDO porque os zémanés do tal ERP não seguiram a Recomendação/best practices de programação no Oracle e não tem como vc usar sequences nem tabela de valor (simulando sequences), Te respondendo :

        – no RDBMS Oracle (e na Esmagadora MAIORIA dos RDBMSs) não há como lockar uma COLUNA apenas : vc locka um REGISTRO ou LOCKA A TABELA TODA, ponto….

        – especificamente no RDBMS Oracle, os locks a nível de tabela NUNCA impedem os SELECTs, e um SELECT ‘normal’ nunca locka nada… Isso é uma característica FUNDAMENTAL do Oracle, blocks não impedem LEITURAS e LEITURAS não CAUSAM blocks… Em outros RDBMSs, pra não ter leitura ‘suja’ (ie, não ler registros que estejam sendo alterados/inseridos) realmente o SGBD aplica LOCKs mas no caso do Oracle não é assim,…
        O que vc pode ter no Oracle que ‘impede’ um SELECT é um lock a nível de REGISTRO, aí isso impediria a leitura de registros que estivessem lockados SE o SELECT interessado em ler os registros lockados faça um SELECT nnn FROM tabela WHERE condiçãoderegistros FOR UPDATE…

        => NO seu caso, ao que entendo o ERP não usa sequences pra obter o valor-chave E na hora de buscar o próximo valor chave ele vai na tabela e faz um simples SELECT MAX(coluna) FROM tabela, sem lockar nada, né ? Nessas condições imho a sua alternativa única seria fazer um LOCK TABLE nessa tabela, pois aí vc tem CERTEZA que eunquanto esse lock não for liberado pela sua rotina NENHUMA OUTRA TRANSAÇÂO de outros usuários inseriu novos dados e portanto teu SELECT MAX ** realmente ** tá retratando a verdade…

        []s

        Chiappa

        #109242
        Avatar de MottaMotta
        Participante

          Chiappa , primeiro grato por entender a encrenca e não dar sugestões de alterar o ERP.

          Segundo grato por confirmar a minha suspeita que a única solução seria mesmo o LOCK TABLE.

          Valeu.

          #109243
          Avatar de José Laurindo ChiappaJosé Laurindo Chiappa
          Moderador

            Sim : fiz questão de EXPLICITAR que estamos gambiarrando justamente pelo fato do ERP ter feito caquinha E em tese ser inviável alterar o tal ERP : nem de longe esse tipo de coisa como lock de tabelas é recomendável – o que fizemos aqui foi tampar o nariz e gambiarrar, repito mas é que temos pra hoje, nessas condições…

            Só uma última obs : CONFIRME na Documentação e no Suporte Técnico do tal ERP que realmente, positivamente, não há outra maneira… Digo isso porque não é incomum vc ter uma tela de entrada de dados , uma Procedure ou algo assim no ERP que é o ponto ÚNICO de INSERT nas tabelas em questão : se isso existir, TALVEZ vc possa temporariamente substituir essa tela e/ou essa procedure por uma versão SUA customizada, que não permita INSERTs enquanto tua outra rotina está sendo executada, OU talvez temporariamente tirar o privilégio nessa tela/rotina enquanto a sua está rodando, digamos…. ERPs são famosos por ter coisas assim…

            Mas é por aí : não existindo um ponto passível de alteração/configuração, só te resta o caminho de lockar a tabela inteira, sim…

            []s

            Chiappa

          Visualizando 4 posts - 1 até 4 (de 4 do total)
          • Você deve fazer login para responder a este tópico.
          plugins premium WordPress