Showing posts with label gdb. Show all posts
Showing posts with label gdb. Show all posts

Monday, September 10, 2012

How to obtain all executing queries from a core file

When investigating core files from crashes, one can quite easily figure out which query crashed, as we've seen.

Sometimes you want to just list all the currently executing statements, this is useful for diagnosing hangs or corruptions.

At least GDB 7 supports python macros, which can help us a lot here.   I use a core file from 5.5.27, also a non-debug build but not "stripped".   So it's a standard build made with -g allowing us to reference symbols.

I wrote a simplistic macro to iterate through mysqld's global "threads" variable.
This is what my ~./.gdbinit looks like:


set history filename gdb_history.txt
set history size 32000
set history save on
set pagination off
set logging overwrite on
set logging on
set print elements 1024
set print pretty on
set print object on
define print_thds
        set $thd = ($arg0)->first
        while ( $thd != 0 && $thd->next != 0)
             
                set $thread_id=$thd->thread_id
                set $cmd=$thd->command
                set $proc_info=$thd->proc_info ? $thd->proc_info : ""
                 set $query = $thd->query_string->string
printf "thread id: %lu\n",$thread_id print $cmd
print $proc_info
print $query.str
printf "\n\n"      
                set $thd=$thd->next
        end
end
document print_thds
  print_thds : Dumps the query_strings in a list of THD objects
end

Loading a corefile and executing the macro, see now how it works :

[sbester@fc14 mysql-advanced-5.5.27-linux2.6-x86_64]$ gdb ./bin/mysqld ./core.5376
GNU gdb (GDB) Fedora (7.2-52.fc14)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
...
SIGINT is used by the debugger.
Are you sure you want to change it? (y or n) [answered Y; input not from terminal]
Reading symbols from /home/sbester/mysql/5.5/mysql-advanced-5.5.27-linux2.6-x86_64/bin/mysqld...done.
[New Thread 5417]
[New Thread 5376]
Reading symbols from /lib/modules/2.6.35.14-106.fc14.x86_64/vdso/vdso.so...Reading symbols from /usr/lib/debug/lib/modules/2.6.35.14-106.fc14.x86_64/vdso/vdso.so.debug...done.
done.
(gdb) print_thds threads
thread id: 22
$1 = COM_QUERY
$2 = 0x9ae27c "init"
$3 = 0x7fffc801dc80 "/* 50605 */  delete  ignore from `t1` order by  ( `b`<>  null )"


thread id: 21
$4 = COM_QUERY
$5 = 0xa0aeda "update"
$6 = 0x1880850 "/* 50605   explain extended   */  insert  ignore into `t1` set `a`=`a`"


thread id: 20
$7 = COM_SLEEP
$8 = ""
$9 = 0x0


thread id: 19
$10 = COM_SLEEP
$11 = ""
$12 = 0x0


thread id: 18
$13 = COM_QUERY
$14 = 0xa10e30 "updating"
$15 = 0x7fffd800e540 "/* 50605 */  delete  ignore from `t1` where (  ( `b` )    ) >= (  ( `a` is  null  )  )"


thread id: 17
$16 = COM_SLEEP
$17 = ""
$18 = 0x0


thread id: 16
$19 = COM_QUERY
$20 = 0x9ae27c "init"
$21 = 0x7fffd0017930 "/* 50605   explain extended   */ update  ignore`t3` set `a` = 4.7  order by  (  ( `a` is  null  )   sounds like  ( `a` )   ) desc limit 8"


thread id: 15
$22 = COM_QUERY
$23 = 0x9be1e5 "Updating"
$24 = 0x7fffc8005230 "/* 50605  explain partitions  */ update `t3` set `a` = `a`  where  ( `a` )    limit 1"


thread id: 14
$25 = COM_SLEEP
$26 = ""
$27 = 0x0


thread id: 13
$28 = COM_QUERY
$29 = 0x9ae27c "init"
$30 = 0x7fffc0045e10 "/* 50605   explain extended   */ update `t1` set `b` =  'e'   order by   ( `a`  not like  `b` )   desc limit 7"


thread id: 12
$31 = COM_QUERY
$32 = 0x9be1e5 "Updating"
$33 = 0x1850f80 "/* 50605 */ update  ignore`t3` set `b` = `b`  where (   ( `b`  and  `a` )  ) = (  (  ( `a` is  null  )<> ( `a` )   ) ) limit 7"


