inacreditÁvel

65 respostas
skill_ufmt

Galerinha,

Estou aqui quase saindo do trabalho, há 1 dia da entrega do sistema para o cliente, e a aplicação para de funcionar completamente. :shock:

Como perdigueiro sai desesperadamente atrás do problema, quando me deparo com a seguinte situação:

Tenho uma maldita tabela no BD rodando em ORACLE onde existe uma chave primáira composta, acontece que um dos campos dessa chave é sequêncial. EX.

Chave Composta
campo1 campo2
10 1
10 2
10 3
11 1
11 2
11 3

Essa tabela é a principal tabela do sistema.

Acontece que para o sequênciamento estava sendo feito um SELECT MAX no campo e somando 1 :evil:

Agora imaginem, 3000 acessos silmultâneos fazendo este select + 1, e retornado o mesmo valor, visto que isso não garante um lock na tabela.

Oque ocorre, aplicação condenada :roll:

Surgiram algumas idéias, mas nada que resultasse numa solução viável ao momento, então resolvi recorrer a esse poço de talentos para que alguma alma me de alguma sugestão ou pelo um ombro amigo pra chorar :frowning:

E para os que pensaram em trigger, e storeProcedures, definitivamente fora de questão por exigências do cliente. :roll:

O sistema incrivelmente já está em produção na sua versão 1(não imagino como) e este é uma versão dois deste mesmo sistema(meu pai eterno), portanto, sem mudanças radicais ou vai mais um boooom tempo de refactoring.

idéias? :idea: :idea: :idea:

65 Respostas

mister_m

Mudar o segundo valor pra ser sempre sequencial, independente do primeiro? Algo como:

10 1
10 2
10 3
11 4
11 5
11 6
T

select max? Isso é coisa de quem nunca viu “SEQUENCEs” na vida e resolveu usar um banco de dados Oracle. Aproveitando o que o Mister__M lhe disse, daria para alimentar o segundo campo com uma sequence, ou então usar uma outra sequence para gerar um número sequencial, e calcular o primeiro e o segundo campo a partir desse número gerado?

skill_ufmt

mister__m:
Mudar o segundo valor pra ser sempre sequencial, independente do primeiro? Algo como:

10 1 10 2 10 3 11 4 11 5 11 6

solução boa, mas acontece que são Pai e Filhos, nem semrpe vai ter essa sequência, por ex.

se eu pegar o 10 2, no seu exemplo ai, eu teria que gerar 10 7, 10 8, enfim alguns registros e não somente 1.

Outra coisa, é que esse registro só é gravado nesta tabela após ser feitas outras 3 operações no banco, e um comit no final de tudo isso.

Acontece que se der um rollback, é pau na coisa, se mais de um usuário acessar ao mesmo tempo, é pau na app, não posso dar lock na tabela, pois isso impediria os outros 2999 usuários de fazer operações nela :slight_smile:

Uma sugestão foi ter uma segunda tabela auxiliar onde se repetissem estes dois valores e esta sim fosse lockada, mas mas isso implicaria em mudanças estruturais e boas partes da aplicação :frowning:

Sem contar que a app, é totalmente estruturada, oo passo longe disso aqui, e não foi me permitido refazer tudo ou refatorar.

skill_ufmt

Acontee que a SEQUENCE não funciona em chaves compostas :frowning:

Tentamos simular um sequence, com uma tabela auxiliar, e usando um “for update” após o select, mas isso não ficou nada viável :frowning:

T

Pelo que estou imaginando, você poderia tentar fazer uma solução mista - obter o primeiro campo com uma SEQUENCE, e o segundo com SELECT MAX. Qual seria o problema nesse caso?

skill_ufmt

thingol:
Pelo que estou imaginando, você poderia tentar fazer uma solução mista - obter o primeiro campo com uma SEQUENCE, e o segundo com SELECT MAX. Qual seria o problema nesse caso?

O primeiro campo é imutável a cada gerão de “Filhos”, o que muda seria o segundo campo que é no caso o sequencial.

O problema do MAX, é que ele não me garante um valor exclusivo, e se mais uma pessoa tentar usar este mesmo valor, o ORACLE trava geral, e esse valor em questão fia inutilizável enquanto o oracle não comitar as operações pendentes, só que se alguém vai lá e faz MAX novamente me retorna o mesmo valor, porque não foi inserido nada lá entende? a da sinuca de bico, porque o MAX sempre me trás o cara que não ta comitado e inutilizável, deixando travado banco e aplicação.

mister_m

Eu nunca disse que ia ficar “bonitinho” assim :slight_smile:

Mas, por que não pode ser 10 1, 11 2, 10 3? Pelo que eu entendi, o importante é não coincidir e manter a ordem, não?

skill_ufmt

Como é que vocês fazem, quando ocorre algo deste tipo, uma chave composta que um dos campos é sequencial?

Criam um novo campo que distinguirá cada registro tornado este chave primária, passando a composta para chave única e continuam fazendo as buscas normais por esta chave única?

Como é feito num banco onde exitem grandes massas de dados?

Deve ter um modo, isso é rotineiro de se acontecer, ou não?

mister_m

Explique seu caso de uso para isso :slight_smile:

