MySql: cambio de innodb_file_per_table por un db en vivo


18

Tengo una gran base de datos MySql (150 GB) y solo ahora me he dado cuenta de que innodb_file_per_tableestá configurada en lo offque hace que toda la base de datos esté alojada en un solo archivo ( ibdata1). Quiero activar innodb_file_per_tabley dividir retroactivamente la base de datos en varios archivos, ¿cuál es la mejor manera de hacer esto?

Respuestas:


32

Realmente solo hay una forma de lograr esto. Tendrá que exportar los datos utilizando mysqldumps, descartar todas las bases de datos, cerrar mysqld, eliminar ib_logfile0, eliminar ib_logfile1, eliminar ibdata1, agregar innodb_file_per_tabledebajo del [mysqld]encabezado, iniciar mysql.

Publiqué esta respuesta en StackOverflow en octubre de 2010

Estos son los pasos enumerados verticalmente:

Paso 01) MySQL Vuelca todas las bases de datos en un archivo de texto SQL (llámalo SQLData.sql)

Paso 02) Descarte todas las bases de datos (excepto el esquema mysql)

Paso 03) Apagar mysql

PRECAUCIÓN : para limpiar totalmente las transacciones no confirmadas de los archivos de InnoDB, ejecute esto

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

Paso 04) Agregue las siguientes líneas a /etc/my.cnf

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

Nota al margen: cualquiera que sea su conjunto para innodb_buffer_pool_size, asegúrese de que innodb_log_file_size sea el 25% de innodb_buffer_pool_size.

Paso 05) Eliminar ibdata1, ib_logfile0 e ib_logfile1

En este punto, solo debe haber el esquema mysql en / var / lib / mysql

Paso 06) Reinicia mysql

Esto recreará ibdata1 a 10MB, ib_logfile0 e ib_logfile1 a 1G cada uno

Paso 07) Vuelva a cargar SQLData.sql en mysql

ibdata1 crecerá pero solo contendrá metadatos de tabla

Cada tabla InnoDB existirá fuera de ibdata1

Supongamos que tiene una tabla InnoDB llamada mydb.mytable. Si ingresa en / var / lib / mysql / mydb, verá dos archivos que representan la tabla

  • mytable.frm (encabezado del motor de almacenamiento)
  • mytable.ibd (Página principal de datos de tabla e índices de tabla para mydb.mytable)

ibdata1 nunca contendrá más datos e índices de InnoDB.

Con la opción innodb_file_per_table en /etc/my.cnf, puede ejecutar OPTIMIZE TABLE mydb.mytable y el archivo /var/lib/mysql/mydb/mytable.ibd realmente se reducirá.

Lo he hecho muchas veces en mi carrera como DBA MySQL

De hecho, la primera vez que hice esto, colapsé un archivo ibdata1 de 50 GB en 500 MB.

Darle una oportunidad. Si tiene más preguntas sobre esto, envíeme un correo electrónico. Créeme. Esto funcionará a corto plazo y a largo plazo. !!!

Existe una alternativa que extraerá la tabla InnoDB sin reducir ibdata1.

Paso 01) Agregue las siguientes líneas a /etc/my.cnf

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

Paso 02) service mysql restart

Paso 03) Para extraer una sola tabla de InnoDB llamada mydb.mytable, haga esto:

ALTER TABLE mydb.mytable ENGINE=InnoDB;

Esto creará un archivo por favor, mantenga el archivo de estructura original

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

Puede hacer esto para cada tabla InnoDB. Desafortunadamente, ibdata1 se mantendrá 150GB.


mientras ejecutaba la recarga desde los archivos .sql recibí el siguiente error ¿ ERROR 1071 (42000) at line 25: Specified key was too long; max key length is 1000 bytesalguna idea?
Corrió el

@Ran, publícalo como una pregunta separada.
RolandoMySQLDBA


Si configura innodb_file_per_tabley luego hace lo mismo ALTER TABLEen cada tabla, ¿puede eliminar el archivo ibdata1 para reclamar el espacio sin tener que restaurar?
SystemParadox

1
@SystemParadox ABSOLUTAMENTE NO !!!!!!!! Perderá el diccionario de datos.
RolandoMySQLDBA

5

Si desea recuperar el espacio de ibdata, su única opción es un volcado / restauración, como señala Rolando . También es probablemente mejor para el rendimiento hacer esto.

Sin embargo, si solo quiere reducir sus pérdidas y 'perder' esos 150 GB en el disco duro, simplemente puede habilitarlo innodb_file_per_tableen my.cnf y reiniciar su servidor.

Luego, para cada tabla, emita:

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

El problema aquí es que los espacios de tabla grandes tomarán un tiempo.

Lo que sugeriría es configurar un esclavo de su base de datos en vivo, ejecutar la conversión en el esclavo, luego apagar el maestro / esclavo y copiar el nuevo espacio de datos al maestro, o promover el esclavo para que sea maestro una vez que se haya puesto al día .

Tendrá dificultades para realizar este cambio sin tiempo de inactividad.


+1 por ser brutalmente honesto y decir 'corta tus pérdidas'. También podrías haber dicho 'muerde la bala'.
RolandoMySQLDBA

Puede usar pt-online-schema-change para evitar el tiempo de inactividad mientras ejecuta la tabla alter.
cornernote
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.