¿Cómo puedo optimizar un mysqldump de una gran base de datos?

173

Tengo una aplicación Symfony con una base de datos InnoDB que es ~ 2GB con 57 tablas. La mayor parte del tamaño de la base de datos reside en una sola tabla (~ 1.2GB). Actualmente estoy usando mysqldump para hacer una copia de seguridad de la base de datos todas las noches.

Debido a mi conexión de Comcast, a menudo si estoy ejecutando un volcado manualmente, mi conexión al servidor se agota antes de que se complete el volcado, lo que hace que tenga que volver a ejecutar el volcado. [Actualmente ejecuto un cron que realiza el volcado todas las noches, esto es solo para volcados que ejecuto manualmente.]

¿Hay alguna forma de acelerar los volcados para el problema del tiempo de espera de conexión, pero también para limitar el tiempo que el servidor está ocupado con este proceso?

Por cierto, actualmente estoy trabajando para reducir el tamaño de la base de datos general para resolver este problema.

Patricio
fuente
2
¿Qué parámetros (si los hay) está pasando al comando mysqldump?
Toby
Agregar --compact puede ser una opción para usted.
Toby
nada realmente -mysqldump [database] -u[user] -p'[password]' > db_backup.sql
Patrick
44
Una alternativa simple screenpara su situación sería usar nohup, le permitirá que su comando continúe ejecutándose en el servidor, incluso si su conexión se corta. Por ej nohup mysqldump [options] > backup.sql 2> backup.err &. Si no proporciona un archivo de salida nohup, se creará nohup.outde manera predeterminada.
dabest1
1
Eche un vistazo a aty screen(este último si está instalado, pero ates estándar en todos los unixes) o las ServerAliveIntervalopciones para SSH para ver las formas de lidiar con el cortafuegos que lo apaga después de una conexión inactiva durante demasiado tiempo.
MattBianco

Respuestas:

134

El principal cuello de botella en el vertedero como este es la E / S de la unidad. Está leyendo una carga de datos y volviendo a escribirla. Puede acelerar esto de varias maneras:

  • Asegúrese de que su salida vaya a una (s) unidad (es) diferente (s) a la (s) en la que están almacenados los archivos de la base de datos; esto hará una gran diferencia con los discos giratorios ya que los cabezales de las unidades no se moverán constantemente entre la ubicación que se lee y la ubicación en la que se escribe.
  • La salida de mysqldump será muy compresible, por lo que si no puede separar la salida de la entrada como se mencionó anteriormente, canalice la salida a través gzipo similar. Esto reducirá la cantidad de escritura que se está realizando (así que reduzca la carga general de E / S y la cantidad de movimiento de la cabeza) a expensas de algún tiempo de CPU (que de todos modos puede tener mucho de sobra en estos momentos).
  • Además, (también o en lugar de la compresión) pasa la salida a través de una utilidad de tubería (como pv ) que admite grandes memorias intermedias de escritura para agrupar más los bloques escritos en las unidades, una vez más para reducir el efecto de la latencia del movimiento del cabezal, esto hará que una gran diferencia si se usa la --quickopción para reducir el impacto de RAM al hacer copias de seguridad de tablas grandes).
  • Solo ejecute su proceso de copia de seguridad cuando la carga de E / S sea baja.

Sin embargo, es posible que esté solucionando el problema incorrecto: podría ser más fácil abordar las caídas de conexión (aunque reducir la carga de E / S impuesta por sus copias de seguridad ayudará a reducir el efecto que tiene en otros usuarios, por lo que vale la pena intentarlo de todos modos). ¿Podría ejecutar sus copias de seguridad manuales a través de la pantalla (o herramientas similares como tmux )? De esa manera, si su conexión con el servidor se cae, puede volver a conectarse y volver a conectar a la screensesión sin que se interrumpa ningún proceso.

Si está enviando los datos directamente a través de la conexión (es decir, está ejecutando mysqldump en su máquina local contra una base de datos remota, por lo que el volcado aparece localmente), es mejor que primero ejecute el volcado en el servidor, comprimiendo según sea necesario y luego transfiriendo los datos a través de la red utilizando una herramienta (como rsync) que admite transferencias parciales para que pueda reanudar la transferencia (en lugar de reiniciar) si una caída de conexión la interrumpe.