Normalmente isso é coisa de usuário que acha “bonito” ser assim. Por que 10 1, 11 2, 10 3 não atende?

louds

Hmm, você não poderia travar os registros primeiro.

Isso vai te garantir o sequênciamento correto e paralelismo entre seqüências diferentes.
O problema é quando inserir o primeiro, para isso você pode travar um tabela secundária.

Fora isso, recomento pegarem algum expert oracle/j2ee para ajudar nessa situação.

foia

v se isso ajuda…


:oops:

fôia

louds

Inacreditavel nesse projeto são 2 coisas.

:arrow: A porta que usou select max/count para gerar chave primaria, isso é uma das primeiras coisas que você aprende que não escala para mais de UM usuario simultâneo.

:arrow: Um projeto que vai ter toda essa carga só receber testes de stress um dia antes.

Sinceramente? Sejam honestos com o cliente ou criem diversão suficiênte para corrigir o problema por baixo dos panos.

skill_ufmt

mister__m:
Eu nunca disse que ia ficar “bonitinho” assim :slight_smile:

Mas, por que não pode ser 10 1, 11 2, 10 3? Pelo que eu entendi, o importante é não coincidir e manter a ordem, não?

pode ser assim sim mister.

Acontece o seguinte, para que eu possa inserir nas outras tabelas e nessa eu só preciso ter o próximo número que estará no segundo campo, sem usar MAX.

± isso: select numero maior do campo2 onde campo = algum valor

mister_m

Se for assim, usa uma sequence! :slight_smile:

skill_ufmt

louds:
Hmm, você não poderia travar os registros primeiro.

Isso vai te garantir o sequênciamento correto e paralelismo entre seqüências diferentes.
O problema é quando inserir o primeiro, para isso você pode travar um tabela secundária.

Fora isso, recomento pegarem algum expert oracle/j2ee para ajudar nessa situação.

Surgiu esta idéia aqui e até agora é a melhor, más só posso travar uma tabela auxiliar mesmo, a tabela em questão nunca, ela se relaciona com todo mundo o que me travaria o resto todo :slight_smile:

Um dúvida quanto a esta solução, é que eu tenho 3 operações no banco antes de comitar tudo, e a tabela ficaria lockada nesse período, o que poderia me acarretar um certo transtorno, concorda?

skill_ufmt

louds:
Inacreditavel nesse projeto são 2 coisas.

:arrow: A porta que usou select max/count para gerar chave primaria, isso é uma das primeiras coisas que você aprende que não escala para mais de UM usuario simultâneo.

:arrow: Um projeto que vai ter toda essa carga só receber testes de stress um dia antes.

Sinceramente? Sejam honestos com o cliente ou criem diversão suficiênte para corrigir o problema por baixo dos panos.

tu acha que coloquei o inacreditável ai por que? hehe
Tu não mensionou o fato de o sistema estar na versão 2, como a 1 está rodando? hehehe

Acontece também que os testes aqui não bem “testes” hehe
não existe programas para teste de stress, o teste é feito visualmente(essa é pra acabar), só começaram a testar as consultas dos desenvolvedores(é não temos um DBA, pasmem novamente) por que insisti muito neste sentido.

Mas quem acabou encontrando esse problemão foi o sortudo aqui ehehe. E isso aconteceu justamente no último caso de uso, que é o mais importante(outro erro).

E nem irei mencionar que isso está e foi utilizado em mais uns 5 sistemas aqui dos quais não participei, ou seja, estado de alerta geral com luz vermelha girando em cima kkkkk

Enfim, usando uma frase de uma música que não me lembro de quem é, “É pra rir ou pra chorar?”

mister_m

Se este for o problema, faz isso num contexto transacional separado do primeiro. Deve resolver.

skill_ufmt

mister, mas o sequence não funcionará para o segundo campo, somente funciona para um campo só e quando este for a chave primária da tabela, ou to falando merda? :roll:

skill_ufmt

Pensei o segunte,

isolo o select max com for update num método, neste método eu abro uma conexão nova sem interferir na conexão que já está funcionando, e nesta conexão nova, eu já faço um insert atualizando o valor da tabela auxiliar, desta maneira, eu faria rapidamente um selec/insert/comit, isso já desalocaria a tabela para outros usuários, que já poderia pegar um valor novo, e assim não repetiria, e evitaria ao máximo o paralelismo.

será que é boa ou má solução?

mister_m

Sequence não é como campo identity. Você é que é responsável por ler o valor da sequence, por sinal. Não tem razão pra não funcionar.

Agora, que muitos frameworks de mapeamento O/R não sabem lidar sozinhos com a segunda sequence já é outro problema…

mister_m

Pelo que eu entendi até agora, o uso de sequence é bem superior.

skill_ufmt

Sequence não é como campo identity. Você é que é responsável por ler o valor da sequence, por sinal. Não tem razão pra não funcionar.

Agora, que muitos frameworks de mapeamento O/R não sabem lidar sozinhos com a segunda sequence já é outro problema…

segundo alguns experiente aqui, isso não funciona, não é possível fazer uma sequence para o segundo campo.

como é possível retornar uma sequence para o segundo campo, mister, seguindo que busco a sequence da maneira abaixo?

SELECT NOMEDASEQUENCE.NEXTVAL FROM DUAL

