2009-06-19 19 views
33

Ho una tabella distribuita su due server che eseguono MySql 4. Ho bisogno di unirli in un unico server per il nostro ambiente di test.tabella mysqldump senza scaricare la chiave primaria

Queste tabelle hanno letteralmente milioni di record ciascuna, e la ragione per cui sono su due server è a causa di quanto sono enormi. Qualsiasi alterazione e impaginazione dei tavoli ci darà un colpo troppo grande per le prestazioni.

Poiché sono in un ambiente di produzione, è impossibile per me modificarli in alcun modo sui loro server esistenti.

Il problema è che la chiave primaria è un campo di incremento automatico univoco, quindi ci sono intersezioni.

Ho cercato di capire come utilizzare il comando mysqldump per ignorare determinati campi, ma i tasti --disable-semplicemente alterano la tabella, invece di eliminare completamente le chiavi.

A questo punto sembra che avrò bisogno di modificare la struttura del database per utilizzare un checksum o un hash per la chiave primaria come una combinazione dei due campi unici che in realtà dovrebbero essere unici ... Io davvero voglio fare questo

Help!

risposta

24

se non ti interessa quale sarà il valore della colonna auto_increment, quindi carica il primo file, rinomina la tabella, quindi ricrea la tabella e carica il secondo file. infine, utilizzare

INSERT newly_created_table_name (all, columns, except, the, auto_increment, column) 
     SELECT all, columns, except, the, auto_increment, column 
     FROM renamed_table_name 
+0

sembra promettente, inizierò a provare questo. –

+0

Ho un campo chiave esterna che fa riferimento a chiavi primarie. Questa soluzione mantiene quel tipo di integrità referenziale? Non sembra che lo faccia. – aamiri

+1

No, non lo farà. Cambia la chiave primaria. – longneck

10

È possibile creare una vista della tabella senza la colonna chiave primaria, quindi eseguire mysqldump su tale vista.

Quindi, se i vostri "utenti" tabella ha le colonne: id, nome, email

> CREATE VIEW myView AS 
    SELECT name, email FROM users 

Edit: ah che vedo, non sono sicuro se c'è un altro modo, allora.

+0

