lsofrel:查看进程打开的DB relation文件

5090阅读 1评论2013-06-28 Bean_lee
分类:Mysql/postgreSQL

   某些情况下,某条SQL执行非常耗时并且DISK IO高,我们想看下进程在操作那些表。strace可以看到文件在操作的文件描述符,根据文件描述符结合lsof可以看到进程操作哪些磁盘文件,这其实也不是我们想要的,给你/usr/pgdata/base/16384/16392这样的磁盘文件你也不清楚对应那个表,当然了,oid2name可做到从文件名映射到relation。为了排查问题的方便,我写了一个小工具,lsofrel,顾名思义,就是查看进程打开那些relation的小工具:
  1. #!/bin/sh


  2. POSTGRES_PREFIX="XXXXXX/base"
  3. DB_NAME="XXXDB"

  4. usage()
  5. {
  6.     echo -e " USAGE: lsofrel PID [FD]"
  7.     echo -e " OUTPUT: FD\tfilename\tOID\trelation"
  8. }


  9. show_rel()
  10. {
  11.     local pid=$1
  12.     local target_fd=$2
  13.     DB_DIR=`oid2name |grep $DB_NAME |awk '{print $1}'`
  14.     DB_PREFIX="$POSTGRES_PREFIX/$DB_DIR/"
  15.     filelist=`lsof -p $pid |grep $DB_PREFIX |grep REG|grep -v fsm|grep -v vm| awk 'BEGIN{OFS="|"}{print $4,$9}' `
  16.     
  17.     for pair in $filelist
  18.     do
  19.     
  20.      fd=` echo $pair |awk -F'[|]' '{print $1}'|tr -d u `
  21.         if [ -z "$target_fd" -o "$fd" = "$target_fd" ]
  22.         then
  23.             file=`echo $pair |awk -F'[|]' '{print $2}' `
  24.             file_p=`basename $file`
  25.             echo -e "$fd\t$file\t\c"
  26.             oid2name -d $DB_NAME -f $file_p |awk '{if(NR==4) print}'
  27.         fi
  28.     done
  29.     
  30. }
  31. if [ $# -lt 1 ]
  32. then
  33.     usage
  34.     exit
  35. else
  36.     show_rel $1 $2
  37. fi
    POSTGRES_PREFIX中的XXXX改为自己的postgres数据库所在的目录,DB_NAME 改为自己的数据库名称,就可以查看某进程在操作自己数据库的哪些文件。
   
   因为截图是用的公司的数据库,为了信息安全我只显示了系统表(grep pg),并且将数据库存储路径做了处理。该脚本接受1到2个参数,第一个参数是进程ID,第二个参数是进程打开的的FD,如果存在的话。只有一个参数,会显示该进程打开的所有relation。有两个参数会显示该进程某FD对应的路径及relation。比较简单,如上图所示。如果SQL大量磁盘IO操作的话,配合strace,可以看到SQL在读那个relation的记录。
    
上一篇:PostgreSQL源码分析之FSM
下一篇:PostgreSQL之查找最慢的SQL