Actualización de la clave principal de MySQL


103

Tengo una tabla user_interactionscon 4 columnas:

 user_1
 user_2
 type
 timestamp

La clave principal es (user_1,user_2,type)
y quiero cambiar a(user_2,user_1,type)

Entonces lo que hice fue:

drop primary key ...  
add primary key (user_2,user_1,type)...

y voilá...

El problema es que la base de datos está viva en un servidor.

Entonces, antes de que pudiera actualizar la clave primaria, ya se habían introducido muchos duplicados y se están infiltrando continuamente.

¿Qué hacer?

Lo que quiero hacer ahora es eliminar los duplicados y mantener los que tienen la última versión timestamp(que es una columna en la tabla).

Y luego, de alguna manera, actualice la clave principal nuevamente.


16
De repente me siento mal por cada DBA que maldije en voz baja ...
Ignacio Vazquez-Abrams

5
la próxima vez agregue una clave única con las mismas columnas que la clave principal, luego actualice la clave principal
knittl

1
@Ignacio, está en vivo en un servidor, pero ese es un servidor de respaldo :-). No soy un DBA, pero no intentaré esto en un servidor REALMENTE en vivo :-)
simplfuzz

1
@knittl, sí, eso es lo que pensé ahora, aunque muy tarde :-)
simplfuzz

4
@pixeline: es una clave primaria compuesta.
Ignacio Vazquez-Abrams

Respuestas:


231

La próxima vez, use una sola instrucción "alterar tabla" para actualizar la clave principal.

alter table xx drop primary key, add primary key(k1, k2, k3);

Para arreglar cosas:

create table fixit (user_2, user_1, type, timestamp, n, primary key( user_2, user_1, type) );
lock table fixit write, user_interactions u write, user_interactions write;

insert into fixit 
select user_2, user_1, type, max(timestamp), count(*) n from user_interactions u 
group by user_2, user_1, type
having n > 1;

delete u from user_interactions u, fixit 
where fixit.user_2 = u.user_2 
  and fixit.user_1 = u.user_1 
  and fixit.type = u.type 
  and fixit.timestamp != u.timestamp;

alter table user_interactions add primary key (user_2, user_1, type );

unlock tables;

El bloqueo debería evitar que lleguen más actualizaciones mientras lo hace. El tiempo que tarda esto obviamente depende del tamaño de su mesa.

El principal problema es si tiene algunos duplicados con la misma marca de tiempo.


11

Si la clave principal resulta ser un valor de auto_increment, debe eliminar el incremento automático, luego soltar la clave principal y luego volver a agregar el incremento automático

ALTER TABLE `xx`
MODIFY `auto_increment_field` INT, 
DROP PRIMARY KEY, 
ADD PRIMARY KEY (new_primary_key);

luego vuelva a agregar el incremento automático

ALTER TABLE `xx` ADD INDEX `auto_increment_field` (auto_increment_field),
MODIFY `auto_increment_field` int auto_increment;

luego establezca el incremento automático de nuevo al valor anterior

ALTER TABLE `xx` AUTO_INCREMENT = 5;

2

También puede usar la IGNOREpalabra clave, ejemplo:

 update IGNORE table set primary_field = 'value'...............
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.