Bom dia Leandro... Concordo com você que seja um tanto quanto "decepcionante" você não conseguir um lock para consultas, mas como tratado, faz parte do modelo relacional. Também tive essa dificuldade no início, quando vim trabalhar com bancos relacionais.
Bem, mas como comentei, uma forma de "burlar" esta restrição é utilizar a instrução "FOR UPDATE NOWAIT". Segue um exemplo: Em uma seção do psql (pgadmin, aplicação da empresa, etc...) aberta eu realizo um select: begin; select * from municipio where cod_uf = 43 FOR UPDATE NOWAIT; (Observe que eu não fechei a transação...) Se em outra seção aberta eu realizar o mesmo select : begin; select * from municipio where cod_uf = 43 FOR UPDATE NOWAIT; O banco simplesmente me retorna a mensagem: ERROR: could not obtain lock on row in relation "municipio" Bem... É uma forma de burlar o problema a princípio, mas como já discutido aqui, o melhor a fazer (ao menos a médio prazo) é rever a aplicação. Depois de revista, ai sim você pode optar pelo melhor modelo. Utilizar o FOR UPDATE NOWAIT em consultas de atualização não é um erro, mas utilizá-lo indiscriminadamente pode trazer transtornos e "efeitos colaterais" não desejados. Todavia, como cada caso exige uma solução específica, fica ai a sugestão. Espero ter ajudado. Att, -- Charly Frankl http://javadevilopers.blogspot.com/ [email protected] Linux user #391083 2009/8/12 JotaComm <[email protected]> > Olá, Miguel > > Faça o seguinte: > > Sessão A: > BEGIN; > UPDATE tabela SET codigo=100 WHERE codigo=1; > --Vá para a sessão B > > > Sessão B: > BEGIN; --Opcional > SELECT * FROM tabela WHERE codigo=1; > --Aqui você ainda verá o registro 1, porque a transação (Sessão A) que está > alterando o registro não fez o commit, então consequentemente você não > consegue através desta sessão ver que o registro foi modificado. Para ver > que o registro 1 não existe mais é necessário executar o comando COMMIT na > Sessão A. > > Qualquer dúvida pergunta ai. > > 2009/8/12 MIGUEL JOSE DE LIMA <[email protected]> > > Bom dia, >> Leandro, eu concordo com vc, talvez tenho que aprender a conviver com os >> conceitos >> de Banco de Dados Relacional e SQL..., mas confesso a vc que para mim é >> meio >> decepicionante, não conseguir LOCAR um registro para leitura e poder >> tratar isso. >> Até velho bom antigo CLIPPER fazia isso, vc imagina eu acostumado a fazer >> isso >> por logos anos, também com ADABAS. >> Mas eu gostaria, se possível, de lhe perguntar: COMO É POSSÍVEL ATUALIZAR >> UM SALDO DE QUALQUER COISA (estoque/contacorrente), SEM PRENDER O >> REGISTRO PARA LEITURA? COMO POSSO SIMULAR ISSO? >> Obs.: Como algumas pessoas já tentaram me ajudar..., informa mais uma vez >> que >> o SELECT ... FOR UPDATE não bloquei leitura! >> >> Obrigado! >> >> 2009/8/11 Leandro Henrique Pereira Neto < >> [email protected]> >> >>> Pelo que conheço não é uma questão do PostgreSQL e sim de bancos padrão >>> SQL, pelo menos nos mais populares (SqlServer, Oracle, MySQL, PostgreSQL e >>> DB2). >>> >>> >>> O SELECT "simples" nunca é bloqueado (somente se usar for update). >>> Porém usar todos os SQL com FOR UPDATE pode travar todo o seu sistema >>> rapidinho já que somente uma transação poderá ler os dados de cada vez, como >>> em sistema OLTP temos normalmente mais leitura do que alteração a coisa >>> acaba ficando complicada. >>> >>> O que tem são os conceitos de transação e de consistência de leitura. >>> >>> Talvez seja o caso de você pensar o sistema em temos de bancos SQL e não >>> tentar fazer no PostgreSQL o que um banco como o Adabas faz pois estruturas >>> de funcionamento e implementação totalmente diferentes. >>> >>> Leandro Henrique Pereira Neto >>> Administração de bancos de dados >>> >>> >>> >>> >>> Charly Frankl escreveu: >>> >>> Miguel, boa noite... >>> >>> Para você bloquear os selects, faça todos com FOR UPDATE ... Ai você tem >>> opções, onde para retornar logo que está "ocupado" utilize NOWAIT. >>> >>> Att, >>> >>> >>> 2009/8/11 JotaComm <[email protected]> >>> >>>> Olá, Miguel >>>> >>>> Já comentei no email anterior e fiz uma pequena descrição de como isso >>>> funciona. Você deu uma olhada no exemplo que mandei? >>>> >>>> O PostgreSQL não bloqueia a leitura (SELECT), apenas operações de >>>> escrita (UPDATE e DELETE). >>>> >>>> >>>> 2009/8/11 MIGUEL JOSE DE LIMA <[email protected]> >>>> >>>>> Oi Mário, Este é o problema a leitura nunca é bloqueada. >>>>> Fiz os testes pedidos, mas para mim não mudou nada! >>>>> Veja: >>>>> - Na sessão 1: >>>>> db_teste=# BEGIN WORK; >>>>> BEGIN >>>>> db_teste=# LOCK TABLE tab_material IN ROW EXCLUSIVE MODE NOWAIT; >>>>> LOCK TABLE >>>>> db_teste=# UPDATE tab_material SET desc_serma = 'LAPIS Y' where >>>>> codg_serma='10'; >>>>> UPDATE 1 >>>>> db_teste=# *** aguardando novo comando *** >>>>> - Na sessão 2: >>>>> db_teste=# BEGIN WORK; >>>>> BEGIN >>>>> db_teste=# SELECT * FROM tab_material where codg_serma='10'; >>>>> codg_empr | codg_serma | id_serma | desc_serma >>>>> >>>>> >>>>> -----------+------------+------------+------------+--------------+------ >>>>> 202 | 10 | 2020000010 | LAPIS Y | >>>>> >>>>> É isso ai!!!?? >>>>> Obrigado. >>>>> >>>>> 2009/8/11 Mário Oshiro <[email protected]> >>>>> >>>>>> Em SQLServer, fiz um teste parecido com o seu. >>>>>> >>>>>> Qdo vc faz um lock de registro ou trabela, ele nao bloqueia a leitura >>>>>> de outras sessoes, ate' que a >>>>>> sessao de posse do lock, faça um update de algum dado do registro. >>>>>> >>>>>> Para bloquear o select que vc fez, faca em seguida um update com a >>>>>> mesmo >>>>>> where assim : >>>>>> >>>>>> db_teste=# SELECT * FROM tab_material where codg_serma='10' FOR >>>>>> UPDATE; >>>>>> update tab_material set codg_serma='10' where codg_serma='10' ; >>>>>> >>>>>> teste la e depois envie o resultado. >>>>>> >>>>>> até mais. >>>>>> >>>>>> >>>>>> >>>>>> MIGUEL JOSE DE LIMA wrote: >>>>>> > Caros, participantes... >>>>>> > Sou iniciante neste mundo do PostgreSQL. >>>>>> > Trabalho com outro Banco de Dados - ADABAS (UNIX SOLARIS/MAINFRAME), >>>>>> > mas me incubiram de fazer testes no PostgreSQL para bloquer >>>>>> registros. >>>>>> > Então... >>>>>> > >>>>>> > Estou precisando de ajuda para bloquear a leitura de um registro, ou >>>>>> > seja, >>>>>> > em um cenário como: >>>>>> > "Atualização de Estoque de um Material" : >>>>>> > Antes de atualizar o estoque do material selecionado eu preciso >>>>>> > bloquear o registro para que >>>>>> > nenhuma outra sessão possa obter o dado do registro. >>>>>> > PRECISO DE UMA LEITURA EXCLUSIVA - TOTALMENTE RESTRITIVA. >>>>>> > Estou usando o PostgreSQL 8.3.7 para os testes - em linux >>>>>> > Já li e reli sobre o Isolamento de Transação, mas pode ser que eu >>>>>> não >>>>>> > esteja entendendo...??? >>>>>> > Fiz o seguinte teste via psql: >>>>>> > - Na Sessão "A" >>>>>> > db_teste=# BEGIN WORK; >>>>>> > BEGIN >>>>>> > db_teste=# LOCK TABLE tab_material IN ROW EXCLUSIVE MODE NOWAIT; >>>>>> > LOCK TABLE >>>>>> > db_teste=# SELECT * FROM tab_material where codg_serma='10' FOR >>>>>> UPDATE; >>>>>> > resultado obtido ok! >>>>>> > *** aqui eu preciso bloquear todos os materiais/itens (de um >>>>>> pedido) >>>>>> > - como ex. fiz de apenas 1 (um). >>>>>> > >>>>>> > - Na Sessão "B": >>>>>> > ** Fiz o mesmo SELECT sem a clausula FOR UPDATE: >>>>>> > SELECT * FROM tab_material where codg_serma='10' >>>>>> > >>>>>> > ** aqui eu obtive o resultado ok da leitura. >>>>>> > Portanto, é aqui, neste ponto que não deveria permitir nenhuma >>>>>> > leitura, já que sessão "A" ainda não terminou! >>>>>> > E AI ALGUÉM PODE ME AJUDAR!? >>>>>> > >>>>>> > Obrigado! >>>>>> > >>>>>> > >>>>>> >>>>>
_______________________________________________ pgbr-geral mailing list [email protected] https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
