MySQL - O incremento automático não aumenta sequencialmente se a última linha foi excluída

8

Eu tenho uma tabela que contém um ID de chave primária incrementado automaticamente. Se eu excluir a última linha (ID mais alta, por exemplo, ID de exemplo = 6) e inserir uma nova linha, o novo ID começará em 7. Qual parâmetro eu tenho que alterar para que a chave primária comece em 6?

CREATE TABLE animals (
 id MEDIUMINT NOT NULL AUTO_INCREMENT,
 name CHAR(30) NOT NULL,
 PRIMARY KEY (id)
) ENGINE=MyISAM;

INSERT INTO animals (name) VALUES
('dog'),('cat'),('penguin'),
('lax'),('whale'),('ostrich');

Resultado:
nome do id
1 cachorro
2 gato
3 pinguim
4 lax
5 baleia
6 avestruz

DELETE FROM animals WHERE id = 6;
INSERT INTO animals (name) VALUES
('x');

Resultado:
id nome
1 cachorro
2 gato
3 pinguim
4 lax
5 baleia
7 x

Obrigado pelo conselho.

Giordano
fonte
E daí se houver lacunas? (que podem aparecer devido a várias outras razões, não apenas apagando linhas)
ypercubeᵀᴹ
o que você gostaria de fazer se a exclusão acontecer após alguma inserção? você vai reutilizar essa lacuna? é sim, então não acho que a identidade seja o tipo certo para essa coluna. Ele oferece a você a oportunidade de não se preocupar com valores exclusivos nessa coluna. se você deseja manter os valores em sequência, pode usar apenas o tipo de dados regular do tipo INT / BIGINT. encontrar / reutilizar / redefinir valores para cada lacuna ausente é como perder o objetivo da Propriedade de identidade.
Anup Shah
@giordano Por que você quer ser um maníaco por AUTO_INCREMENT PRIMARY KEY? lidar com isso, há também um "gap" em seus dados da tabela se você atualizar / excluir devido à fragmentação ..
Raymond Nijland
Eu fiz uma investigação sobre valores contínuos de incremento automático para o SQL Server há algum tempo: sqlity.net/pt/792/the-gap-in-the-identity-value-sequence - Embora não seja o MySQL, os mecanismos subjacentes são os mesmos , para que você obtenha resultados semelhantes. Em suma, você não pode evitar lacunas nas seqüências geradas automaticamente.
Sebastian Meine 15/10
@ypercube: obrigado por respostas. De fato, a diferença que obtive de outro exemplo mais complexo, mas eu queria mostrar um exemplo mínimo. O exemplo real foi (1) alterar a data de validade de uma linha (por exemplo, de uma tabela de produtos) devido à alteração de um atributo e (2) adicionar o novo produto com o mesmo código do produto, novo atributo, nova data efetiva e validade aberta encontro. O que aconteceu foi que a nova chave primária não foi incrementada automaticamente com +1, mas +2. Obviamente, na etapa (1) ou (2), há um incremento automático invisível. Gostaria de saber qual é a outra razão para as lacunas.
Giordano

Respostas:

12

Isso ocorre por design - todos os DBMS agem assim com colunas de incremento automático.

Se não a integridade referencial externa, poderia ser danificada. Para um exemplo simples disso, imagine que você está armazenando URLs para um serviço de encurtamento usando uma coluna de incremento automático como chave. Você ainda não sabe se o URL encurtado já foi fornecido a alguém, e o banco de dados certamente não, portanto, a reutilização da ID 1234 pode resultar na avó pobre de alguém visitando somenastypornsite.xxx em vez de loverlyknitting.org quando ela clicar em http: / /shortthi.ng/1234 em um email antigo, em vez de receber a mensagem "desculpe, mas este link não existe mais em nossos registros".

Além disso, se você redefinir o incremento após excluir o último item, você também estará realizando todo o trabalho (ou espera que o banco de dados) renumere tudo após o 5º item de 5 milhões quando o 5º item for removido? completo com alterações em outras tabelas nas quais existem restrições de chave estrangeira apontando para a coluna de incremento? Esse trabalho extra pode ficar muito caro em termos de IO.

Se você fazer redefinir o ponto de incremento depois de eliminar o último item, não ser muito, muito cuidadoso de seus níveis de isolamento de transação: Você pode redefini-la apenas como uma outra operação faz uso do valor, levando a erros (ou pior, falhas silenciosas), a menos você garante que sua ação seja totalmente 100% isolada.

Geralmente recomendo que as pessoas que trabalham com bancos de dados leiam "SQL Antipatterns", que possui um capítulo sobre esse assunto chamado "Psuedo-Key Neat Freaks" (que aborda o assunto de uma maneira mais amigável do que o título do capítulo pode implicar para alguns!). Essencialmente, se o valor tiver significado além de ser uma chave (ou, no máximo, transportar informações sobre pedidos de inserção), provavelmente não deve ser uma coluna de incremento automático e se não tiver significado além de ser uma chave (ou, no máximo, levar ordem de inserção) informações), então as lacunas não devem importar.

David Spillett
fonte
Obrigado por esta explicação. Vejo que tenho que me aprofundar no conceito-chave. Gostaria de saber como o mecanismo de incremento automático funciona, pois observei também lacunas na chave primária quando não a excluí, mas alterei (atualizei) uma linha e adicionei uma nova. Definitivamente, o que não vou fazer é alterar manualmente o valor do incremento automático.
Giordano
Em relação a "pesquisar mais profundamente o conceito-chave", recomendo vivamente o livro SQL Antipatterns de Bill Karwin - ele cobre este e vários outros tópicos comuns (e não tão comuns), falando sobre como errar, por que o erro comum Os métodos podem causar problemas, como corrigi-los e quando o método "errado" pode ser bom de usar (ou a única opção) de qualquer maneira, de maneira concisa, mas acessível.
precisa
Spillet: Obrigado por esta indicação. Eu li agora e foi muito útil. No entanto, eu não entendo por que InnoDB e MyISAM contar de maneira diferente: dba.stackexchange.com/questions/51883/...
Giordano
0

Você pode redefinir o valor de incremento automático usando o seguinte:

ALTER TABLE MyTable AUTO_INCREMENT = 1234;

Você precisaria determinar o valor máximo presente na tabela e adicionar 1 a esse valor para usar na instrução acima.

Max Vernon
fonte
Má idéia, isso impedirá que sua tabela seja lida ou escrita em "quase todas" versões do MySQL. O MySQL 5.6 pode executar um LIVE ALTER, mas às vezes também precisa bloquear a tabela.
Raymond Nijland 15/10
2
@RaymondNijland Eu não acho que a fechadura duraria o suficiente para alguém perceber.
ypercubeᵀᴹ
@ Max, Raymond, ypercube: Obrigado pela resposta. Vou evitar fazer esse tipo de mudança.
Giordano