thread id: 11
$34 = COM_QUERY
$35 = 0x9ae27c "init"
$36 = 0x7ffff0005760 "/* 50605  explain /*!50605 format= json*/  */ update  ignore`t2` set `a` = -1.4  where (   ( `a`<=  `a` )  ) < (     CONCAT(  ( `b` )   ,   ( `a`  xor   null )   ,   ( `a` is  null  )   )     ) order by   (   null )   desc limit 5"


thread id: 9
$37 = COM_QUERY
$38 = 0x9ae27c "init"
$39 = 0x7fffd8005140 "/* 50605  explain   */  delete  from `t2` order by  (  ( `b` )  = ( `b`   sounds like -4.6 )    ) desc"


thread id: 8
$40 = COM_QUERY
$41 = 0x9be1e5 "Updating"
$42 = 0x7fffdc004d40 "/* 50605  explain /*!50605 format= json*/  */ update `t1` set `a` =  'deg'   where   ( `a`<`a` )"


thread id: 7
$43 = COM_QUERY
$44 = 0x9ae27c "init"
$45 = 0x7fffd00048e0 "/* 50605   explain extended   */ update `t2` set `a` = 8  order by   ( `b`>`b` )  asc  limit 4"


thread id: 5
$46 = COM_QUERY
$47 = 0xa10e30 "updating"
$48 = 0x7fffcc034000 "/* 50605  explain /*!50605 format=traditional */  */  delete  ignore from `t3`"


thread id: 4
$49 = COM_QUERY
$50 = 0x9ae27c "init"
$51 = 0x7fffc001b8d0 "/* 50605 */  delete  from `t1` where (  (  ( `a` )  < (  ( `b` is  null  )<=   ( `a`<>  null )    ) ) )  &   (     OCTET_LENGTH(  ( `b` )     )     ) order by  ( `b` )    desc limit 7"


thread id: 3
$52 = COM_SLEEP
$53 = ""
$54 = 0x0


thread id: 2
$55 = COM_QUERY
$56 = 0x9ae27c "init"
$57 = 0x7fffc0004a90 "/* 50605  explain /*!50605 format= json*/  */ update  ignore`t3` set `b` =   null  order by   ( 1.5 )   limit 8"


thread id: 1
$58 = COM_QUERY
$59 = 0xa0aeda "update"
$60 = 0x7fffcc004a90 "/* 50605   explain extended   */  insert  ignore into `t1` set `a`=6"

Thursday, August 21, 2008

how to debug a mysqld core file from an rpm install

You have a typical rpm installation of mysql, and the process is crashing. Here are the basic steps needed to find out more info about a crash:

  • Configure the OS to be able to create corefiles. (Redhat details), (Solaris details)
  • Tell mysqld to create a corefile by adding the following options to my.cnf:

[mysqld_safe]
core-file-size=unlimited

[mysqld]
core-file
Usually the corefile will be created in the datadir with a name like core.2921 where 2921 was the pid of the running process. The location is configurable on most OS's.

You'll need the following to study the core file:

  • exact mysqld binary that created the core file
  • the core file
  • the glibc version of the original system (rpm -qa|grep -i glibc)
  • the debuginfo package corresponding to the original mysql rpms.
Let's go through a hypothetical example next.
On my server I have installed MySQL-server-community-5.0.67-0.rhel5.x86_64.rpm and it's been crashing. I have a corefile called core.12345 which I've moved to a test system because I don't want to impact production while playing around with it.

On the production server we have glibc 2.3.4-2.36 installed. So to setup the test box to study the core I do this:

From dev.mysql.com download the MySQL-community-debuginfo-5.0.67-0.rhel5.x86_64.rpm
Download the glibc-2.3.4-2.36.x86_64.rpm from somewhere (in case test system isn't running same version). Next we extract the RPMS and launch gdb and tell it the path to load libraries and symbol files:

rpm2cpio MySQL-community-debuginfo-5.0.67-0.rhel5.x86_64.rpm | cpio -idvu
rpm2cpio glibc-2.3.4-2.36.x86_64.rpm | cpio -idvu

gdb ./mysqld --core ./core.12345
set solib-absolute-prefix .
file ./usr/lib/debug/usr/sbin/mysqld.debug

From here you should get reasonable output from GDB, such as "thread apply all bt" and "bt full" and continue to examine the corefile...