Non su mysql 4 :(. Lo so, triste :(. –

+0

A seconda della dimensione della tabella, è possibile creare una copia temporanea (senza PK) invece di creare una vista. – balpha

+0

Le tabelle sono nell'intervallo di milioni di record. –

3
SELECT null as fake_pk, `col_2`, `col_3`, `col_4` INTO OUTFILE 'your_file' 
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' 
LINES TERMINATED BY '\n' 
FROM your_table; 

LOAD DATA INFILE 'your_file' INTO TABLE your_table 
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"' 
LINES TERMINATED BY '\n'; 

Per fanciness aggiunto, è possibile impostare un prima inserto grilletto sulla vostra tabella di ricezione che imposta la nuova chiave primaria per fila portata prima che si verifichi l'inserimento, utilizzando in tal modo discariche regolari e ancora svuotare il tuo pk. Non testato, ma sentendoci piuttosto fiducioso.

2

Utilizzare un manichino chiave primaria temporanea:

Usa mysqldump normalmente --opts -c. Ad esempio, la tua chiave primaria è 'id'. Modifica i file di output e aggiungi una riga "dummy_id" alla struttura della tua tabella con lo stesso tipo di "id" (ma non la chiave primaria ovviamente). Quindi modifica l'istruzione INSERT e sostituisci "id" con "dummy_id". Una volta importati, rilascia la colonna "dummy_id".

0

jimyi era sulla strada giusta.

Questo è uno dei motivi per cui le chiavi di autoincremento sono un PITA. Una soluzione non è eliminare i dati ma aggiungervi.

CREATE VIEW myView AS 
SELECT id*10+$x, name, email FROM users 

(dove $ x è una singola cifra che identifica in modo univoco il database originale) sia la creazione della vista sul database di origine (che si accenni potrebbe non essere possibile) o utilizzare una routine di estratto come quello descritto da Autocrazia o del carico i dati nelle tabelle di staging sulla casella di test.

alternativa, non creare la tabella nel sistema di prova - invece mettere in tabelle separate per i dati src quindi creare una vista che preleva da entrambi:

CREATE VIEW users AS 
(SELECT * FROM users_on_a) UNION (SELECT * FROM users_on_b) 

C.

+0

Non capisco come sia utile creare una vista, dato che mysqldump non emette la vista DATA, solo l'istruzione CREATE VIEW, quindi non sei più avanti. Se stai usando la vista per creare una tabella temporanea, la vista è ridondante. Se poi userai select .. into outfile, quindi ancora una volta, la vista è ridondante. Cosa mi manca? –

6
  1. clonare il vostro tavolo
  2. goccia la colonna nella tabella di clone
  3. Dump tavolo clone senza la struttura (ma con l'opzione -c per ottenere inserti completi)
  4. Importa dove vuoi
3

Questo è un dolore totale. I aggirare questo problema eseguendo qualcosa come

sed -e "s/([0-9]*,/(/gi" export.sql > expor2.sql 

sulla discarica di sbarazzarsi delle chiavi primarie e poi

sed -e "s/VALUES/(col1,col2,...etc.) VALUES/gi" LinxImport2.sql > LinxImport3.sql 

per tutte le colonne tranne che per la chiave primaria. Ovviamente, dovrai fare attenzione che lo standard ([0-9]*, non sostituisca nulla che desideri effettivamente.

La speranza che aiuta qualcuno.

+0

Ho dovuto rimuovere la bandiera 'i' dall'espressione regolare, ma per il resto, ha funzionato come un incantesimo! Grazie! – joshwhatk

+0

non hai bisogno della seconda istruzione quando usi 'mysqldump --complete-insert ...'. – Blauhirn

0

La soluzione che ho utilizzato è semplicemente eseguire un'esportazione SQL regolare dei dati che sto esportando, quindi rimuovere la chiave primaria dalle istruzioni di inserimento utilizzando un RegEx trovare & sostituire l'editor. Personalmente uso il Sublime Text, ma sono sicuro che TextMate, Notepad ++ ecc. Possono fare lo stesso.

Quindi eseguo semplicemente la query in cui mai il database deve essere inserito i dati copiando la query nella finestra di query di HeidiSQL o PHPMyAdmin. Se c'è un LOT di dati, salvi la query di inserimento in un file SQL e uso invece l'importazione di file. Copia & incolla con enormi quantità di testo che spesso blocca Chrome.

Questo potrebbe sembrare un sacco di lavoro, ma raramente uso più di un paio di minuti tra l'esportazione e l'importazione. Probabilmente molto meno di quanto vorrei usare sulla soluzione accettata. Ho usato questo metodo di soluzione su diverse centinaia di migliaia di righe senza problemi, ma penso che diventerebbe problematico quando raggiungi milioni.

10

Per risolvere questo problema, ho cercato questa risposta, ho trovato la risposta di @ pumpkinthehead e ho capito che tutto ciò che dobbiamo fare è trovare + sostituire la chiave primaria in ogni riga con il valore NULL in modo che mysql utilizzi il valore auto_increment predefinito anziché.

(your complete mysqldump command) | sed -e "s/([0-9]*,/(NULL,/gi" > my_dump_with_no_primary_keys.sql

uscita originale:

INSERT INTO `core_config_data` VALUES 
    (2735,'default',0,'productupdates/configuration/sender_email_identity','general'), 
    (2736,'default',0,'productupdates/configuration/unsubscribe','1'), 

uscita Transformed:

INSERT INTO `core_config_data` VALUES 
    (NULL,'default',0,'productupdates/configuration/sender_email_identity','general'), 
    (NULL,'default',0,'productupdates/configuration/unsubscribe','1'), 

Nota: Questo è ancora un hack; Ad esempio, fallirà se la colonna di auto-incremento non è la prima colonna, ma risolve il mio problema il 99% delle volte.

Problemi correlati