[oracle_br] Re: Duvida sobre Deadlock

2008-05-22 Por tôpico jlchiappa
Colega, esse método de trabalho é absolutamente ESTRANHO, não vejo
muito sentido nisso : veja, se eu quero ler a informação eu quero ler
TODA a informação que existe de acordo com os meus critérios de
pesquisa, só depois se eu for alterar aí sim se mais alguém alterou
antes eu recebo um msg de erro, acho que nâo receber a informaçâo que
existe só porque alguém a consultou antes, E receber a informação numa
eventual próxima consulta se o lock já foi removido (mesmo sem
alteração!)  deve ser EXTREMAMENTE CONFUSO pro usuário, não é de modo
ALGUM um procedimento padrão e recomendado isso  E lógico, se é
uma programa que está fazendo processo em background, pra vc ter
várias leituras simultâneas (cada sessão fazendo uma leitura de uma
parte) é para isso que foi inventado o PARALLEL SQL... Ou pelo menos
se poderia fazer Parallel DIY, na mão, via rowid, procure em
asktom.oracle.com que vc acha exemplos...
  Bom, mas sim, dá pra fazer, é algo totalmente sem sentido mas dá pra
fazer, mas é em PL/SQl e não em SQL, exemplo (LOGICAMENTE isso só
funciona entre sessões DIFERENTES, na mesma sessão que fez o lock ela
vê tudo, lógico) :
 
[EMAIL PROTECTED]:SQLselect empno, ename, sal from emp order by sal;

 EMPNO ENAME SAL
-- -- --
  7369 SMITH 800
  7900 JAMES 950
  7876 ADAMS1100
  7521 WARD 1250
  7654 MARTIN   1250
  7934 MILLER   1300
  7844 TURNER   1500
  7499 ALLEN1600
  7782 CLARK2450
  7698 BLAKE2850
  7566 JONES2975
  7788 SCOTT3000
  7902 FORD 3000
  7839 KING 5000

14 linhas selecionadas.

== numa sessão 1 quero ler e travar o primeiro registro NA ORDEM
desejada (ordem é fundamental aqui, NÃO EXISTE ordem natural numa
tabela) :

scott#1:SQLed
Gravou file afiedt.buf

  1  DECLARE
  2 resource_busy   exception;
  3 pragma exception_init( resource_busy, -54 );
  4 v_reg EMP%rowtype;
  5  BEGIN
  6for x in ( select rowid rid from emp order by sal)
  7loop
  8   Begin
  9  select * into v_reg from emp where rowid = x.rid for
update nowait;
 10  dbms_output.put_line('Emp='  || v_reg.empno
 11   || ',Name=' || v_reg.ename
 12   || ',Sal='  || v_reg.sal);
 13  exit;
 14   Exception
 15  when resource_busy then
 16 null;
 17   End;
 18end loop;
 19* END;
scott#1:SQL/
Emp=7369,Name=SMITH,Sal=800

Procedimento PL/SQL concluído com sucesso.

== na sessão 2, pulei o registro lockado pela sessão 1 

scott#2:SQLDECLARE
  2 resource_busy   exception;
  3 pragma exception_init( resource_busy, -54 );
  4 v_reg EMP%rowtype;
  5  BEGIN
  6for x in ( select rowid rid from emp order by sal)
  7loop
  8   Begin
  9  select * into v_reg from emp where rowid = x.rid for
update nowait;
 10  dbms_output.put_line('Emp='  || v_reg.empno
 11   || ',Name=' || v_reg.ename
 12   || ',Sal='  || v_reg.sal);
 13  exit;
 14   Exception
 15  when resource_busy then
 16 null;
 17   End;
 18end loop;
 19  END;
 20  /
Emp=7900,Name=JAMES,Sal=950

Procedimento PL/SQL concluído com sucesso.

== sessão 3, pulei o lock da sessão 1 e da sessão 2, achando o
próximo não-locakdo e o lockando  :

