2010-02-26 10 views
62

Tengo una tabla user_interactions con 4 columnas:Actualización de MySQL primaria clave

user_1 
user_2 
type 
timestamp 

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

Así que lo que hice fue:

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

y voila ...

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

Así que antes de que pudiera actualizar la clave primaria, muchos duplicados que ya han entrado, y que se están arrastrando continuamente.

¿Qué hacer?

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

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

+8

de repente me siento mal por todos y cada uno de DBA Maldije por lo bajo ... –

+3

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

+0

@ignacio tee hee – benlumley

Respuesta

150

La próxima vez, utilizar una sola "ALTER TABLE" declaración para actualizar la clave principal.

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

para arreglar las 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 debe dejar más actualizaciones que vienen mientras que su están haciendo esto. Cuánto tiempo lleva esto depende obviamente del tamaño de su mesa.

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

+1

¡Eres genial! Ojalá pudiera agradecerte lo suficiente. – dharm0us

2

Usted puede utilizar la palabra clave IGNORE también, ejemplo:

update IGNORE table set primary_field = 'value'............... 
+0

Está intentando alterar la columna, no actualizar el valor. –

4

Si la clave principal pasa a ser un valor AUTO_INCREMENT, usted tiene que quitar el incremento automático, a continuación, colocar la clave principal a continuación, volver a agregar el incremento automático

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

continuación, añadir de nuevo el incremento automático

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

continuación, establezca incremento automático de nuevo a valor anterior

ALTER TABLE `xx` AUTO_INCREMENT = 5; 
Cuestiones relacionadas