MySQL: el aumento automático no aumenta secuencialmente si se eliminó la última fila


8

Tengo una tabla que contiene una identificación de clave primaria con incremento automático. Si elimino la última fila (la identificación más alta, para la identificación de examen = 6) e inserto una nueva fila, la nueva identificación comienza en 7. ¿Qué parámetro tengo que cambiar para que la clave primaria comience en 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:
nombre de identificación
1 perro
2 gato
3 pingüino
4 lax
5 ballena
6 avestruz

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

Resultado:
nombre de identificación
1 perro
2 gato
3 pingüino
4 lax
5 ballena
7 x

Gracias por el consejo.


Entonces, ¿qué pasa si hay lagunas? (que puede aparecer debido a otras razones, no sólo mediante la supresión de filas)
ypercubeᵀᴹ

¿Qué le gustaría hacer si la eliminación ocurre después de una inserción? vas a reutilizar esa brecha? es sí, entonces no creo que Identity sea el tipo correcto para esa columna. le brinda la oportunidad de no preocuparse por valores únicos en esa columna. Si tiene la intención de mantener los valores en secuencia, entonces podría haber utilizado el tipo de datos de tipo INT / BIGINT normal. encontrar / reutilizar / restablecer valores para cada espacio perdido es como perder el propósito de la Propiedad de identidad.
Anup Shah

@ giordano ¿Por qué quieres ser un fanático aseado de AUTO_INCREMENT PRIMARY KEY? lidiar con él también hay una "brecha" en los datos de su tabla si actualiza / elimina debido a la fragmentación ..
Raymond Nijland

Hice una investigación sobre los valores continuos de autoincremento para SQL Server hace un tiempo: sqlity.net/en/792/the-gap-in-the-identity-value-sequence - Si bien no es para MySQL, los mecanismos subyacentes son los mismos , así obtendrás resultados similares. En resumen, no puede evitar huecos y secuencias generadas automáticamente.
Sebastian Meine

@ypercube: gracias por las respuestas. De hecho, la brecha que obtuve de otro ejemplo más complejo, pero quería mostrar un ejemplo mínimo. El ejemplo real fue (1) cambiar la fecha de vencimiento de una fila (por ejemplo, de una tabla de productos) debido al cambio de un atributo y (2) agregar el nuevo producto con el mismo código de producto, nuevo atributo, nueva fecha de vigencia y vencimiento abierto fecha. Lo que sucedió es que la nueva clave primaria no se incrementó automáticamente con +1 sino +2. Obviamente, en el paso (1) o (2) hay un incremento automático invisible. Me pregunto cuáles son las otras razones de las brechas.
giordano

Respuestas:


12

Esto es por diseño: todos los DBMS actúan con columnas de incremento automático.

Si no lo hicieran, la integridad referencial externa podría dañarse. Para un ejemplo simple de esto, imagine que está almacenando URL para un servicio de acortamiento utilizando una columna de incremento automático como clave. No sabe si la URL abreviada ya se ha entregado a alguien, y la base de datos ciertamente no lo hace, por lo que reutilizar la ID 1234 podría hacer que la pobre abuela visite somenastypornsite.xxx en lugar de loverlyknitting.org cuando hace clic en http: / /shortthi.ng/1234 en un correo electrónico antiguo, en lugar de recibir el mensaje "lo siento pero este enlace ya no existe en nuestros registros".

Además, si restablece el incremento después de eliminar el último elemento, ¿también pasará por todo el trabajo (o esperará que la base de datos) renumere todo después del quinto elemento de 5 millones cuando se elimine el quinto elemento? completa con cambios en otras tablas donde sus restricciones de clave externa apuntan a la columna de incremento? Tal trabajo extra podría ser muy costoso en cuanto a IO.

Si haces restablecer el punto mínimo de la subasta después de eliminar el último elemento, no ser muy, muy cuidadoso de sus niveles de aislamiento de transacción: Es posible restablecerlo al igual que otra transacción hace uso del valor, lo que conduce a errores (o peor, fallos silenciosos), a menos te aseguras de que tu acción esté completamente aislada al 100%.

En general, recomiendo a las personas que trabajan con bases de datos que lean "Antipatterns SQL", que tiene un capítulo sobre este tema llamado "Psuedo-Key Neat Freaks" (que cubre el asunto de una manera más amigable de lo que el título del capítulo puede implicar para algunos). Esencialmente, si el valor tiene un significado más allá de ser una clave (o como máximo llevar información de orden de inserción), entonces probablemente no debería ser una columna de incremento automático, y si no tiene ningún significado más allá de ser una clave (o como máximo llevar orden de inserción) información), entonces las brechas no deberían importar.


Gracias por esta explicación Veo que tengo que profundizar en el concepto clave. Me pregunto cómo funciona el mecanismo de incremento automático, ya que observé también huecos en la clave primaria cuando no la eliminé, pero cambié (actualicé) una fila y agregué una nueva. Definitivamente, lo que no haré es cambiar el valor del incremento automático de forma manual.
giordano

Con respecto a "profundizar en el concepto clave", recomiendo encarecidamente el libro SQL Antipatterns de Bill Karwin: cubre este y otros temas comunes (y no tan comunes), que hablan sobre cómo equivocarse, por qué el mal común los métodos pueden causar problemas, cómo solucionarlos y cuándo el método "incorrecto" podría estar bien (o la única opción) de todos modos, de manera concisa pero accesible.
David Spillett

Spillet: Gracias por esta indicación. Leí ahora y fue muy útil. Sin embargo, no entiendo por qué InnoDB y MyISAM cuentan de manera diferente: dba.stackexchange.com/questions/51883/…
giordano

0

Puede restablecer el valor de auto_increment utilizando lo siguiente:

ALTER TABLE MyTable AUTO_INCREMENT = 1234;

Debería determinar el valor máximo presente en la tabla y agregar 1 a ese valor para usar en la declaración anterior.


Mala idea, esto impedirá que su tabla lea o escriba en "casi todas" las versiones de MySQL. MySQL 5.6 podría hacer una ALTERACIÓN EN VIVO, pero a veces también necesita bloquear la tabla.
Raymond Nijland

2
@ RaymondNijland No creo que la cerradura dure lo suficiente como para que cualquiera se dé cuenta.
ypercubeᵀᴹ

@Max, Raymond, ypercube: Gracias por responder. Evitaré hacer este tipo de cambio.
giordano
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.