Temos uma tabela MySQL que possui um campo de incremento automático definido como INT (11). Esta tabela praticamente armazena uma lista de trabalhos que estão sendo executados em um aplicativo. A qualquer momento durante a vida útil do aplicativo, a tabela pode conter milhares de entradas ou ficar completamente vazia (ou seja, tudo terminou).
O campo não tem chave estrangeira para mais nada.
O incremento automático parece se redefinir aleatoriamente para zero, embora nunca tenhamos sido capazes de interceptar a redefinição.
O problema se torna evidente porque vemos o campo de incremento automático chegar a, digamos, 600.000 registros ou mais e, pouco tempo depois, o campo de incremento automático parece estar em execução nos 1000s baixos.
É quase como se o incremento automático se redefinisse se a tabela estivesse vazia.
Isso é possível e, se for, como faço para desativá-lo ou alterar a maneira como ele é redefinido?
Se não for, alguém tem uma explicação de por que pode estar fazendo isso?
Obrigado!
fonte
Respostas:
http://dev.mysql.com/doc/refman/4.1/en/innodb-auto-increment-handling.html
Por isso, quando o serviço (ou servidor) reiniciar, acontecerá o seguinte:
Portanto, em inglês simples, após o início do serviço MySQL, ele não tem idéia do valor do incremento automático para sua tabela. Portanto, quando você insere uma linha pela primeira vez, ela encontra o valor máximo do campo que usa incremento automático, adiciona 1 a esse valor e usa o valor resultante. Se não houver linhas, começará em 1.
Isso foi um problema para nós, pois estávamos usando o recurso de incremento automático da tabela e do mysql para gerenciar ordenadamente os IDs em um ambiente multithread em que os usuários estavam sendo redirecionados para um site de pagamento de terceiros. Portanto, tivemos que garantir que o ID que o terceiro recebesse e nos enviasse de volta fosse único e continuasse assim (e, é claro, existe a possibilidade de o usuário cancelar a transação após o redirecionamento).
Então, estávamos criando uma linha, obtendo o valor de incremento automático gerado, excluindo a linha para manter a tabela limpa e encaminhando o valor para o site de pagamento. O que acabamos fazendo para corrigir o problema da maneira como o InnoDB lida com os valores de IA foi o seguinte:
Isso sempre mantém o transactionId mais recente gerado como uma linha na tabela, sem explodir desnecessariamente a tabela.
Espero que ajude qualquer pessoa que possa se deparar com isso.
Editar (2018-04-18) :
Como Finesse mencionado abaixo, parece que o comportamento disso foi modificado no MySQL 8.0+.
https://dev.mysql.com/worklog/task/?id=6204
A redação desse log de trabalho está com falhas, na melhor das hipóteses, no entanto, parece que o InnoDB nessas versões mais recentes agora suporta valores persistentes de autoinc durante as reinicializações.
-Grêmio
fonte
Ocorremos esse problema e descobrimos que, quando a tabela de otimização era executada em uma tabela vazia, o valor de incremento automático também era redefinido. Veja este relatório de erros do MySQL .
Como solução alternativa, você pode:
Em vez de
OPTIMIZE TABLE
.Parece que é isso que o MySQL faz internamente (sem definir o valor de incremento automático, obviamente)
fonte
Apenas um tiro no escuro - se o aplicativo estiver usando a
TRUNCATE TABLE
para esvaziar a tabela quando terminar o processamento, isso redefinirá o campo de incremento automático. Aqui está uma breve discussão sobre a questão. Embora esse link mencione que o InnoDB não redefine os auto_increments em um trunc, isso foi relatado como um bug e corrigido alguns anos atrás.Supondo que meu palpite esteja correto, você pode mudar de truncar para excluir para corrigir o problema.
fonte
Somente uma redefinição explícita desse valor, ou uma eliminação / recriação desse campo ou outra operação violenta semelhante deve redefinir um contador de auto_increment. (O TRUNCATE era uma teoria realmente boa.) Parece impossível que você repita um INT de 32 bits quando o último valor que você testemunha é de apenas 600k. Definitivamente, não deve ser redefinido apenas porque a tabela se esvazia. Você tem um bug no mysql ou algo no seu código PHP. Ou o cara no cubículo ao lado está brincando com você.
Você pode depurar ativando o log binário , pois ele conterá instruções como esta em todo:
Então, pelo menos, você pode ver todos os detalhes do que está acontecendo com essa tabela, inclusive logo antes da redefinição do contador.
fonte
ALTER TABLE table_name ENGINE = MyISAM
Funciona para mim. Nossa tabela é sempre mantida muito pequena, portanto não há necessidade do InnoDB.
fonte
O InnoDB não armazena o valor de incremento automático no disco, esquecendo-o quando o servidor MySQL é desligado. Quando o MySQL é iniciado novamente, o motor InnoDB restaura o valor de incremento automático desta forma:
SELECT (MAX(id) + 1) AS auto_increment FROM table
. Este é um erro que é fixo no MySQL versão 8.0.Mude o mecanismo da tabela para resolver o problema:
Ou atualize o servidor MySQL para a versão 8.0 quando for lançado.
fonte