- Este tópico contém 10 respostas, 7 vozes e foi atualizado pela última vez 15 anos, 2 meses atrás por
burga.
-
AutorPosts
-
17 de setembro de 2010 às 6:07 pm #96123
luan
ParticipanteBom 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
17 de setembro de 2010 às 7:12 pm #96126VitorLeandro
ParticipanteFala 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.
17 de setembro de 2010 às 9:31 pm #96130jspaulonci
ParticipanteLuan , 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.
17 de setembro de 2010 às 10:01 pm #96131Peterson
ParticipanteComo 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.
17 de setembro de 2010 às 10:01 pm #96132vieri
ParticipanteNo 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?
17 de setembro de 2010 às 10:20 pm #96133fsitja
ParticipanteVocê 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.
17 de setembro de 2010 às 11:07 pm #96134luan
ParticipanteObrigado 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
18 de setembro de 2010 às 4:54 am #96139burga
ParticipanteEu 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.
20 de setembro de 2010 às 9:04 pm #96159luan
ParticipanteBoa Burga perfeito, fiz o que você sugeriu!
Muito obrigado galera…
Abs []’s
20 de setembro de 2010 às 9:50 pm #96163Peterson
Participanteburga… mestre dos magos do SQL.
🙂
21 de setembro de 2010 às 12:22 am #96165burga
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!
-
AutorPosts
- Você deve fazer login para responder a este tópico.