Não vejo como, sempre me retorna um campo :frowning:

mister_m

No comments :mrgreen:

skill_ufmt:
como é possível retornar uma sequence para o segundo campo, mister, seguindo que busco a sequence da maneira abaixo?

SELECT NOMEDASEQUENCE.NEXTVAL FROM DUAL

Não vejo como, sempre me retorna um campo :frowning:

Dois selects ou um:

louds

Que tal usar um esquema parecido a um dos métodos de locking do sybase, hashed locking.

Crie 1 tabela auxiliar com uns X registros, onde X é 2-3 vezes o tipo de usuarios simultâneos do teu sistema.

No teu código java faça hashing para espalhar a primeira parte da PK no intervalo de valores da tabela que acabou de criar.

De um select for update em um registro apenas da tabela auxiliar, vai ser via PK e ter poucos registros, então vai ser rápido.

Pronto, melhor que isso começa estourar o budget de minutos que você tem para arrumar isso.

skill_ufmt

No comments :mrgreen:

skill_ufmt:
como é possível retornar uma sequence para o segundo campo, mister, seguindo que busco a sequence da maneira abaixo?

SELECT NOMEDASEQUENCE.NEXTVAL FROM DUAL

Não vejo como, sempre me retorna um campo :frowning:

Dois selects ou um:

Calam mister não se exalte hehe, mas como vou referenciar um campo especifico para esta sequence, aqui no oracle não me deixa fazer referência a campo na criação da sequence. É uma sequence só, posso ter noms diferentes de sequences mas me retorna a emsa coisa :frowning:

skill_ufmt

louds:
Que tal usar um esquema parecido a um dos métodos de locking do sybase, hashed locking.

Crie 1 tabela auxiliar com uns X registros, onde X é 2-3 vezes o tipo de usuarios simultâneos do teu sistema.

No teu código java faça hashing para espalhar a primeira parte da PK no intervalo de valores da tabela que acabou de criar.

De um select for update em um registro apenas da tabela auxiliar, vai ser via PK e ter poucos registros, então vai ser rápido.

Pronto, melhor que isso começa estourar o budget de minutos que você tem para arrumar isso.

Hehe, cara seis são demais :slight_smile:

Mas já estou acreditando que isso não será entregue amanha kkkk

mister_m

skill_ufmt:
Calam mister não se exalte hehe, mas como vou referenciar um campo especifico para esta sequence, aqui no oracle não me deixa fazer referência a campo na criação da sequence. É uma sequence só, posso ter noms diferentes de sequences mas me retorna a emsa coisa :frowning:

Cara, acho que você está meio perdido. Uma sequence não está relacionada a campo nenhum no Oracle. Seu código é que relaciona.

Então você tem que conseguir usar criar n sequences ou até usar a mesma pros dois campos.

C
A sua aplicação é DONA do banco ou outras aplicações fazem atualizações nesta mesma tabela ( INSERTs ) ?
  
 Se a aplicação tem acesso exclusivo de escrita nesta tabela basta vc isolar o acesso a esta tabela e sincronizar o acesso ä mesma, mais ou menos assim:
public class KeyGenerator{
      private Map keys = new HashMap();

      public sinchronized Integer getNext( Integer mainKey ){
            // SELECT MAX(secondKey) FROM TABLE WHERE MAIN_KEY = ?
            Integer current = // resultado da query ou zero caso seja a                   primeira
            Integer old = (Integer) keys.get(mainKey);
            if( old == null ){
                old = new Integer(0);
            }
             Integer result = Math.max( old.intValue() , current.intValue()) + 1;
             keys.put( mainKey , result );
             return result;
      }
}
Assim vc tem controle sobre as outras threads e de vez em quando vc pode esvaziar esta cache de acordo com um tempo pré-determinado.
skill_ufmt

CLAUDIO GUALBERTO:

Assim vc tem controle sobre as outras threads e de vez em quando vc pode esvaziar esta cache de acordo com um tempo pré-determinado.

Parece interessante, mas está me parecendo o que já tenho no momento dando problema, não saquei a questão do cache que tu falou.

skill_ufmt

