Chinaunix首页 | 论坛 | 博客
  • 博客访问: 3892141
  • 博文数量: 146
  • 博客积分: 3918
  • 博客等级: 少校
  • 技术积分: 8585
  • 用 户 组: 普通用户
  • 注册时间: 2010-10-17 13:52
个人简介

个人微薄: weibo.com/manuscola

文章分类

全部博文(146)

文章存档

2016年(3)

2015年(2)

2014年(5)

2013年(42)

2012年(31)

2011年(58)

2010年(5)

分类: Mysql/postgreSQL

2013-06-28 18:46:22

   某些情况下,某条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的记录。
    
阅读(5020) | 评论(1) | 转发(0) |
给主人留下些什么吧!~~