Como parte de su "reducción del tamaño de la base de datos global para resolver este problema", supongo que una gran parte de sus datos no cambia. Es posible que pueda mover una gran parte de los 1.2 Gb de esa tabla principal a otra y eliminar eso de los que copia la mysqldumpllamada. No necesita hacer una copia de seguridad de estos datos cada vez si nunca cambia. La división de datos entre tablas y bases de datos de esta manera generalmente se conoce como partición de datos y también puede permitirle distribuir los datos y la carga de E / S en varias unidades. La base de datos de alta gama ha incorporado soporte para particionamiento automático, aunque en mysql probablemente tendrá que hacerlo manualmente y alterar su capa de acceso a datos para tenerlo en cuenta.

Desviarse del tema para este sitio (por lo que probablemente debería pasar a ServerFault o SuperUser para preguntar si necesita más detalles): si parece estar perdiendo conexiones debido a la inactividad, verifique las opciones en su servidor SSH y cliente SSH para hacer Asegúrese de que los paquetes Keep-Live estén habilitados y se envíen con la suficiente frecuencia. Si ve caídas incluso si la conexión está activa, también puede intentar usar OpenVPN o similar para envolver la conexión: debe manejar una caída breve, incluso una caída completa si su conexión completa está inactiva durante unos segundos, de modo que el cliente SSH y El servidor no se da cuenta.

David Spillett
fuente
Desearía poder reducir la cantidad de conexiones ssh caídas a mis servidores. Si espero no usar el terminal por más de ~ 60 segundos, corro toppara asegurar que la conexión no se caiga. (Y estoy bastante seguro de que es la conexión de Comcast, ya que solo estamos usando un enrutador y firewall WRT estándar en el trabajo y mi conexión de Comcast en casa nunca se cae)
Patrick
He agregado una breve nota específica para las conexiones SSH.
David Spillett
2
Profundidad y perspicacia en esta respuesta. Deberías obtener un +3 por esto. Lo siento, solo puedo darte +1.
RolandoMySQLDBA
116

PERSPECTIVAS PARA HACER COPIAS DE SEGURIDAD CON mysqldump

En mi humilde opinión, hacer copias de seguridad se ha convertido en una forma de arte si sabes cómo abordarlo

Tienes opciones

Opción 1: mysqldump una instancia entera de mysql

¡Esta es la más fácil, la obviedad!

mysqldump -h... -u... -p... --hex-blob --routines --triggers --all-databases | gzip > MySQLData.sql.gz

Todo escrito en un archivo: estructuras de tablas, índices, disparadores, procedimientos almacenados, usuarios, contraseñas cifradas. Otras opciones de mysqldump también pueden exportar diferentes estilos de comandos INSERT, archivo de registro y coordenadas de posición desde registros binarios, opciones de creación de bases de datos, datos parciales (opción --where), etc.

Opción 2: mysqldump bases de datos separadas en archivos de datos separados

Comience creando una lista de bases de datos (2 técnicas para hacer esto)

Técnica 1

mysql -h... -u... -p... -A --skip-column-names -e"SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('information_schema','mysql')" > ListOfDatabases.txt

Técnica 2

mysql -h... -u... -p... -A --skip-column-names -e"SELECT DISTINCT table_schema FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql')" > ListOfDatabases.txt

La técnica 1 es la forma más rápida. La técnica 2 es la más segura y segura. La técnica 2 es mejor porque, a veces, los usuarios crean carpetas para fines generales en / var / lib / mysql (datadir) que no están relacionadas con la base de datos. Information_schema registraría la carpeta como una base de datos en la tabla information_schema.schemata. La técnica 2 omitiría las carpetas que no contienen datos mysql.

Una vez que compila la lista de bases de datos, puede proceder a recorrer la lista y mysqldump, incluso en paralelo si así lo desea.

for DB in `cat ListOfDatabases.txt`
do
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz &
done
wait

Si hay demasiadas bases de datos para iniciar a la vez, volcado en paralelo 10 a la vez:

COMMIT_COUNT=0
COMMIT_LIMIT=10
for DB in `cat ListOfDatabases.txt`
do
    mysqldump -h... -u... -p... --hex-blob --routines --triggers ${DB} | gzip > ${DB}.sql.gz &
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