mister__m:
[
Cara, acho que você está meio perdido. Uma sequence não está relacionada a campo nenhum no Oracle. Seu código é que relaciona.

Então você tem que conseguir usar criar n sequences ou até usar a mesma pros dois campos.

Completamente perdido hehe
Vo ver isso amanha, essa questão de várias sequences e volto a postar aqui, ok?

F

Olá,

Nao tinha visto este post antes. Vamos la ver se ajuda em algo.

Skill teu problema é a conhecida sequence in parent pelos DBA’s, existem algumas solucoes. O pessoal ja mostrou algumas, mas eu particularmente quando precisei usar isso fiz da seguinte maneira. Essa solucao é adequada se tu nao precisa ter uma sequencia uniforme dos codigos, ou seja, nao tenha problema em falhar algum codigo.

10 1 10 2 10 4 11 3 11 7

Nesse caso tu pode criar o registro vazio no incio da transacao, locar ele com select for update e depois ir fazendo o update no mesmo.
Claro isso cheira meio a uma gambiarra, mas para o problema resolve e nao da dor de cabeca.

Utilizar sequence é uma boa pedida, eu so nao entendi porque tu fez tanta confusao sobre o uso dela.

Outra coisa que notei nos topicos anteriores foi tu falando que o Oracle loca a tabela. Isso nao é verdade o Oracle loca somente os registros alterados. Pode ter certeza que se a aplicacao ta parando quando tem um unico registro locado de duas uma, ou estao tentando alterar o registro locado (nao a tabela, esta nao é locada a menos que tu force isso) ou o servidor nao ta aguentando as requisicoes e ta colocando processos em fila.

Sinceramente é meio chatinho de arrumar isso dependendo de como tua aplicacao foi feita, mas nada impossivel.

Qualquer coisa poste ai.

]['s

F

skill_ufmt:
mister__m:
[
Cara, acho que você está meio perdido. Uma sequence não está relacionada a campo nenhum no Oracle. Seu código é que relaciona.

Então você tem que conseguir usar criar n sequences ou até usar a mesma pros dois campos.

Completamente perdido hehe
Vo ver isso amanha, essa questão de várias sequences e volto a postar aqui, ok?

Skill,

Imagine uma sequence como uma grande tabela que armazena valores sequenciais.

1 2 3 ... 100000000000000000

Agora imagina o SELECT

O que ele faz, retorna o proximo valor “liberado” na tabela, seria semelhante com isso.
Imaginando que tu tenha uma tabela auxiliar pra armazenar codigos sequenciais.

A diferenca da sequence é que tu nao consegue usar um codigo que ja foi soliciatado com o NEXTVAL. O maximo que tu consegue saber é o codigo atual usando CURRVAL.

Para inserir em uma tabela com usando sequence seria ± assim.

CREATE TABLE teste (codigo NUMBER ,descricao VARCHAR2(200))

Deve ter erro de sintaxe, mas a idéia de como fazer é essa.

]['s

skill_ufmt

fabgp2001:

Qualquer coisa poste ai.

]['s

Fábio, respondendo a seus dois post, ok?

Bom, as coisas não estavm sendo feitas por SEQUENCES, quem gerenciava era a maldita classe com um select max comum.

Quando descobri tal fato, me dirigi ao gerente e o mesmo não acreditou que as coisas estavam nesse nível, mas enfim, discutimos e tiveram que por as tais sequences no oracle, isso afetou a minha aplicação e mais umas 3 que estavam entrando em produção nas quais detectei o mesmo problema.

É dificil acreditar, mas foi isso que aconteceu.

Foram feitos todos os sequences nas tabelas e todas estão funcionando perfeitamente, com exceção desta minha tabela principal que tem as chaves compostas.

O meu forte não é BD, só sei oque não se pode fazer hehe e creio que deveriam ter um DBA para isso, mas enfim.

Pelo que foi me passado, na vrdade rolou uma reunião com o pessoal que tem experiência dentro da empresa, e rolaram idéias, a maioria já citadas aqui.

A soluçaõ que tava discutindo com o mister_m, e acho que essa mesma que vc postou, foi desconsireda, porque segundo eles, a sequence não poderia ser usada em chave composta.

O mister_m me disse que pode, então vo ver isso amanha.

Quanto ao lock de tabela, realmente estava me referindo a lock naquele registro em questão que estaria seno usado, neste estaria tudo locado inclusive seus relacionamentos, certo? os outros 2999 não poderiam operar nada nele, certo?

Dai surgiu a idéia de usar a tabela auxiliar, e fazer lock nela em vez de na minha tabela principal, inicial era uma trigger qeu faria, mas o cliente vetou isso, então eu teria que controlar isso via aplicação, dai caimos no mesmo fato, por que a aplicação gerenciaria isso? e se me ocorre uma falha igual a que ocorreu, quem me garante a unicidade da chave? isso usando um select max, se fosse um equence daria certo, mas ai novamete teria a idéia de que a sequence não funcionaria porque a tabela auxiliar tbm seria de dois campos, dai esta idéia minguo novamente.

Quanto a usar o for update para dar lock no registro, era a solução melhor, só que novamente caiu em discussão que se eu tivesse 3000, 2999 em lock, e por acaso desse problema na app, seria feito um rollback, mas isso liberaria os 2999 caras, e ai boom n app novamente ehhe.
Essa informação foi desmentida por um amigo meu depois, segundo ele seria liberado somente o próximo cara da fila mesmo usando um for update.

Acho que ai surgiria o problema dessa fila de caras esperando a liberação do registro, isso me daria um belo problema tbm, ou não? sem dizer que o sistema é web, e os usuários ficariam loucos hehe talvez até um timeout ocorresse, ou vários refresh(F5), o que acho tbm ocorreria mais fila :slight_smile:

Dai surgiu a idéia de seprarmos em uma classe o for update, , onde eu daria lock, incrementaria o valor, inseria na tabela, e libera a mesma, a cda acesso eu teria um valor novo, e seria uma operação teoricamente mais rápida de ser feita.

Acho que agora explanei mais como ta a coisa, talvez eu esteja aumenta a complexidade da coisa, mas é por ae.

mister_m

Só pra deixar bem claro: sequences são como contadores independentes dentro do banco, que são incrementados quando alguém pede o próximo valor, funcionando fora do contexto transacional, ou, dependendo da forma que você enxerga, num contexto transacional completamente isolado do atual e sem nunca dar rollback.

Já que sequences são contadores, não tem nada a ver com as tabelas e podem ser usados da forma que quisermos. Normalmente, usamos para incrementar sequencialmente o valor de uma coluna em uma tabela, mas nada impede outros usos ou o uso para mais de uma coluna de uma tabela.

Em suma, a menos que te proíbam de usar sequences para resolver o seu problema ou exista alguma limitação de negócio, seja feliz :slight_smile:

skill_ufmt

mister__m:

Em suma, a menos que te proíbam de usar sequences para resolver o seu problema ou exista alguma limitação de negócio, seja feliz :-)

Cara, vo ver esse negócio amanha cedo, se tu tiver certo, vo rezar pra que sua vida seja farta, longa e com muita mulherada hehhe

PS: vi que trampa na suma, conhece o Claudio Miranda? conheci ele por aqui nos eventos do CAJU :slight_smile:

mister_m

skill_ufmt:
mister__m:

Em suma, a menos que te proíbam de usar sequences para resolver o seu problema ou exista alguma limitação de negócio, seja feliz :-)

