Reparar todas las tablas de MySQL en un sistema Vicidial

28 Nov

El domingo pasado recibí el correo de un cliente: su sistema de marcación predictiva con vicidial había tenido fallas eléctricas durante el fin de semana, ocasionando que las tablas de MySQL se corrompieran y que el sistema quedara inservible (al menos lo relacionado con la marcación predictiva).

Tras cerca de una hora reparé todas las tablas usando unos comandos simples como los que siguen:

/etc/init.d/mysql stop
cd /var/lib/mysql/asterisk
myisamchk -r *.MYI
/etc/init.d/mysql start

Sin embargo, me percaté que al hacer esto, estaba solo reparando las tablas una por una. El sistema tenía 4 núcleos, por lo que era posible hacer mucho más trabajo al mismo tiempo (4 tareas a la vez) en vez de ir una por una.

El sistema terminó de manera habitual tras el paso de 1 1/2 hrs. Para evitar que tanto tiempo se perdiera en nuevas ocasiones, decidí crear un script en bash que reparara todas las tablas de manera simultánea (limitándose a 1 proceso por cada núcleo del sistema), y me quedó el código así:

#!/bin/bash

# Editar estos valores:
## CORES 		debe ser igual al número de núcleos en el sistema 
##				(revisar el comando "cat /proc/cpuinfo")
## MYSQLDBDIR	debe ser igual a la carpeta de MySQL que contiene la BD
##				que debamos reparar (default: "/var/lib/mysql/asterisk")

CORES=4
MYSQLDBDIR=/var/lib/mysql/asterisk

# Enlistar los archivos
FILES=`ls $MYSQLDBDIR/*.MYI`
RUNS=0
for i in $FILES
do
	SALIR=0
	while [ $SALIR -eq 0 ]
	do
		# Obtener la cantidad de procesos en el sistema
		PROCS=`ps -eF|grep myisamchk|egrep -v "grep"|wc -l`

		# Ejecutamos el while los procesos activos sean menor a CORES
		if [ $CORES -gt $PROCS ]
		then
			echo `date +"%X"` Revisando/Reparando tabla $i
			myisamchk -r $i &
			# Descansamos 1 segundo
			sleep 1
			SALIR=1
		else
			# Esperamos 3 segundos
			sleep 3
		fi
	done

done

# Ya se terminaron de correr todas las instrucciones de reparación,
# pero existe la posibilidad de que algunas de ellas aún estén ejecutándose.
# Revisamos para ver si hay procesos corriendo y avisar al usuario
while [ $SALIR -eq 0 ]
do
	# Obtener la cantidad de procesos en el sistema
	PROCS=`ps -eF|grep myisamchk|egrep -v "grep"|wc -l`
	if [ $PROCS -gt 0 ]
	then
		echo `date +"%X"` Hay $PROCS procesos corriendo. Esperando 10s...
		sleep 10
	else
		echo "No hay procesos corriendo"
		SALIR=1
	fi
done
echo `date +"%X"` Fin. Ya puedes reiniciar MySQL

Los siguientes pasos son algo obvios:

  1. Hay que guardar este script como un archivo checar.sh
  2. Editamos el archivo y cambiamos el número de cores de nuestro sistema, así como la ubicación de la carpeta de MySQL que contiene los archivos de la BD
  3. Darle permisos de ejecución (chmod 755 checar.sh)
  4. Ejecutarlo: ./checar.sh
El script correrá varios procesos en paralelo para revisar cada uno una tabla. Mientras más núcleos tenga nuestro procesador, más rápido el script aprovechará los recursos para crear la reparación.
Espero les sirva.
¡Suerte!

 

Advertencia: Aunque este script puede ayudarnos a reparar nuestras tablas en caso de algún problema (falla eléctrica, corrupción del sistema de archivos, fallo en el disco duro, etc) no hay nada más seguro que respaldar nuestra información periódicamente. Siempre ten a la mano copias de seguridad de aquella información crítica, ya que no podemos hacernos responsables por la pérdida de información causada por el mal uso de las directivas que se muestran en este artículo. Úsalo bajo tu propio riesgo.