scott#3:SQLDECLARE
  2 resource_busy   exception;
  3 pragma exception_init( resource_busy, -54 );
  4 v_reg EMP%rowtype;
  5  BEGIN
  6for x in ( select rowid rid from emp order by sal)
  7loop
  8   Begin
  9  select * into v_reg from emp where rowid = x.rid for
update nowait;
 10  dbms_output.put_line('Emp='  || v_reg.empno
 11   || ',Name=' || v_reg.ename
 12   || ',Sal='  || v_reg.sal);
 13  exit;
 14   Exception
 15  when resource_busy then
 16 null;
 17   End;
 18end loop;
 19  END;
 20  /
Emp=7876,Name=ADAMS,Sal=1100

Procedimento PL/SQL concluído com sucesso.


[]s

 Chiappa
 
--- Em oracle_br@yahoogrupos.com.br, Manuel Acacio Ludgero Domingos
[EMAIL PROTECTED] escreveu

 
 Pessoal , estou com um problema e talvez vc´s possam me ajudar.
  
 Seguinte tenho uma tabela preciso fazer um select de um registro
travando esse registro e alterando dele , utilizei o select for update
skip locked para travar e desprezar os travados.
  
 Porem quando outra sessao efetuar o mesmo select , o registro
travado nao pode vir e sim o proximo destravado .
  
 estou colocando no select um 

RE: [oracle_br] Re: Duvida sobre Deadlock

2008-05-22 Por tôpico Manuel Acacio Ludgero Domingos

Entao não eh bem isso ,
 
A situacao eh a seguinte tenho uma proc que ira selecionar um registro e depois 
fazer update nele , porem essa proc vai ser chamada em em paralelo podendo ser 
chamado no mesmo milesimo de segundo , preciso impedir q em uma chamada x o 
mesmo registro seja chamado na x+1 , e nao posso deixar a chamada esperando com 
wait, o exemplo abaixo daria certo , se eu pudesse efetuar a leitura da tabela 
inteira porem eu nao posso pq a proc deve rodar em questão de milessegundo e 
preciso prever a volumetria da tabela , uma ideia seria colocar o rownum = 1 , 
mas mesmo no exemplo abaixo se no select do for eu colocasse rownum = 1 , 
retornaria somente a primeira vez , e a segunda e a terceira daria 
no_data_found , pq o oracle monta o rownum antes de dar lock e o mesmo se eu 
colocasse for update skip locked .
 
Dei um jeito colocando o select em um cursor e dando somente um fetch , porem 
nao tem rownum no select sendo assim executa o plano todo , perdendo 
performance .
 
Acho q ficou mais claro , veja bem não é ilógico me expressei mal no outro 
email :)
 
Se puder me ajudar eu agradeço muito.
 
Acacio


To: [EMAIL PROTECTED]: [EMAIL PROTECTED]: Thu, 22 May 2008 15:38:34 
+Subject: [oracle_br] Re: Duvida sobre Deadlock




