Locations of visitors to this page

Wednesday, August 17, 2011

Getting MySQL process list with GDB

用GDB调试MySQL,显示线程列表

define helper functions
cat >mysql.gdb <<'EOF'
#set interactive-mode off
set confirm off
dont-repeat
define show_processlist
  #argc is not available in older version gdb
  #if $argc==1
  #  set $p_thread_id=(long long)$arg0
  #else
    set $p_thread_id=(long long)-1
  #end
  set $current=((base_ilist)threads).first
  set $last=&(((base_ilist)threads).last)
  printf "Id\tUser\tHost\tDb\tCommand\tTime\tState\tInfo\n"
  while $current != $last
    set $tmp=(class THD *)$current
    set $tmp_sctx=$tmp->security_ctx
    if ( $p_thread_id == -1 || $p_thread_id == $tmp->thread_id )
      set $id=$tmp->thread_id
      set $user=(char*)($tmp_sctx->user?$tmp_sctx->user:($tmp->system_thread?"system user":"unauthenticated user"))
      set $host=$tmp_sctx->host_or_ip
      set $db=($tmp->db)?$tmp->db:"NULL"
      set $command=(int)($tmp->command)
      #set $proc_info=(char*)(($tmp->killed==THD::KILL_CONNECTION)?"Killed":0) #5.1
      set $proc_info=(char*)($tmp->killed?"Killed":0)
      set $state_info=(char*) ($tmp->locked ? "Locked" : $tmp->net.reading_or_writing ? ($tmp->net.reading_or_writing == 2 ? "Writing to net" : $command == COM_SLEEP ? "" : "Reading from net") : $tmp->proc_info ? $tmp->proc_info : ($tmp->mysys_var && $tmp->mysys_var->current_cond) ? "Waiting on cond" : "NULL")
      set $start_time=$tmp->start_time
      #set $now=my_time(0) #5.1
      set $now=time((time_t*) 0)
      set $query=(char*)($tmp->query_string.str?$tmp->query_string.str:"")
      printf "%u\t%s\t%s\t%s\t%s\t%u\t%s\t%.100s\n",$id,$user,$host,$db,command_name[$command].str,$now-$start_time,$state_info,$query
    end
    set $current=$current->next
  end
end
document show_processlist
  Prints MySQL process list.
  Syntax: show_processlist [thread id]
  Examples:
    show_processlist
    show_processlist 123
    show_processlist -1
end
define kill_thread
  #if $argc >= 1
    set $p_thread_id=(unsigned long long)$arg0
    #set $p_only_kill_query=(char *)(($argc >= 2)?$arg1:"connection")
    set $p_only_kill_query=(char *)$arg1
    set $only_kill_query=(strcmp($p_only_kill_query,(char *)"query")==0)?1:0
    set $current=((base_ilist)threads).first
    set $last=&(((base_ilist)threads).last)
    while $current != $last
      set $tmp=(class THD *)$current
      if $p_thread_id == $tmp->thread_id
        set $id=$tmp->thread_id
        printf "kill thread id %d %s\n", $id, $only_kill_query?"only query":""
        #call kill_one_thread($tmp, $id, $only_kill_query)
        call sql_kill($tmp, $id, $only_kill_query)
        loop_break
      end
      set $current=$current->next
    end
  #else
  #  help kill_thread
  #end
end
document kill_thread
  Kills MySQL thread.
  Syntax: kill_thread <thread id> <query|connection>
  Examples:
    kill_thread 123
    kill_thread 123 "connection"
    kill_thread 321 "query"
end
EOF

show processlist


mysql_port=8217
# older version gdb does not support '-ex' option
#gdb -batch -silent -p $(pgrep -f "/mysqld .*$mysql_port"|head -n1) -x mysql.gdb -ex 'show_processlist'
gdb -silent -p $(pgrep -f "/mysqld .*$mysql_port"|head -n1) -x mysql.gdb <<'EOF' |\
sed -n '/^=====begin=====$/,/=====end=====/p'|sed '1d;$d'
set prompt
set pagination off
printf "\n\n"
printf "=====begin=====\n"
show_processlist
printf "=====end=====\n"
EOF

kill thread

thread_id=223
gdb -silent -p $(pgrep -f "/mysqld .*$mysql_port"|head -n1) -x mysql.gdb <<EOF
kill_thread $thread_id "connect"
EOF

No comments:

Website Analytics

Followers