Cara, vo ver esse negócio amanha cedo, se tu tiver certo, vo rezar pra que sua vida seja farta, longa e com muita mulherada hehhe

Se eu não tiver certo com respeito a sequences não estarem ligadas/limitadas a colunas de tabelas, vou precisar é de terapia pra entender como todos os sistemas que fiz que usam Oracle passaram do primeiro INSERT… :mrgreen:

Além de trabalhar na Summa, ele também faz parte da organização do SouJava. :slight_smile:

skill_ufmt

mister__m:

Se eu não tiver certo com respeito a sequences não estarem ligadas/limitadas a colunas de tabelas, vou precisar é de terapia pra entender como todos os sistemas que fiz que usam Oracle passaram do primeiro INSERT… :mrgreen:

Além de trabalhar na Summa, ele também faz parte da organização do SouJava. :-)

Vo considerar problema resolvido então hehehe

É também, esqueci desse ponto :slight_smile:
Troquei bastante idéia com ele, ele é daqui de Cuiabá, gente boa, massa ele num restaurante por kg aqui, tavam passando, R$ 0,10 centavos por prato, cara ele apronto um alvoroço, tivemos que filmar a cena toda ehehe, ainda ganhamos desconto depois pra num denunciar kkk, só o Claudio mesmo.

Rafael_Nunes

Eu nao vejo motivo para sequence em chave composta nao funcionar, eu ja fiz alguns testes com isso e nao tive problema nenhum.
Afinal ela te retorna dois valores sequenciais unicos, a cada requisiçao.

C
É simples,
  o seu problema está ligado com o trasaction isolation level, ou seja, as outras transações  lêm do banco o que está 'comitado', quando vc gera uma nova chave atravéz do SELECT MAX vc precisa guardar este valor em algum lugar fora do banco onde as outras transações ( threads diferentes ) tenham acesso. É o mesmo que dizer "no banco está como 100 , mas já tem outras transações trabalhando com 105" , portanto nossa próxima chave é 106. Note que se transações anteriores falharem vc pode ter uma lacuna na sequencia da chave intermediaria, ou seja,

10,1
10,2
10,4
10,6
E isto só funciona de verdade se somente a aplicação Java tiver acesso de INSERT nesta tabela.

F

Olá,

Eu so nao consegui entender ainda o porque dos lock e qual o motivo teria pra fazer uma tabela auxiliar, iria dar o mesmo problema.
Exemplo:

Eu estou incluindo um novo registro no banco. Até que eu commit essa minha insercao este registro nao existe para os demais, nesse caso o Oracle nao da lock de nada.
Se eu vou fazer update em um registro, os outros 1 milhao de usuarios irao ver uma foto deste registro antes de eu comecar a alteracao, e apos eu dar commit todos comecarao e ver o que foi alterado.
Em nenhum desses casos o Oracle trava consulta aos registros, agora se o problema é que dois usuarios nao conseguem alterar o mesmo registro ao mesmo tempo, obvio que nao vai dar e obvio que com tabela auxiliar irá ocorrer a mesma coisa.