Colega, esse método de trabalho é absolutamente ESTRANHO, não vejomuito sentido 
nisso : veja, se eu quero ler a informação eu quero lerTODA a informação que 
existe de acordo com os meus critérios depesquisa, só depois se eu for alterar 
aí sim se mais alguém alterouantes eu recebo um msg de erro, acho que nâo 
receber a informaçâo queexiste só porque alguém a consultou antes, E receber a 
informação numaeventual próxima consulta se o lock já foi removido (mesmo 
semalteração!) deve ser EXTREMAMENTE CONFUSO pro usuário, não é de modoALGUM um 
procedimento padrão e recomendado isso  E lógico, se éuma programa que está 
fazendo processo em background, pra vc tervárias leituras simultâneas (cada 
sessão fazendo uma leitura de umaparte) é para isso que foi inventado o 
PARALLEL SQL... Ou pelo menosse poderia fazer Parallel DIY, na mão, via rowid, 
procure emasktom.oracle.com que vc acha exemplos...Bom, mas sim, dá pra fazer, 
é algo totalmente sem sentido mas dá prafazer, mas é em PL/SQl e não em SQL, 
exemplo (LOGICAMENTE isso sófunciona entre sessões DIFERENTES, na mesma sessão 
que fez o lock elavê tudo, lógico) :[EMAIL PROTECTED]:SQLselect empno, 
ename, sal from emp order by sal;EMPNO ENAME SAL-- -- 
--7369 SMITH 8007900 JAMES 9507876 ADAMS 11007521 WARD 12507654 
MARTIN 12507934 MILLER 13007844 TURNER 15007499 ALLEN 16007782 CLARK 24507698 
BLAKE 28507566 JONES 29757788 SCOTT 30007902 FORD 30007839 KING 500014 linhas 
selecionadas.== numa sessão 1 quero ler e travar o primeiro registro NA 
ORDEMdesejada (ordem é fundamental aqui, NÃO EXISTE ordem natural numatabela) 
:scott#1:SQLedGravou file afiedt.buf1 DECLARE2 resource_busy exception;3 
pragma exception_init( resource_busy, -54 );4 v_reg EMP%rowtype;5 BEGIN6 for x 
in ( select rowid rid from emp order by sal)7 loop8 Begin9 select * into v_reg 
from emp where rowid = x.rid forupdate nowait;10 dbms_output.put_line('Emp=' || 
v_reg.empno11 || ',Name=' || v_reg.ename12 || ',Sal=' || v_reg.sal);13 exit;14 
Exception15 when resource_busy then16 null;17 End;18 end loop;19* 
END;scott#1:SQL/Emp=7369,Name=SMITH,Sal=800Procedimento PL/SQL concluído com 
sucesso.== na sessão 2, pulei o registro lockado pela sessão 1 
scott#2:SQLDECLARE2 resource_busy exception;3 pragma exception_init( 
resource_busy, -54 );4 v_reg EMP%rowtype;5 BEGIN6 for x in ( select rowid rid 
from emp order by sal)7 loop8 Begin9 select * into v_reg from emp where rowid = 
x.rid forupdate nowait;10 dbms_output.put_line('Emp=' || v_reg.empno11 || 
',Name=' || v_reg.ename12 || ',Sal=' || v_reg.sal);13 exit;14 Exception15 when 
resource_busy then16 null;17 End;18 end loop;19 END;20 
/Emp=7900,Name=JAMES,Sal=950Procedimento PL/SQL concluído com sucesso.== 
sessão 3, pulei o lock da sessão 1 e da sessão 2, achando opróximo não-locakdo 
e o lockando :scott#3:SQLDECLARE2 resource_busy exception;3 pragma 
exception_init( resource_busy, -54 );4 v_reg EMP%rowtype;5 BEGIN6 for x in ( 
select rowid rid from emp order by sal)7 loop8 Begin9 select * into v_reg from 
emp where rowid = x.rid forupdate nowait;10 dbms_output.put_line('Emp=' || 
v_reg.empno11 || ',Name=' || v_reg.ename12 || ',Sal=' || v_reg.sal);13 exit;14 
Exception15 when resource_busy then16 null;17 End;18 end loop;19 END;20 
/Emp=7876,Name=ADAMS,Sal=1100Procedimento PL/SQL concluído com 
sucesso.[]sChiappa--- Em oracle_br@yahoogrupos.com.br, Manuel Acacio Ludgero 
Domingos[EMAIL PROTECTED] escreveu  Pessoal , estou com um problema e 
talvez vc´s possam me ajudar.  Seguinte tenho uma tabela preciso fazer um 
select de um registrotravando esse registro e alterando dele , utilizei o 
select for updateskip locked para travar e desprezar os travados.  

[oracle_br] Re: Duvida sobre Deadlock

