Red de conocimiento informático - Material del sitio web - Cómo analizar la información de seguimiento de fallos

Cómo analizar la información de seguimiento de fallos

Cuando MySQL sale de forma anormal, la información de rastreo a menudo se imprime en error.log. Podemos obtener algunas razones de la excepción de este rastreo, como errores de aserción, acceso al contenido a punteros nulos, etc. A medida que se investiga esta información, generalmente hacemos inferencias basadas en la lógica del código, escribimos casos de prueba para reproducirlos, parcharlos y verificarlos nuevamente. Sin embargo, en las primeras etapas de la salida anormal de MySQL en línea, la información de rastreo a menudo se imprime en error.log. Podemos obtener algunas razones de la excepción de este rastreo, como errores de aserción, acceso al contenido de punteros nulos, etc. A medida que se eliminan estas fallas de información, generalmente hacemos inferencias basadas en la lógica del código, escribimos casos de prueba para reproducirlos, luego parcheamos y luego realizamos el proceso de verificación.

Sin embargo, debido a que los parámetros de compilación de MySQL implementados en la línea en los primeros días no estaban muy estandarizados, los rastreos que causaron algunos fallos de MySQL no parecían tan transparentes, eran muy difíciles de entender o incluso no tenían sentido. en absoluto. Esto nos trae muchos inconvenientes a la hora de solucionar problemas. Por supuesto, este problema se resolvió usando google-breakpad para obtener un miniconjunto de datos de fallas de MySQL, pero esa es una historia para otro día y no entraré en eso aquí.

¿Es cierto que no se puede deducir nada de tales rastreos? incierto. Analicemos uno de los fracasos de esta semana.

En línea, una biblioteca de respaldo de la versión 5.5 falló repentinamente después de ejecutarse durante 3 meses. El rastreo del fallo es:

/u01/mysql/bin/mysqld(my_print_stacktrace 0x39)[0x7b1b69 ]<. /p>

/u01/ mysql/bin/mysqld(my_print_stacktrace 0x39)[0x7b1b69]

/u01/ mysql/bin/mysqld(handle_segfault 0x43c)[0x4fa39c]

/lib64/libpthread.so.0[0x344dc0f520]

/u01/mysql/bin/mysqld[0x7fb4c1]

/lib64/libpthread.so.0[0x344dc077e1]

/lib64/libc.so.6(clone 0x6d)[0x344d8e68ed

Esta información de rastreo es típica de las primeras compilaciones e implementaciones de MySQL. La información de rastreo es difícil de leer. Sin embargo, según la experiencia y algo de sentido común, este es un hilo con una relación de llamada muy simple, porque el pthread creado en el rastreo solo llama a la función mysqld una vez. Por lo tanto, supongo que este hilo puede ser un hilo en segundo plano. ¿Qué línea de código es la dirección 0x7fb4c1 que muestra la capa mysqld? Esto es muy crítico para que analicemos el problema.

Después de adivinar, es hora de verificar, ¡y GDB interviene! Utilice GDB para desmontar en la máquina correspondiente.

Nota:

1. ¡No realice operaciones relacionadas con GDB durante los períodos pico de trabajo!

2. ¡Esté muy familiarizado con las operaciones de GDB que está realizando!

3. ¡Es mejor notificar al DBA correspondiente!

¡Entonces, levántate! Dirección de desmontaje en línea 0x7fb4c1. Primero verifique qué función es:

gdb -p 31639 -ex "disassemble?0x7fb4c1?" --ex "quit" --batch--ex "quit" --batch gt ; /tmp/g1.log

Volcado de código ensamblador de 0x7fb4c1 a 0x7fb4f1:

0x00000000007fb4c1: cmp esi, (rax)

0x00000000007fb4c3: jne 0x7fb4b0 <; /p>

0x00000000007fb4c5: mov 0xc(r8), edi

0x00000000007fb4c9: cmp 0x4(rax), edi

0x00000000007fb4cc: jne 0x7fb4b0

0x 00000000007fb4ce: mov 0x60(rax), rdi

0x00000000007fb4ce: mov 0x60(rax), rdi3449

3450 buf_pool = buf_pool_from_array(j);

3451

0x00000000007fb46d: mov r12, -0x740(rbp)

0x00000000007fb474: nopl 0x0(rax)

0x00000000007fb486: prueba r12, r12

0x00 000000007fb489: je 0x7fb908

0x00000000007fb48f : lea (r9, r9, 2), rdi

0x00000000007fb493 : mov r12, rax

0x00000000007 fb496: xor edx, edx

0x00000000007fb498: shl $0x3, rdi

0x00000000007fb49c: mov -0x6c8(rbp, rdi, 1), esi

0x00000000007fb4b4: test rax, rax

0x00000000007fb4b7: je 0x7fb900

3452 blocks_num = UT_LIST_GET_LEN(buf_pool-gt;flush_list);

0x00000000007fb4c1: cmp esi, (rax)

0x000000 00007fb4c3:jne 0x7fb4b0

0x00000000007fb4c5: mov 0xc(r8), edi

0x00000000007fb4c9: cmp 0x4(rax), edi

0x00000000007fb4cc: jne 0x7fb4b0

0

x00000000007fb4ce: mov 0x60(rax), rdi

0x00000000007fb4d2: cmp rdi, 0x10(r11)

0x00000000007fb4d6: jne 0x7fb4b0

0x0000 0007fb4d8:nopl 0x0(rax , rax, 1)

3453 bpage = UT_LIST_GET_FIRST(buf_pool-gt;flush_list);

3454 new_blocks_num = 0;

0x00000000007fb4a3: lea -0x6d0(rbp , rdi, 1), r8

0x00000000007fb4ab: jmp 0x7fb4c1

0x00000000007fb4ad: nopl (rax)

3455

3456 encontrado = FALSO ;

3457 while (bpage != NULL) {

3458 if (prev_flush_info[j].space == bpage-gt;space

3459 amp; amp; prev_flush_info[j].offset == bpage-gt; offset

0x00000000007fb4b0: mov 0x40(rax), rax

3460 amp; /p>

0x00000000007fb4bd: add $ 0x1, rdx

¡Finalmente vea el código familiar!

¡Se puede determinar que la esencia del problema es causada por la excepción en línea! 3452. Es decir, se accede a buf_pool-gt; flux_list.count con una dirección de memoria ilegal.

Este código es una variable de memoria a la que srv_master_thread. La excepción ocurrió en otro lugar, causando esto. La memoria está contaminada. En cuanto al motivo, no tengo idea. Lo analizaré cuando lo encuentre más tarde.

En este punto, hemos podido. Profundice en el rastreo de MySQL y descubra el misterio de la dirección en el rastreo. Aún no se ha resuelto, y se puede descubrir otra información en el rastreo, y los consejos de los expertos detrás de él pueden quedar claros de un vistazo.

Dirección original: Cómo analizar el rastreo de fallos, gracias al autor original por compartirlo.