Opción 3: mysqldump tablas separadas en archivos de datos separados

Comience creando una lista de tablas

mysql -h... -u... -p... -A --skip-column-names -e"SELECT CONCAT(table_schema,'.',table_name) FROM information_schema.tables WHERE table_schema NOT IN ('information_schema','mysql')" > ListOfTables.txt

Luego volcar todas las tablas en grupos de 10

COMMIT_COUNT=0
COMMIT_LIMIT=10
for DBTB in `cat ListOfTables.txt`
do
    DB=`echo ${DBTB} | sed 's/\./ /g' | awk '{print $1}'`
    TB=`echo ${DBTB} | sed 's/\./ /g' | awk '{print $2}'`
    mysqldump -h... -u... -p... --hex-blob --triggers ${DB} ${TB} | gzip > ${DB}_${TB}.sql.gz &
    (( COMMIT_COUNT++ ))
    if [ ${COMMIT_COUNT} -eq ${COMMIT_LIMIT} ]
    then
        COMMIT_COUNT=0
        wait
    fi
done
if [ ${COMMIT_COUNT} -gt 0 ]
then
    wait
fi

Opción 4: USE SU IMAGINACIÓN

Pruebe variaciones de las opciones mencionadas más técnicas para obtener instantáneas limpias

Ejemplos

  1. Ordene la lista de tablas por el tamaño de cada tabla ascendente o descendente.
  2. Usando un proceso separado, ejecute "ENJUAGAR TABLAS CON BLOQUEO DE LECTURA; SELECCIONE SUEÑO (86400)" antes de iniciar mysqldumps. Mata este proceso después de que mysqldumps estén completos. Esto es útil si una base de datos contiene InnoDB y MyISAM
  3. Guarde los mysqldumps en carpetas con fecha y gire las carpetas de respaldo antiguas.
  4. Cargue mysqldumps de instancia completa en servidores independientes.

CONSIDERACIÓN

Solo la Opción 1 trae todo. El inconveniente es que mysqldumps creado de esta manera solo se puede volver a cargar en la misma versión de lanzamiento de mysql que se generó mysqldump. En otras palabras, un mysqldump de una base de datos MySQL 5.0 no se puede cargar en 5.1 o 5.5. La razón ? El esquema mysql es totalmente diferente entre las principales versiones.

Las opciones 2 y 3 no incluyen guardar nombres de usuario y contraseñas.

Aquí está la forma genérica de volcar las concesiones SQL para usuarios que es legible y más portátil

mysql -h... -u... -p... --skip-column-names -A -e"SELECT CONCAT('SHOW GRANTS FOR ''',user,'''@''',host,''';') FROM mysql.user WHERE user<>''" | mysql -h... -u... -p... --skip-column-names -A | sed 's/$/;/g' > MySQLGrants.sql

La opción 3 no guarda los procedimientos almacenados, por lo que puede hacer lo siguiente

mysqldump -h... -u... -p... --no-data --no-create-info --routines > MySQLStoredProcedures.sql &

Otro punto que debe tenerse en cuenta es sobre InnoDB. Si tiene un gran grupo de búferes InnoDB, tiene sentido limpiarlo lo mejor que pueda antes de realizar cualquier copia de seguridad. De lo contrario, MySQL pasa el tiempo limpiando las tablas con las páginas sucias sobrantes del grupo de búferes. Esto es lo que sugiero:

Aproximadamente 1 hora antes de realizar la copia de seguridad, ejecute este comando SQL

SET GLOBAL innodb_max_dirty_pages_pct = 0;

En MySQL 5.5, innodb_max_dirty_pages_pct predeterminado es 75. En MySQL 5.1 y versiones posteriores, innodb_max_dirty_pages_pct predeterminado es 90. Al establecer innodb_max_dirty_pages_pct en 0, esto acelerará el vaciado de páginas sucias en el disco. Esto evitará o al menos disminuirá el impacto de limpiar cualquier confirmación incompleta de dos fases de los datos de InnoDB antes de realizar cualquier mysqldump en cualquier tabla de InnoDB.

PALABRA FINAL EN mysqldump

La mayoría de las personas se alejan de mysqldump en favor de otras herramientas y esas herramientas son realmente buenas.

