Pular para o conteúdo
Visualizando 11 posts - 1 até 11 (de 11 do total)
  • Autor
    Posts
  • #96123
    luan
    Participante

      Bom dia galera, como sou meio novo no mundo o Oracle/plsql cheguei pela primeira vez no problema de concorrência.

      Vi que o oracle dispõe de alguns recursos para isso, como o SELECT FOR UPDATE.
      No meu caso precisaria tratar a concorrência pois estou criando um sistema de agendamento, e existe a possibilidade de duas pessoas clicarem no mesmo horário disponível ao mesmo tempo.
      Para esse caso qual seria a melhor opção, seria usar o select for update?

      Muito obrigado

      Abs []s

      #96126
      VitorLeandro
      Participante

        Fala Luan,

        O Select for update efetua um lock de linha (Row-x) nas linhas selecionadas. O interessante é saber se é isto mesmo que você quer.. Será que enquanto a tela de agendamente estiver aberta, nunguem mais poderá agendar no período selecionado? Se o sistema crescer muito, acredito que você possa ter problemas com Blocking Locks e DeadLocks, causando algumas lentidoes desnecessárias.

        Eu utilizaria um cursor sem efetuar o lock ou [NOWAIT], será bem mais performático a nível de concorrencia.

        #96130
        jspaulonci
        Participante

          Luan , se eu fosse você eu não faria nada, o Oracle bloqueia automaticamente a linha, ou seja, no caso de duas pessoas tentarem fazer a mesma operação ao mesmo tempo, um terá que esperar, fazer o que….isso é normal. O que vc tem que pensar é, escrever a aplicação para que libere logo o bloqueio.

          #96131
          Peterson
          Participante

            Como o João disse, o Oracle trata muito bem a concorrência, não é preciso você implementar tratamento para esta na sua aplicação. Caso 2 pessoas tentem alterar o mesmo registro ao mesmo tempo, o Oracle faz com que a primeira lock a linha e só a libere depois do commit. Enquanto isso a segunda pessoa acessa os dados anteriores a alteração da primeira pessoa através da tablespace undo.

            #96132
            vieri
            Participante

              No seu sistema de agendamento se você usar o select for update,
              o segundo usuário usando o mesmo horário, irá tomar uma excessão
              ORA-xpto – Resource busy , e vc terá que tratar isso na aplicação,
              se deixar o oracle trabalhar sosinho a sessão ficará em wait até a mesma terminar.

              Mas eu acho que vc tem problemas de concepção na modelagem.

              Se um usuário agenda uma consulta 10:30 e outro agenda
              10:30, elas deveriam ser linhas distintas.
              Provavelmete vc tem um tabelão, com todos os horários possiveis e faz update na linha inserindo apenas os nomes dos clientes nesses horários.

              O ideal seria uma tab de clientes, outra de agendamentos, e outra de horários disponives.

              concorda?

              #96133
              fsitja
              Participante

                Você está modelando as tabelas ainda? Qual seu modelo atual?

                Imagine a seguinte situação:

                João e Maria estão tentando agendar um horário cada um.

                João seleciona o horário que ele deseja, preenche algum formulário adicional com mais informações mas desiste de agendar antes de confirmar o agendamento.

                Enquanto isso, Maria seleciona seu horário enquanto João preenche o formulário adicional.
                Pergunto: em que momento é feito o “lock” na agenda?
                – Maria deveria enxergar que não há horários disponíveis?
                – Maria deveria poder prosseguir com o preenchimento do seu formulário, em caso de João (e quaisquer outros usuários) desistir do agendamento? Como efeito colateral, se os dois decidirem confirmar, um verá uma mensagem de erro na confirmação dizendo que o horário foi “tomado” por alguém que preencheu mais rápido…

                Tudo vai depender da sua implementação e do seu modelo de dados. Penso que é sim necessário abordar o problema de concorrência. O Oracle não resolve os problemas que apontei acima sozinho, e muitos outros.

                O select for update (com ou sem nowait) vai servir para controlar o comportamento da procedure que faz o agendamento e da consulta que exibe os horários disponíveis.

                #96134
                luan
                Participante

                  Obrigado pelas respostas galera, meu modelo atuel eh seguinte:

                  • Tabela CLIENTES
                  • Tabela AGENDA_DADO ( possui as datas disponíveis bem como status,etc)
                  • Tabela AGENDA_DETAIL ( possui id_agenda_dado, e os horários disponíveis bem como id_cliente e flag que pode ser ‘DISPONIVEL’ ou ‘OCUPADO )

                  Na minha Interface do usuário eu exibo um calendário que mostra os dias disponíveis, após o usuário escolher o dia, é exibido um DataGrid com todos os horários para o dia que foi escolhido, exibe apenas os horários que estão com a flag ‘DISPONIVEL’. Minha ideia era clicar duas vezes na linha do grid eu daria um update na tabela AGENDA_DETAIL seto o id do cliente e também mudo a flag para ‘OCUPADO’.

                  Minha ideia era no momento que for clicado duas vezes no horário disponível eu dar um lock na linha por um determinado tempo, pois se alguma outra pessoa clicar também iria lançar uma exception que seria tratada avisando o usuário que o horário não está mais disponível.

                  Eu só não sei se conseguiria usar o SELECT FOR UPDATE para este caso, seria o caso?
                  Minha modelagem está ruim?
                  Na verdade já está td pronto, inclusive as telas e estão funcionando, faltou agora só adicionar a função do clique duplo no horário disponível para realmente marcar a consulta.

                  Abs []s

                  #96139
                  burga
                  Participante

                    Eu só não sei se conseguiria usar o SELECT FOR UPDATE para este caso, seria o caso?

                    É possível usar o select for update neste caso, mas não é necessário.

                    Só o fato de você fazer o update da flag de ‘DISPONIVEL’ para ‘OCUPADO’ já resolve teu problema.

                    Quando você vai agendar um horário, você pode usar a condição flag = ‘DISPONIVEL’ no comando de atualização do registro. Exemplo:

                    update AGENDA_DETAIL set flag = ‘OCUPADO’, id_cliente = quem_esta_agendando where id_da_dua_tabela = id_do_registro_a_ser_alterado AND flag = ‘DISPONIVEL’;

                    A parte em vermelho já basta para que somente a primeira pessoa a executar o update e efetuar o commit reserve o horário. A condição vai impedir as outras pessoas de atualizar o registro e sobrescrever o horário da pessoa que agendou anteriormente.

                    Após o update e commit, é só verificar se o id_cliente é o mesmo da pessoa que tentou agendar o horário, se sim, sucesso, se id_cliente não for igual, mostrar mensagem de que horário não está mais disponível.

                    Estou falando de update pois você comentou que a tabela AGENDA_DETAIL já tem os horários disponíveis, então imagino que esta funcionalidade de agendar horários seja feita somente com atualizações de registros já existentes.

                    #96159
                    luan
                    Participante

                      Boa Burga perfeito, fiz o que você sugeriu!

                      Muito obrigado galera…

                      Abs []’s

                      #96163
                      Peterson
                      Participante

                        burga… mestre dos magos do SQL.

                        🙂

                        #96165
                        burga
                        Participante

                          [quote=”Peterson”:3f7xh9p6]burga… mestre dos magos do SQL. [/quote]

                          Receita:

                          3 xícaras de chá de dicas da galera sobre o problema;
                          4 colheres de sopa de dúvidas do pessoal em relação ao problema;
                          3 xícaras de chá de respostas do luan às dúvidas da galera;
                          1 pitada de modelagem do banco.

                          Junte tudo, e bata no liquidificador. Asse por 10 minutos…

                          Sirva ainda quente, um exemplo de como resolver o problema de uma forma diferente da inicial.

                          Ou seja, sem a ajuda de todos a “receita” não ia sair! 😆

                          E aqui no grupo tem um pessoal bem melhor do que eu em relação a SQL, só o francisco aí já me dá um baile!

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