MySql: modifica di innodb_file_per_table per un db live


18

Ho un grande database MySql (150 GB) e solo ora ho notato che innodb_file_per_tableè impostato su offche fa sì che l'intero DB sia ospitato su un singolo file ( ibdata1). Voglio attivarlo innodb_file_per_tablee farlo dividere retroattivamente il DB in più file, qual è il modo migliore per farlo?

Risposte:


32

C'è davvero solo un modo per farlo. Dovrai esportare i dati utilizzando mysqldumps, eliminare tutti i database, chiudere mysqld, eliminare ib_logfile0, eliminare ib_logfile1, eliminare ibdata1, aggiungere innodb_file_per_tablesotto l' [mysqld]intestazione, avviare mysql.

Ho pubblicato questa risposta in StackOverflow nell'ottobre 2010

Ecco i passaggi elencati in verticale:

Step 01) MySQLDump di tutti i database in un file di testo SQL (chiamalo SQLData.sql)

Passaggio 02) Rilascia tutti i database (tranne lo schema mysql)

Passaggio 03) Spegni mysql

CAVEAT : per ripulire totalmente le transazioni senza commit dai file InnoDB, esegui questo

mysql -uroot -p... -Ae"SET GLOBAL innodb_fast_shutdown = 0;"
service mysql stop

Passaggio 04) Aggiungi le seguenti righe a /etc/my.cnf

[mysqld]
innodb_file_per_table
innodb_flush_method=O_DIRECT
innodb_log_file_size=1G
innodb_buffer_pool_size=4G

Sidenote: qualunque sia il tuo set per innodb_buffer_pool_size, assicurati che innodb_log_file_size sia il 25% di innodb_buffer_pool_size.

Passaggio 05) Elimina ibdata1, ib_logfile0 e ib_logfile1

A questo punto, dovrebbe esserci solo lo schema mysql in / var / lib / mysql

Passaggio 06) Riavvia mysql

Ciò ricrea ibdata1 a 10 MB, ib_logfile0 e ib_logfile1 a 1G ciascuno

Passaggio 07) Ricaricare SQLData.sql in mysql

ibdata1 crescerà ma conterrà solo metadati di tabella

Ogni tabella InnoDB esiste al di fuori di ibdata1

Supponiamo di avere una tabella InnoDB denominata mydb.mytable. Se vai in / var / lib / mysql / mydb, vedrai due file che rappresentano la tabella

  • mytable.frm (intestazione del motore di archiviazione)
  • mytable.ibd (Home dei dati delle tabelle e degli indici delle tabelle per mydb.mytable)

ibdata1 non conterrà più dati e indici InnoDB.

Con l'opzione innodb_file_per_table in /etc/my.cnf, puoi eseguire OPTIMIZE TABLE mydb.mytable e il file /var/lib/mysql/mydb/mytable.ibd si ridurrà effettivamente.

L'ho fatto molte volte nella mia carriera come DBA MySQL

In effetti, la prima volta che l'ho fatto, ho compresso un file ibdata1 da 50 GB in 500 MB.

Provaci. Se hai ulteriori domande al riguardo, inviami un'e-mail. Fidati di me. Funzionerà a breve e lungo termine. !!!

Esiste un'alternativa che estrarrà la tabella InnoDB senza ridurre ibdata1.

Passaggio 01) Aggiungi le seguenti righe a /etc/my.cnf

[mysqld]
innodb_file_per_table
innodb_flush_method=O_DIRECT
innodb_log_file_size=1G
innodb_buffer_pool_size=4G

Step 02) service mysql restart

Passaggio 03) Per estrarre una singola tabella InnoDB chiamata mydb.mytable, procedere come segue:

ALTER TABLE mydb.mytable ENGINE=InnoDB;

Questo creerà un file pleus mantenendo il file di struttura originale

  • /var/lib/mysql/mydb/mytable.frm
  • /var/lib/mysql/mydb/mytable.ibd

Puoi farlo per ogni tabella InnoDB. Sfortunatamente, ibdata1 rimarrà 150 GB.


mentre eseguo la ricarica dai file .sql ho avuto il seguente errore ERROR 1071 (42000) at line 25: Specified key was too long; max key length is 1000 bytesqualche idea?
Ran

@Ran, per favore, pubblicalo come domanda separata.
RolandoMySQLDBA,


Se si imposta innodb_file_per_tablee quindi si esegue l'operazione ALTER TABLEsu ogni singola tabella, è possibile eliminare il file ibdata1 per recuperare lo spazio senza dover ripristinare?
SystemParadox

1
@SystemParadox ASSOLUTAMENTE NO !!!!!!!! Perderai il dizionario dei dati.
RolandoMySQLDBA

5

Se vuoi recuperare lo spazio di ibdata, una discarica / ripristino è la tua unica scelta, come sottolinea Rolando . Probabilmente è anche meglio che le prestazioni facciano questo.

Tuttavia, se vuoi solo ridurre le perdite e "perdere" quei 150 GB sul disco rigido, puoi semplicemente abilitare innodb_file_per_table in my.cnf e riavviare il server.

Quindi per ogni tabella, emettere:

ALTER TABLE x DISABLE KEYS;
ALTER TABLE x ENGINE=InnoDB;
ALTER TABLE x ENABLE KEYS; 

Il problema qui è che i grandi tablespace impiegheranno un po 'di tempo.

Quello che suggerirei è di impostare uno slave del tuo db live, eseguire la conversione sullo slave, quindi spegnere il master / slave e copiare il nuovo dataspace sul master o promuovere lo slave come master una volta raggiunto .

Avrai difficoltà a apportare questa modifica senza tempi di inattività.


+1 per essere brutalmente onesto e dire "taglia le tue perdite". Avresti potuto dire anche "mordi il proiettile".
RolandoMySQLDBA

È possibile utilizzare pt-online-schema-change per evitare tempi di inattività durante l'esecuzione della tabella di modifica.
Cornernote,
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.