Tales herramientas incluyen

  1. MAATKIT ( scripts de volcado / restauración paralelos , de Percona [obsoleto pero excelente])
  2. XtraBackup (Copia de seguridad de instantánea de TopNotch de Percona)
  3. CDP R1Soft ( Opción de módulo MySQL que toma instantáneas de punto en el tiempo)
  4. MySQL Enterprise Backup (anteriormente InnoDB Hot Backups [comercial])

Si tiene el espíritu de un verdadero DBA MySQL, puede adoptar mysqldump y tener el dominio completo sobre él que se puede lograr. Que todas tus copias de seguridad sean un reflejo de tus habilidades como MySQL DBA .

RolandoMySQLDBA
fuente
2
+1 para un buen uso de mysqldump así como para: si tiene el espíritu de un verdadero MySQL DBA, puede adoptar mysqldump y tener el dominio completo sobre él que se puede lograr. Que todas sus copias de seguridad sean un reflejo de sus habilidades como DBA MySQL ... ¡¡¡Grandes líneas !!!
Abdul Manaf
44
En InnoDB, volcar tablas individualmente le dará una copia de seguridad inconsistente.
Alain Collins el
55
@AlainCollins es por eso que ejecuto mysqldumps en un esclavo de replicación que es de solo lectura. Una vez que Seconds_Behind_Master es 0, ejecuta STOP SLAVE. Ahora tiene un punto constante en el tiempo para hacer mysqldumps en cualquiera de los estilos antes mencionados. Lo he hecho para empresas de comercio en línea en los últimos 5 años sin una sola queja para mí o los propietarios de mi empresa. A partir de este momento, hago paralelos mysqldumps cada 10 minutos para este cliente. También hago esto para que otros clientes proporcionen períodos de respaldo más rápidos.
RolandoMySQLDBA
Tengo una base de datos de 32 GB, ¡así que la opción 3 es exactamente lo que tenía en mente! ¡Gracias!
Raymond el
Tengo que hacer una copia de seguridad y volver a importar 1 TB de datos para reducir el tamaño extremadamente grande ibdata1. En tiempos de SSD respaldados por RAID de hardware, la opción 3 es la única solución para mí.
rabudde
18

Echa un vistazo a la replicación de MySQL maestro a esclavo. Le permite clonar la base de datos del maestro a otro servidor de bases de datos con la misma base de datos. Eso incluye las identidades maestra y esclava. Slave se hace la copia exacta del servidor de la base de datos maestra y / o sus bases de datos. Puede haber una relación uno-uno, muchos, muchos-uno entre maestro (s) y esclavo (s).

Slave lee continuamente el registro binario en el maestro (bin log almacena las consultas escritas en el servidor de la base de datos maestra) y recibe información en su servidor de la base de datos esclava. (esto significa que su base de datos maestra no se verá afectada en absoluto)

La buena noticia es que no afectará demasiado a su servidor MySQL ya que no notará ningún tiempo de inactividad o respuestas de consulta lentas. Lo usamos para bases de datos de 10 Gb y funciona de maravilla sin ningún tiempo de inactividad.

Replicación MySQL en la misma máquina

poelinca
fuente
Si bien eso funcionaría para mí, creo que podría ser un poco exagerado. Actualmente no necesito ese nivel de respaldo, aunque lo tendré en cuenta si cambian los requisitos de la aplicación.
Patrick
44
+1 para hacer una copia de seguridad de una réplica para eliminar la carga de E / S de la copia de seguridad del DB principal y reducir posibles problemas relacionados con el bloqueo, con una advertencia importante: tenga cuidado con la opción "réplica en la misma máquina" que sus operaciones en el esclavo puede competir con el maestro por el ancho de banda de E / S: asegúrese de que los archivos de datos del esclavo tengan una unidad / matriz diferente que el maestro para mitigar este problema.
David Spillett
1
Lo mismo ocurre con el comentario de David Splllet. Configuré y mantuve docenas de Maestros / Esclavos con copias de seguridad mysqldump en los esclavos para My Web Hosting Employer. +1 de mi parte también.
RolandoMySQLDBA
16

Plan A: Ver también Xtrabackup de Percona. Esto permite la copia de seguridad en línea de InnoDB, sin ningún bloqueo significativo.