2008-05-22 Por tôpico jlchiappa
No e-mail original vc tinha dito :

..tenho uma tabela preciso fazer um select de um registro travando
esse registro e alterando ele ... Porem quando outra sessao efetuar
o mesmo select , o registro travado nao pode vir e sim o proximo
destravado .

é o que eu fiz, ok ? INCLUSIVE, diferentes execuções duma proc ***
NECESSARIAMENTE *** vão sim estar em sessões difentes, então a técnica
de pular os regs lockados que eu empreguei funcionaria, sim...E outra,
 o que acontece na procedure é que normalmente vc tem uma ARGUMENTO
indicando qual o registro que vc quer selecionar e updatear, então
essa lógica de buscar o próximo sorry mas penso que ainda não faz
muito sentido... E outra, tal como eu disse, normalmente se vc quer
ter várias sessões fazendo um processamento, Parallel SQL é a
indicação
  Também não faz sentido procedure chamada 2x no mesmo milisegundo -
que tipo de sistema vc está construindo que exige isso ??? Normalmente
OU um sistema é OLTP (aonde o usuário consulta um ou mais registros,
os analisa na tela e pode ou não desejar alterá-los) ou é BATCH (aonde
há a figura da carga de dados, que tipicamente TEM que ser completada
antes de qquer consulta, então a´entra a figura do parallel sql)
Explique direito o que vc quer fazer, que tipo de sistema vc está
construindo, o seu ambiente (se modo c/s ou web), pra gente poder
entender melhor a sua necessidade...

[]s

  Chiappa 
--- Em oracle_br@yahoogrupos.com.br, Manuel Acacio Ludgero Domingos
[EMAIL PROTECTED] escreveu

 
 Entao não eh bem isso ,
  
 A situacao eh a seguinte tenho uma proc que ira selecionar um
registro e depois fazer update nele , porem essa proc vai ser chamada
em em paralelo podendo ser chamado no mesmo milesimo de segundo ,
preciso impedir q em uma chamada x o mesmo registro seja chamado na
x+1 , e nao posso deixar a chamada esperando com wait, o exemplo
abaixo daria certo , se eu pudesse efetuar a leitura da tabela inteira
porem eu nao posso pq a proc deve rodar em questão de milessegundo e
preciso prever a volumetria da tabela , uma ideia seria colocar o
rownum = 1 , mas mesmo no exemplo abaixo se no select do for eu
colocasse rownum = 1 , retornaria somente a primeira vez , e a segunda
e a terceira daria no_data_found , pq o oracle monta o rownum antes de
dar lock e o mesmo se eu colocasse for update skip locked .
  
 Dei um jeito colocando o select em um cursor e dando somente um
fetch , porem nao tem rownum no select sendo assim executa o plano
todo , perdendo performance .
  
 Acho q ficou mais claro , veja bem não é ilógico me expressei mal no
outro email :)
  
 Se puder me ajudar eu agradeço muito.
  
 Acacio
 
 
 To: [EMAIL PROTECTED]: [EMAIL PROTECTED]: Thu, 22 May 2008 15:38:34
+Subject: [oracle_br] Re: Duvida sobre Deadlock
 
 
 
 
 Colega, esse método de trabalho é absolutamente ESTRANHO, não
