Aktualisieren des MySQL-Primärschlüssels

102

Ich habe eine Tabelle user_interactionsmit 4 Spalten:

 user_1
 user_2
 type
 timestamp

Der Primärschlüssel ist (user_1,user_2,type)
und ich möchte zu ändern(user_2,user_1,type)

Also was ich getan habe war:

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

und voila ...

Das Problem ist, dass die Datenbank auf einem Server aktiv ist.

Bevor ich den Primärschlüssel aktualisieren konnte, haben sich bereits viele Duplikate eingeschlichen, die sich ständig einschleichen.

Was ist zu tun?

Was ich jetzt tun möchte, ist, Duplikate zu entfernen und die neuesten zu behalten timestamp(dies ist eine Spalte in der Tabelle).

Und dann irgendwie den Primärschlüssel wieder aktualisieren.

simplfuzz
quelle
16
Ich fühle mich plötzlich schlecht für jeden einzelnen DBA, den ich leise verfluchte ...
Ignacio Vazquez-Abrams
5
Fügen Sie
1
@Ignacio, es ist live auf einem Server, aber das ist ein Backup-Backup-Server :-). Ich bin kein DBA, aber ich werde dieses Ding nicht auf einem WIRKLICH Live-Server
ausprobieren
1
@knittl, ja das habe ich mir jetzt gedacht, allerdings sehr spät :-)
simplfuzz
4
@pixeline: Es ist ein zusammengesetzter Primärschlüssel.
Ignacio Vazquez-Abrams

Antworten:

231

Verwenden Sie beim nächsten Mal eine einzelne Anweisung "alter table", um den Primärschlüssel zu aktualisieren.

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

Um Dinge zu reparieren:

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;

Die Sperre sollte verhindern, dass weitere Updates eingehen, während Sie dies tun. Wie lange dies dauert, hängt natürlich von der Größe Ihres Tisches ab.

Das Hauptproblem besteht darin, dass Sie einige Duplikate mit demselben Zeitstempel haben.

Martin
quelle
11

Wenn der Primärschlüssel zufällig ein Wert für auto_increment ist, müssen Sie das Auto-Inkrement entfernen, den Primärschlüssel löschen und das Auto-Inkrement erneut hinzufügen

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

Fügen Sie dann das automatische Inkrement wieder hinzu

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

Stellen Sie dann das automatische Inkrement auf den vorherigen Wert zurück

ALTER TABLE `xx` AUTO_INCREMENT = 5;
frazras
quelle
2

Sie können auch das IGNORESchlüsselwort verwenden, Beispiel:

 update IGNORE table set primary_field = 'value'...............
Sarfraz
quelle