¿Por qué fallan las tablas MySQL? ¿Cómo lo evito?

9

Soy el administrador de un sitio de Moodle que tenía su tabla de Usuarios corrupta y quedó inutilizable.

Afortunadamente, un simple lo REPAIR TABLE mdl_userhizo funcionar de nuevo. Lo que pasa es que no sé por qué realmente se bloqueó y lo dejó inutilizable, y quiero asegurarme de que esté mejor preparado la próxima vez.

No soy un DBA con experiencia, solo soy un desarrollador que hace muchas cosas, así que tengan paciencia conmigo.

Podría restaurar una copia de seguridad, pero creo que hay formas de evitar bloqueos.

Esas tablas son utf8_general_ci y usan MyISAM.

¿Por qué se bloquea una tabla MySQL? ¿Qué puedo hacer para evitar que eso suceda?

AeroCross
fuente

Respuestas:

11

Es bastante fácil que una tabla MyISAM se bloquee.

En el encabezado de cada tabla MyISAM hay un contador que rastrea la cantidad de identificadores de archivos abiertos que hay en la tabla.

Si inicia mysql y el número en el encabezado no coincide con el número de identificadores de archivo reales, mysqld trata la tabla como bloqueada.

Si un simple lo REPAIR TABLE mdl_userhace funcionar de nuevo cada vez sin pérdida de datos, esto puede indicar que tiene un sitio con mucho tráfico que escribe mdl_user.

Si docenas de tablas requieren esto REPAIR TABLE, convertiría todas las tablas a InnoDB. Sin embargo, si la mdl_usertabla es la única tabla con este problema, hay algo que puede hacer (para este ejemplo, supongamos que la base de datos es moodle);

Si desea que todas las tablas se dejen como MyISAM

PASO 01: Crear un script de tabla de reparación

echo "REPAIR TABLE moodle.mdl_user;" > /var/lib/mysql/MoodleStartUp.sql

PASO 02: Declare la secuencia de comandos de reparación como el archivo de inicio

Agregue esto a /etc/my.cnf

[mysqld]
init-file=/var/lib/mysql/MoodleStartUp.sql

PASO 03: reinicie mysql

Cada reinicio de mysql activará el Script de tabla de reparación

Si desea que todas las tablas se conviertan en InnoDB

Ejecute este código para hacer una secuencia de comandos de conversión masiva de tablas MyISAM a InnoDB y verlo

MYSQL_USER=root
MYSQL_PASS=password
MYSQL_CONN="-u${MYSQL_USER} -p ${MYSQL_PASS}"
echo "SET SQL_LOG_BIN = 0;" > /root/ConvertMyISAMToInnoDB.sql
mysql ${MYSQL_CONN} -A --skip-column-names -e"SELECT CONCAT('ALTER TABLE ',table_schema,'.',table_name,' ENGINE=InnoDB;') InnoDBConversionSQL FROM information_schema.tables WHERE engine='MyISAM' AND table_schema NOT IN ('information_schema','mysql','performance_schema') ORDER BY (data_length+index_length)" > /root/ConvertMyISAMToInnoDB.sql
less /root/ConvertMyISAMToInnoDB.sql

Una vez que esté satisfecho con el contenido del script de conversión, ejecútelo

mysql ${MYSQL_CONN} < /root/ConvertMyISAMToInnoDB.sql

ACTUALIZACIÓN 2012-03-15 14:00 EDT

@Kevin , mientras usa MyISAM, ¿qué sucede si quedarse sin espacio en disco es su problema?

Aquí hay algo a considerar: De acuerdo con la Guía de estudio de certificación MySQL 5.0 ,

ingrese la descripción de la imagen aquí

bulletpoint # 11 dice lo siguiente en las páginas 408,409 Sección 29.2:

Si se queda sin espacio en disco al agregar filas a una tabla MyISAM, no se produce ningún error. El servidor suspende la operación hasta que haya espacio disponible y luego completa la operación.

Cuando te quedes sin espacio en disco, no solo apagues o mates mysql. El recuento de los identificadores de archivos abiertos en cualquier MyISAM utilizado actualmente no se habrá borrado. Por lo tanto, la tabla MyISAM se marca bloqueada. Si puede liberar espacio en disco en el volumen de datos con mysqld aún ejecutándose, mysqld se activará una vez que el espacio en disco esté disponible.

RolandoMySQLDBA
fuente
Excelente respuesta No conocía el bit de los identificadores del archivo, y ya ha resuelto cómo puedo evitar (o reparar automáticamente) en caso de que algo salga mal. ¿Alguna sugerencia de seguridad si el sitio de hecho escribe mucho en mdl_user (o en cualquier otra tabla)?
AeroCross
Debe hacer tres cosas: 1) aumentar RAM, 2) aumentar max_ connections, 3) cambiar a InnoDB.
RolandoMySQLDBA
Noob aquí. ¿Dónde "ejecuto" este código? ¿Desde un archivo cargado en el servidor o desde alguna línea de comando?
UncaughtTypeError
0

También administro un sitio moodle en mysql, y la causa más común de corrupción de tablas para nosotros es quedarse sin espacio en disco.

Kevin
fuente
@RolandoMySQLDBA: sí, el espacio en disco es sin duda el problema (relacionado con algunos otros procesos y la filosofía de administración en general). Desafortunadamente, no vemos que el problema se resuelva solo cuando se despeje el espacio, o no se resuelve de manera oportuna. Mi respuesta fue solo señalar que con nuestra instancia de moodle / mysql, los problemas de espacio en disco pueden causar fallas en la tabla, independientemente de lo que se supone que debe hacer mysql / myisam.
Kevin
-3

Encontré una buena línea para convertir todas las tablas a InnoDB:

mysql -u root -p dbName -e "show table status where Engine='MyISAM';" | 
    awk 'NR>1 {print "ALTER TABLE "$1" ENGINE = InnoDB;"}'  | 
    mysql -u root -p dbName
Dmitry
fuente
El código puede estar bien para eso, pero no responde la pregunta de la primera parte (¿Por qué se bloquea una tabla MySQL?). Si quiere decir que responde la segunda parte (¿Cómo evitarlo?), Agregue más explicaciones, por favor.
ypercubeᵀᴹ
También agregue más detalles. ¿Ejecutar esto convertirá todas las tablas en una base de datos? ¿O todo el servidor? ¿Qué sucederá si una tabla no se convierte y obtenemos un error? ¿Es posible que terminemos con algunas tablas convertidas y algunas dejadas en MyiSAM? En general, ¿qué otras cosas debe considerar un DBA antes de ejecutar esto?
ypercubeᵀᴹ