Aggiornamento della chiave primaria di MySQL


103

Ho una tabella user_interactionscon 4 colonne:

 user_1
 user_2
 type
 timestamp

La chiave primaria è (user_1,user_2,type)
e voglio cambiare in(user_2,user_1,type)

Quindi quello che ho fatto è stato:

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

e voilà ...

Il problema è che il database è attivo su un server.

Quindi, prima che potessi aggiornare la chiave primaria, molti duplicati si sono già insinuati e continuano a insinuarsi.

Cosa fare?

Quello che voglio fare ora è rimuovere i duplicati e mantenere quelli con l'ultima timestamp(che è una colonna nella tabella).

E poi in qualche modo aggiorna di nuovo la chiave primaria.


16
Improvvisamente mi sento male per ogni singolo DBA che ho maledetto sottovoce ...
Ignacio Vazquez-Abrams

5
la prossima volta aggiungi una chiave univoca con le stesse colonne della chiave primaria, quindi aggiorna la chiave primaria
Knittl

1
@Ignacio, è live su un server, ma è un server di backup-backup :-). Non sono un DBA, ma non proverò questa cosa su un server VERAMENTE live :-)
simplfuzz

1
@knittl, sì, è quello che pensavo ora, molto tardi però :-)
simplfuzz

4
@pixeline: è una chiave primaria composta.
Ignacio Vazquez-Abrams,

Risposte:


231

La prossima volta, usa una singola istruzione "alter table" per aggiornare la chiave primaria.

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

Per sistemare le cose:

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;

Il blocco dovrebbe impedire l'arrivo di ulteriori aggiornamenti mentre lo fai. Quanto tempo ci vuole dipende ovviamente dalle dimensioni del tuo tavolo.

Il problema principale è se hai alcuni duplicati con lo stesso timestamp.


11

Se la chiave primaria sembra essere un valore auto_increment, devi rimuovere l'incremento automatico, quindi rilasciare la chiave primaria e aggiungere nuovamente l'incremento automatico

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

quindi aggiungere nuovamente l'incremento automatico

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

quindi reimpostare l'incremento automatico al valore precedente

ALTER TABLE `xx` AUTO_INCREMENT = 5;

2

Puoi anche usare la IGNOREparola chiave, ad esempio:

 update IGNORE table set primary_field = 'value'...............
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.