vejomuito sentido nisso : veja, se eu quero ler a informação eu quero
lerTODA a informação que existe de acordo com os meus critérios
depesquisa, só depois se eu for alterar aí sim se mais alguém
alterouantes eu recebo um msg de erro, acho que nâo receber a
informaçâo queexiste só porque alguém a consultou antes, E receber a
informação numaeventual próxima consulta se o lock já foi removido
(mesmo semalteração!) deve ser EXTREMAMENTE CONFUSO pro usuário, não é
de modoALGUM um procedimento padrão e recomendado isso  E lógico,
se éuma programa que está fazendo processo em background, pra vc
tervárias leituras simultâneas (cada sessão fazendo uma leitura de
umaparte) é para isso que foi inventado o PARALLEL SQL... Ou pelo
menosse poderia fazer Parallel DIY, na mão, via rowid, procure
emasktom.oracle.com que vc acha exemplos...Bom, mas sim, dá pra fazer,
é algo totalmente sem sentido mas dá prafazer, mas é em PL/SQl e não
em SQL, exemplo (LOGICAMENTE isso sófunciona entre sessões DIFERENTES,
na mesma sessão que fez o lock elavê tudo, lógico)
:[EMAIL PROTECTED]:SQLselect empno, ename, sal from emp order by sal;EMPNO
ENAME SAL-- -- --7369 SMITH
8007900 JAMES 9507876 ADAMS 11007521 WARD 12507654 MARTIN 12507934
MILLER 13007844 TURNER 15007499 ALLEN 16007782 CLARK 24507698 BLAKE
28507566 JONES 29757788 SCOTT 30007902 FORD 30007839 KING 500014
linhas selecionadas.== numa sessão 1 quero ler e travar o primeiro
registro NA ORDEMdesejada (ordem é fundamental aqui, NÃO EXISTE ordem
natural numatabela) :scott#1:SQLedGravou file afiedt.buf1 DECLARE2
resource_busy exception;3 pragma exception_init( resource_busy, -54
);4 v_reg EMP%rowtype;5 BEGIN6 for x in ( select rowid rid from emp
order by sal)7 loop8 Begin9 select * into v_reg from emp where rowid =
x.rid forupdate nowait;10 dbms_output.put_line('Emp=' || v_reg.empno11
|| ',Name=' || v_reg.ename12 || ',Sal=' || v_reg.sal);13 exit;14
Exception15 when resource_busy then16 null;17 End;18 end loop;19*
END;scott#1:SQL/Emp=7369,Name=SMITH,Sal=800Procedimento PL/SQL
concluído com sucesso.== na sessão 2, pulei o registro lockado pela
sessão 1 

RE: [oracle_br] Re: Duvida sobre Deadlock

2008-05-22 Por tôpico Manuel Acacio Ludgero Domingos

Sim concordo o código que vc me enviou funciona plenamente , soh q preciso q 
seja muito rapido a execucao e fazendo em um cursor , a tabela será lida 
inteira , quero q soh retorne a primeira linha liberada , bom deixa eu me 
explicar melhor.
 
Estou desenvolvendo um modulo de estoque , a rotina q estou com problemas eh a 
rotina q reserva um item do estoque .
Esta rotina será invocada pelo módulo de promocoes que vai reservar n itens do 
estoque passando o tipo e o estoque em questao .
Só que a rotina será chamada por um cluster entao sim será chamada no mesmo 
milissegundo , ou nao , mas vai haver deadlock e quando houver deadlock eu 
preciso q a minha rotina selecione o proximo item e de um skip no registro 
travado .
 
Tipo efetuo o select selecionando o tipo do item e o estoque , retorno o item 
xpto , dai uma outra rotina do meu modulo recebe o codigo do item e altera o 
status dele para reservado . 
Só que nesse mesmo segundo a proc pode e provavelmente foi chamada novamente 
preciso que retorne somente um entao coloco o rownum = 1 , como a celular eu 
travei com for update nowait skip locked , ele nao acha o rownum = 1 pq ele ta 
travado pela primeira chamada e da no_data_found.
 
O que fiz para resolver eh colocar num cursor e dar somente um fetch com for 
update skip locked , dai ele me tras o proximo registro , porem a performance 
cai , se eu utilizasse o rownum seria melhor , no caso q vc me enviou eh mais 
ou menos isso tbm , soh que vai executar o plano todo , e preciso q essa proc 
execute em questao de msecs , nao soh ela como o processo todo desde a tela q 
chama o banco ateh o modulo de promoces ateh me chamar e voltar pra tela.
 