Estou falando isso com o Oracle funcionando de maneira normal, a nao ser que alguem mudou as configuracoes das transacoes (o que é possivel), mas nesse caso voces deveriam descobrir quem fez isso e dar um premio pra pessoa.

]['s

skill_ufmt

Claudio, Mister_m,

Ainda não consegui usar as sequences para me trazer uma sequencia do segundo campo, vejam porque:

10, 1
10, 2
10, 4
11,1
11,2
11,5
12,2
12,3

Eu não consigo reiniciar a sequence, veja que a cada sequencia aumentada no campo 1, o campo 2 reinicia as sequências, é isso que ta me matando.

Sequence não vai dar certo neste caso, certo?

Lembrando, sem trigger, procedures, com isso daria pra fazer.

Fábio,

A idéia da tabela auxiliar, era que locariamos somente ela, tu tacerto, vai correr o mesmo problema, mas é melhor locar uma tabela apenas sem relacionamentos, do que a minha tabela princiapl onde exitem n relacionamentos, o sistema ia parar total, enquanto na auxiliar o problema seria somente gerenciar essa fila de locks

mister_m

skill_ufmt:
Ainda não consegui usar as sequences para me trazer uma sequencia do segundo campo, vejam porque:

10, 1
10, 2
10, 4
11,1
11,2
11,5
12,2
12,3

Eu não consigo reiniciar a sequence, veja que a cada sequencia aumentada no campo 1, o campo 2 reinicia as sequências, é isso que ta me matando.

As sequences são totalmente controladas por você, skill, e se elas estão sendo reiniciadas é porque seu código faz isso. Como você está usando as sequences neste caso?

skill_ufmt

Então mister, o gerenciamento era feito por uma SELECT MAX, mas como disse isso me ferro agora geral, preciso de uma solução para gerenciar isso, essas reinicialização de sequencias.

Nas outras tabelas como são uma chave só funciona blz o sequence do oracle.
A propósito, fiz os teste e realmente posso ter duas sequences, na mesma tabela, mas ela semrpe me retornam o mesmo valor nas duas fazendo daquele jeito:

select sequence1, sequence2 from dual

O que não ta me servindo.

Se que o problema é a peça aqui que não manja de DBA ehehe mas deve ter sim como fazer.

Me permite chegar ao nível de pedir que coloque um exemplo da sua sequence onde você precisa fazer isso?
como é que eu faço minha sequence1 retornar o primeiro campo, e o sequence2 retornar somente para o segundo campo, isso lembrando que a cada nextval no campo1, preciso reiniciar a sequence no campo 2?

mister_m

Peraí, você disse antes nessa thread que não precisava reiniciar o segundo campo, que ele somente precisava aumentar a cada select. Mudou isso agora?

skill_ufmt

mister__m:

Peraí, você disse antes nessa thread que não precisava reiniciar o segundo campo, que ele somente precisava aumentar a cada select. Mudou isso agora?

Se eu disse, me perdoe, mas o meu problema é justamente ter que reiniciar o segundo campo :smiley:

mister_m

Diga um caso de negócio que justifique isso :slight_smile:

skill_ufmt

Cara hehe, nem me fale nada kkk, to p demais com os ana…

Meu problema todo gira em torno disso:

Vamso supor que eu tenha um processo criminal em que o cara vai ser julgado por homicidio, furto, estupro, esse processo é inserido nessa chave composta assim por exemplo: 10 , 2 onde esse primeiro campo seria o número do processo, e o segundo, uma sequencia deste processo.

Acontece que esse processo pode ser repartido na justiça para se julgar os casos em separado, ou seja, vou ter 3 novos processos um para cada caso, onde oque será incrementado é apenas a sequenciado segundo campo, ficando assim:

10,2 normal
10,3 estupro
10,4 furto
10,5 homicio

isso acontece repetidas vezes e para vários processos dai surgem o problema de ter que reinicializar esta sequencia, na verdade eu preciso sempre de um numero maior ao que já está lá no processo normal.

10,2 normal
10,3 estupro
10,4 furto
10,5 homicio
11,3 normal
11,4 duplo-homicido
11,5 latrocinio
13,5 normal
13,6 roubo
13,7 estelionato

Definiram isso na versão 1, e por incrinvel qeu pareça, foi bugar somente agora no meu último dia kkk
Sou sortudo pacas :slight_smile:

skill_ufmt

Tava vendo o seguinte código:

insert into s_dept([color=red]id[/color],name,region_id)
values ([color=red]s_dept_id.NEXTVAL[/color],‘FINANCE’,2);

há como usar o sequence para o segundo ID: ex.

insert into s_dept(id,name,[color=red]region_id[/color])
values (2,‘FINANCE’,[color=red]s_dept_id.NEXTVAL[/color]);

ou ainda?

insert into s_dept([color=red]id[/color],name,[color=red]region_id[/color])
values ([color=red]s_dept_id.NEXTVAL[/color],‘FINANCE’,[color=red]s_dept_id.NEXTVAL[/color]);

louds

Os DBAs e analistas dai são fraquinhos em… Hoje em dia não usar surrogate key é dose. Pelo que eu entendi eles estão usando uma natural key como primary key, isso é burrada das grandes.

O correto seria manter uma coluna só com a surrogate key, criar 1 FK para a atual primeira coluna da PK e criar uma chave natural com esse sequênciamento de processos. Simples como executar o seguinte sql…

update t set t.seq = (select isnull(max(*), 0)+1 from t as tt where t.fk = tt.fk and t.pk > tt.pk)
Rafael_Nunes

Você não pode simplesmente criar um método que faça essa distribuição de processo?
Por exemplo um método que receba a sequência do processo e a quantidade em quantos será dividido, e retorne a sequência pra vc inserir?

S

Fala skill_ufmt.

Cara, em alguns momentos (Emergência) é necessário fazer algumas gambiarras.
Não posso ajudar muito quanto a java, pois ainda não tenho conhecimento muito elevado, mas trabalhamos com oracle aqui.

Quando eu falo de gambiarra eu falo em criar uma procedure ou function e ir direto no banco fazer o que vc precisa.
Usando procedures e functions vc pode utilizar tudo que o oracle pode te oferecer.

numa procedure ou function vc pode utilizar, por exemplo, o AUTONOMOUS_TRANSACTION, e assim já se preocupar um pouco menos com locks e etc.

skill_ufmt

louds:

update t set t.seq = (select isnull(max(*), 0)+1 from t as tt where t.fk = tt.fk and t.pk > tt.pk)

Pois é, louds, grande CO, isso veio do começo das aplicações java aqui, se não me engano este foi o primeiro sistema desenvolvido aqui e o pessoal tava migrande de outras linguagens ou iniciando, tem cada merda no código que nem te conto heheh
Mais é inviável refazer a coisa toda, e o cliente também não adimite isso :frowning:
Naquela éopoca, acredito que nem DBA tinha como tbm não tem, como você está vendo, eu que to correndo pra ver se arrumo uam solução, hoje sou dba, analista, desenvolvedor e etc hehe

skill_ufmt

Rafael Nunes:
Você não pode simplesmente criar um método que faça essa distribuição de processo?
Por exemplo um método que receba a sequência do processo e a quantidade em quantos será dividido, e retorne a sequência pra vc inserir?

Rafael, meu problema não é bem esse, isso faz tranquilo, o negócio é que quem tem que gerenciar essa chaves para mim é o banco, se eu deixar minha aplicação gerenciar as chaves, vai dar bug, que é o que está correndo agora.

Pode ocorrer de dois usuários pegar chaves iguais, e ai o bicho pega meu amigo hehe

skill_ufmt

Tudo bom Salgado?

O cliente proibe uso de trigger e procedures, acredito que seja isso que você esteja falando, certo?

Há restrições nos projetos desse cliente quanto ao uso disso, pelo que foi me passado isso é bem pesado para o banco fazer, e imagina 10000 ao mesmo tempo, 30000, 100000 …
Não sei te falar certamente o motivo, só sei que existe essa restrição.

S

Cara, acho que o Oracle aguenta.
Mas quem manda é o cliente.

Se eu tiver alguma ideia volto a postar.

Abraço e boa sorte

mister_m

skill_ufmt:
Acontece que esse processo pode ser repartido na justiça para se julgar os casos em separado, ou seja, vou ter 3 novos processos um para cada caso, onde oque será incrementado é apenas a sequenciado segundo campo

Isso acontece repetidas vezes e para vários processos dai surgem o problema de ter que reinicializar esta sequencia, na verdade eu preciso sempre de um numero maior ao que já está lá no processo normal.

Eu entendi sua explicação, mas daí ao segundo número ter que ser zerado com base no primeiro, não faz sentido ainda.

skill_ufmt

mister__m:

Eu entendi sua explicação, mas daí ao segundo número ter que ser zerado com base no primeiro, não faz sentido ainda.

ser zerado a cada campo 1 novo?

Tu ta dizendo o seguinte, que eu poderia mudar o campo1, mas continuar a sequencia do campo dois, certo? dai eu teria:

10,2
10,3
10,4
11,5
11,6
11,7

Caras, como já cai neste buraco mesmo, como vocês costumam fazer esse tipo coisa, nunca usando chave compostas? usam uma chave pk e a composta como natural, como alguém citou aqui? enfim, qual a melhor maneira de se não usar algo assim, quando se tme um caso desse?

mister_m

skill_ufmt:
Tu ta dizendo o seguinte, que eu poderia mudar o campo1, mas continuar a sequencia do campo dois, certo? dai eu teria:

10,2
10,3
10,4
11,5
11,6
11,7

Exato. Serve?

skill_ufmt:
Caras, como já cai neste buraco mesmo, como vocês costumam fazer esse tipo coisa, nunca usando chave compostas? usam uma chave pk e a composta como natural, como alguém citou aqui? enfim, qual a melhor maneira de se não usar algo assim, quando se tme um caso desse?

Tem que usar uma chave surrogate. Jamais use uma chave natural como chave primária.

E

Se tu relamente precisa reiniciar o segundo campo não poderia fazer primeiro um insert com o campo zerado e depois um update do select max, na mesma transação?

Dependendo da configuração do banco e da aplicação até poderia dar duplicate key no primeiro insert, a não ser que o insert de um lock de tabela…

Acho que uma solução parecida já tinha sido mencionada no início da thread…

skill_ufmt

eagnes:
Se tu relamente precisa reiniciar o segundo campo não poderia fazer primeiro um insert com o campo zerado e depois um update do select max, na mesma transação?

Dependendo da configuração do banco e da aplicação até poderia dar duplicate key no primeiro insert, a não ser que o insert de um lock de tabela…

Acho que uma solução parecida já tinha sido mencionada no início da thread…

Sim, mensionei isso e outras pessoas também.
Agradeço pela atenção.

Estamos ainda resolvendo, mas em suma, os analistas estão vendo o impacto ou possibilidade de mudar a chave para que possa continuar em sequencia normal, assim resolveriamos a coisa toda facilmente.

Grato, pelas idéias, posto aqui qualquer coisa.

Luca

Olá

O que eu não consegui entender neste tópico foi porque depois de tantos indicarem qual seria a solução mais adequada o Skill insiste tanto no fato do cliente não querer?

Será que ela paga para ter merda? Se agora está claro que foi cometido um erro grave que está comprometendo o desempenho normal do sistema não vejo como manter a coisa errada. Amanhã em uma futura exansão ou uma simples manutenção o problema vai reaparecer e não sei se o louds, fabio,mister_m e outros estarão disponíveis para lhe ensinar o caminho das pedras.

Para tudo, se reune com o cliente e diz que é importante fazer tal modificação. Mesmo que o cliente tenha outras aplicações acessando a mesma base de dados acho que deixar como está é mirar a espingarda para dar um futuro tiro no pé.

[]s
Luca

fmeyer

skill_ufmt, Boa Madrugada …

Estava analisando este post desde o inicio e venho aqui fortalecer o que o LUCA frizou.

Primeiro, O BD Oracle foi projetado para usar Stored Procedures, Triggers e Functions, assim como diversos SGBD, imagina se a oracle iria colocar um recurso deste com tanto poder e funcionalidade dentro de um sistema CRITICO, posso te afirmar que em um sistema que ajudei a desenvolver quando era estágiario, Tinhamos 38 estações de coleta de dados e cada uma fazia uma inserção de 15 a 20 registros a cada 5 segundos em uma base oracle usando Stored Procedures, e o desempenho era exepcional.

Segundo, Quando eu recebo uns projetos assim eu passo uma semana analisando o código, e com certeza ao ver a “ZONA” que estava a versão de produção sugeriria um refactor, ou ate mesmo iniciar o projeto do zero, Caso o cliente neguasse este artificio eu simplismente recusaria o trabalho, e olha que não esta tao facil assim de arrumar emprego hj em dia.

Terceiro, Seje sincero com o cliente, fale pra ele, "XXXX, Do jeito que esta a aplicação/Banco Não é viavel uma manuntenção … ". Na minha ex empresa fui contratado para fazer manutenção em sistemas, era um call center uma loucura que só ::: cliente interno e externo te ligando o dia todo pq apareceu um ok na tela, e te digo eu pulei fora … dentro de algumas estruturas de trabalho voce como profissional esta apenas “perdendo tempo” não digo que o dinheiro que voce esteja ganhando não seja importante, mas pensar no desgaste e cobrança, por que querendo ou não agora um dos responsaveis pelo sistema é voce, e se algo de errado ocorrer com certeza eles vão chiar e se pelo que eu conheço alguns clientes podem ate te processar ( se voce for consultor ).

Concordo que o cliente é meio “cabeça dura” mas voce como analista deveria colocar as “ideias” na cabeça dele, por que com certeza ele não entendo bulhufas de aplicação (tomo isso como verdade por ele ter falado que Stored Procedures deixam o banco lento). Então chego a conclusão que o errado não é o cliente, mas sim os profissionais que estão em volta (analistas, desenvolvedores, DBA’s) que se sujeitaram a fazer um serviço porco e que no ultimo dia foi dar erro.

Tem varios pontos que nem toquei mas gostaria de deixar minhas palavras.
Seja mais critico da proxima vez.

Boa sorte…

skill_ufmt

Pessoal é o sguinte,

Não estou condizente com a coisa da forma de que está, desde o começo da versão 2, não só por este problema mas por muuuuitos outros que daria uns 30 posts se fosse colocar aqui.

A questão com o cliente é simples e complexa :smiley:
Eles tem muitas aplicações rodando ao mesmo tempo, muito fluxo mesmo, e eles decidiram que não é permitido usar trigger, procedure, o porque eu não sei, só sei que o cliente manda, certo? e não adianta tentar argumentar, ele num quer e pronto acabo, vo matar ele? se bem que seria bom matar alguns políticos :smiley:
O cliente é Governo, tudo lá ´uma merda e uma burocracia para ser feito.
Não permitem frameworks e blás blás, só servlet, jsp e alguns padões que eles definiram a uns trocentos anos atrás e relutam em não mudá-los, mas uma vez, fazer o que?

Mas enfim, certamente contente eu não estou, mas pelo menos até o próximo mês é o que me há :slight_smile:

dsiviotti

Agora está explicado.

chaos

Bem, tratando de governo, eu já estive do outro lado, e sei que geralmente a pessoa que faz essa “exigência” só faz isso pq “ouviu dizer” que não pode ter. Ai ele bate firme nessa exigencia.

Mas é só olhar o edital de licitação e ver se está EXPPLICITAMENTE PROIBIDO o uso de triggers e SP no desenvolvimento, e ainda assim eu te digo que de todas as implementações que eu vi no Governo, 100% (isso mesmo TODAS) foram feitas de um jeito diferente do solicitado, por conta da empresa, que assim que falou pro chefe (o cara que manda, mesmo sem não entender nada, até sem ter o nível médio, as vezes nem o fundamental) que fizeram daquele jeito pq era o único, senão ia dar pau, que não iriam entregar um sistema errado só pq pediram errado, etc, ai o cara releva esse “pequeno desvio” entre especificação e implementação.

E olha que também nunca vi Governo aplicando multa pra contrato atrasado ou entregue de forma diferente da solicitada…

Mas quem sabe vc achou a parte do governo que funciona de verdade, com chefes, digo, gerentes e líderes, que entendem do assunto…

Criado 19 de abril de 2005
Ultima resposta 25 de abr. de 2005
Respostas 65
Participantes 14