Plan B: un esclavo puede detenerse y puede realizar una copia de seguridad consistente por cualquiera de los siguientes medios (copiar archivos, mysqldump, xtrabackup, etc.)

Plan C: Instantánea LVM. Después de una configuración críptica, el tiempo de inactividad para una copia de seguridad es inferior a un minuto, independientemente del tamaño de la base de datos. Detiene mysqld, realiza la instantánea, reinicia mysqld y luego copia la instantánea. El último paso puede llevar mucho tiempo, pero MySQL no está caído.

Plan D: Instantánea de un esclavo: cero tiempo de inactividad.

Rick James
fuente
2
Hoorah a los cuatro planes. ¡Solo puedo dar +0.25 por respuesta! +1 (4 x 0.25)
RolandoMySQLDBA
15

Primero, algunos puntos de administrador: ¿Te estás conectando para hacer un ftp o estás encerrado y se está muriendo? Si es ssh, asegúrese de usar la pantalla para poder reanudar después del bloqueo de Comcast. Si es ftp, asegúrese de comprimirlo / tar antes del envío.

Pruebe también el parámetro --opt o --quick

--opt Esta opción activa un conjunto de opciones adicionales para hacer que las operaciones de volcado y recarga sean más eficientes. Específicamente, es equivalente a usar las opciones --add-drop-table, --add-locks, --all, --quick, --extended-insert, --lock-tables y --disable-keys juntas. Tenga en cuenta que esta opción hace que la salida sea menos portátil y menos comprensible para otros sistemas de bases de datos.

--quick Esta opción le dice a mysqldump que escriba la salida del volcado a medida que lee cada fila del servidor, lo que podría ser útil para tablas grandes. Por defecto, mysqldump lee todas las filas de una tabla en la memoria antes de escribir la salida; para tablas grandes, esto requiere grandes cantidades de memoria, posiblemente haciendo que falle el volcado.

David Hall
fuente
1
¿--Opt no aumentará el tamaño del archivo que eventualmente obtendrá salida?
Toby
Agregará algo, quise agregar, lo que es más en respuesta a su problema ... editar ahora. ¡Gracias!
David Hall
+1 para la pantalla, lo que evita este problema por completo
Gaius
+1 para una respuesta muy agradable y concisa para las explicaciones --opt y --quick de mysqldump.
RolandoMySQLDBA
1
--opt está activado por defecto.
Jordan
5

Solía ​​tener problemas con los tiempos de espera durante los volcados de grandes bases de datos también. Finalmente resolví si enviando comandos individuales para cada tabla en la base de datos y agregando todo a un archivo como este:

TABLES=`mysql -u $USER -p$PWD -Bse 'show tables' $DB`
for TABLE in $TABLES
do
    mysqldump -u $USER -p$PWD $DB $TABLE >> dump.sql
done
Patrick Heck
fuente
44
Esto se considera una copia de seguridad "inconsistente", ya que al restaurar puede tener datos en una tabla que se asigna a otra pero no existe.
Morgan Tocker
3

Creo que la pregunta es sobre cómo restaurar más rápido desde los archivos de volcado creados por mysqldump, no una solución de respaldo diferente.

Una de las formas en que puede hacerlo es creando grupos de tablas en su esquema, y ​​cree un usuario de base de datos separado para cada grupo y finalmente use los permisos de MySQL para no permitir que las tablas se inserten usando todos menos un usuario de base de datos.

Esta es una técnica probada, rápida, casi paralela pero no 100% segura, cuánto tiempo tomará restaurar desde grandes vertederos como 500G más o menos. Pero en mi humilde opinión, necesitas algo paralelo. Consulte el siguiente enlace para ver un ejemplo.

[Restauración rápida y paralela de volcados de SQL (mysqldump) para MySQL] [1]

http://geeksww.com/tutorials/database_management_systems/mysql/tips_and_tricks/fast_parallel_restore_from_sql_dumps_mysqldump_for_mysql.php

"Restauración rápida y paralela de volcados de SQL (mysqldump) para MySQL"

syed
fuente
2
Esta es una copia exacta de su respuesta a otra pregunta. Es posible que desee personalizarlo un poco más para esta pregunta específica.
Paul White
La pregunta NO es específicamente acerca de cómo restaurar más rápido.
Andrew Lorien