it-swarm.it

MySql - modifica innodb_file_per_table per un db live

Ho un DB MySql di grandi dimensioni (150 GB) e solo ora ho notato che il innodb_file_per_table è impostato su off che fa sì che l'intero DB sia ospitato su un singolo file (ibdata1). Voglio attivare innodb_file_per_table e aver diviso retroattivamente il DB in più file, qual è il modo migliore per farlo?

19
Ran

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_table sotto il [mysqld] intestazione, avvia 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

[~ # ~] avvertenza [~ # ~] : 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

Passaggio 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.

32
RolandoMySQLDBA

Se vuoi recuperare lo spazio di ibdata, un dump/restore è la tua unica scelta, come Rolando sottolinea. 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 riavvia 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à.

5
Derek Downey