Acho que agora fez mais sentido
 
Nao soube me expressar nos emails anteriores 
 
 
Se puder me ajudar agradeço muito
 
Valew Chiappa!
 
Acacio


To: [EMAIL PROTECTED]: [EMAIL PROTECTED]: Thu, 22 May 2008 17:58:16 
+Subject: [oracle_br] Re: Duvida sobre Deadlock




No e-mail original vc tinha dito :..tenho uma tabela preciso fazer um select 
de um registro travandoesse registro e alterando ele ... Porem quando outra 
sessao efetuaro mesmo select , o registro travado nao pode vir e sim o 
proximodestravado .é o que eu fiz, ok ? INCLUSIVE, diferentes execuções duma 
proc ***NECESSARIAMENTE *** vão sim estar em sessões difentes, então a 
técnicade pular os regs lockados que eu empreguei funcionaria, sim...E outra,o 
que acontece na procedure é que normalmente vc tem uma ARGUMENTOindicando qual 
o registro que vc quer selecionar e updatear, entãoessa lógica de buscar o 
próximo sorry mas penso que ainda não fazmuito sentido... E outra, tal como eu 
disse, normalmente se vc querter várias sessões fazendo um processamento, 
Parallel SQL é aindicaçãoTambém não faz sentido procedure chamada 2x no 
mesmo milisegundo -que tipo de sistema vc está construindo que exige isso ??? 
NormalmenteOU um sistema é OLTP (aonde o usuário consulta um ou mais 
registros,os analisa na tela e pode ou não desejar alterá-los) ou é BATCH 
(aondehá a figura da carga de dados, que tipicamente TEM que ser 
completadaantes de qquer consulta, então a´entra a figura do parallel 
sql)Explique direito o que vc quer fazer, que tipo de sistema vc 
estáconstruindo, o seu ambiente (se modo c/s ou web), pra gente poderentender 
melhor a sua necessidade...[]sChiappa --- Em oracle_br@yahoogrupos.com.br, 
Manuel Acacio Ludgero Domingos[EMAIL PROTECTED] escreveu  Entao não eh bem 
isso ,  A situacao eh a seguinte tenho uma proc que ira selecionar umregistro 
e depois fazer update nele , porem essa proc vai ser chamadaem em paralelo 
podendo ser chamado no mesmo milesimo de segundo ,preciso impedir q em uma 
chamada x o mesmo registro seja chamado nax+1 , e nao posso deixar a chamada 
esperando com wait, o exemploabaixo daria certo , se eu pudesse efetuar a 
leitura da tabela inteiraporem eu nao posso pq a proc deve rodar em questão de 
milessegundo epreciso prever a volumetria da tabela , uma ideia seria colocar 
orownum = 1 , mas mesmo no exemplo abaixo se no select do for eucolocasse 
rownum = 1 , retornaria somente a primeira vez , e a segundae a terceira daria 
no_data_found , pq o oracle monta o rownum antes dedar lock e o mesmo se eu 
colocasse for update skip locked .  Dei um jeito colocando o select em um 
cursor e dando somente umfetch , porem nao tem rownum no select sendo assim 
executa o planotodo , perdendo performance .  Acho q ficou mais claro , veja 
bem não é ilógico me expressei mal nooutro email :)  Se puder me ajudar eu 
agradeço muito.  Acacio   To: [EMAIL PROTECTED]: [EMAIL PROTECTED]: Thu, 
22 May 2008 15:38:34+Subject: [oracle_br] Re: Duvida sobre Deadlock
 Colega, esse método de trabalho é absolutamente ESTRANHO, nãovejomuito 
sentido nisso : veja, se eu quero ler a informação eu querolerTODA a informação 
que existe de acordo com os meus critériosdepesquisa, só depois se eu for 
alterar aí sim se mais alguémalterouantes eu recebo um msg de erro, acho que