Evitar colisões - PHP - Portugal-a-Programar
Tou com um problema que é:
Tenho de fazer um instert na bd verificando o ultimo id e somar 1 a esse registo, imaginando que o ultimo é 1000 e o proximo é 1001.
Até ai td bm faço lock á tabela e funciona. O problema é que isso influência a performance e não queria isso.
Alguém tem alguma sugestão de como o fazer, perdendo o mínimo de performance e evitar colisões e repetição de dados?
Posso utilizar mais do que 1 autoincrement por tabela? É que ja tem 1.
É do genero o user pode colocar um id manualmente ou utilizar o proximo livre.
No software, nao tenho uma tabela para clientes outra para fornecedores, tenho uma para os dois, porque os campos sao os mesmos.
Um cliente pode ser fornecedor também e podem ter códigos diferentes.
Existe um campo id, codigo-cliente e codigo-fornecedor.
O codigo-cliente ou fornecedor é colocado pelo user ou entao é o proximo codigo vazio.
O id ja ocupa a posição de primary key e auto increment.
continua a ser irrelevante ... qual o problema de usar o auto incrementado ?
Ao colocar auto increment no codigo cliente dá erro pk o id é auto increment
Edited March 31, 2014 by blacksnake
mas não respondeste à pergunta : qual o problema de usar o id auto incrementado ?
O id já é auto incrementado, não existe problema pelo contrário. O que pretendo é qque seja atribuido um valor sequencial ao campo codigo-cliente tal como auto incremente, mas isso tem de ser por código. O problema é como fazer sem haver repetições. Visto que n pode ser unique porque tbm depende do userid. 1 userid so pode ter 1 codigo cliente.
Imagina user id 1 tem o cliente 1 mas o userid 50 tbm tem o id 1 por isso n pode ser unique.
O problema é como evitar repetições caso por ventura insram dados ao mesmo tempo.
Fazer isso sem prejudicar o ACID da bd com a melhor performance possivel.
Imagina o cenário, uma bd multi empresa, que ambas têm clientes, utilizam a mesma tabela mas a lista de clientes de cada empresa começa no numero 1.
se existe mesmo essa necessidade (que para mim não faz sentido ...) usa um registo com o último id inserido em conjunto com um stored procedure que irá ler esse valor e incrementá-lo, tudo no mesmo passo.
Como farias, dizendo "para mim nao faz sentido", sabendo que sao multiplas empresas, e utilizam ambos a mesma tabela? O utilizador tem de criar o codigo de cliente que quiser, nao pode ser automático visto que os clientes podem ter ja um numero definido antes de utilizarem esta aplicação, logo ao migrar para este app têm de manter os codigos de cliente anteriores.
faz o que o auto_increment faz:
usa um registo com o próximo id a ser inserido. agora tens as seguintes situações:
- se o cliente não inseriu nenhum número, então usa o número no registo e incrementa este
- se o cliente inseriu o número, verifica se a relação cliente/número do registo já existe
- se sim : pede outro
- se não, verifica se é o mesmo do registo
- se sim, incrementa o valor do registo e cria o registo com o número pedido
- se não, basta criar o registo com o número pedido
Pois mas assim garante o id certo?
Não existe possibilidade de haver registos duplicados?
Pode haver duas pessoas a inserir o registo ao mesmo tempo e retornar valores iguais, isso é o que não quero que aconteça.
A forma que dizes não vejo mts garantias sem lock da tabela.
só necessitas de fazer lock na tabela com o registo com o próximo ID, o que é muito melhor do que fazer lock da tabela de clientes/fornecedores pelas seguintes razões :
- a tabela de clientes/fornecedores continua a ser acessível sem problemas
- só necessitas de fazer lock na criação de um novo registo
- a tabela de próximo ID só vai ter n_clientes_serviço (isto se no próprio registo tiveres os ID's de próximo cliente e próximo fornecedor)
- se usares stored procedures para fazer todo o processo é fácil usar em código ...
Obridao vou testar 🙂
Qual a vossa opinião sobre esta forma http://stackoverflow.com/questions/805808/emulating-a-transaction-safe-sequence-in-mysql