当在Linux/Unix中遇到CPU使用很高时, 我们会用"top"或"prstat"命令来查找那个进程序点用了最多的CPU. 然后再根据操作系统的进程号, 关联V$PROCESS和V$SESSION来找出是那个Oracle会话引起了问题, 这是一个很有用的解决突然性的性能问题的方法. 但这只能根据CPU或占用的内存的大小来排序, 却不能按IO等其他指标来查找. 如果我们能在Oracle中找出那些会话引起了最多的磁盘读或生成了最多的日志, 将是很有用的信息. 为此我写了一个比较方便的工具:OTop.

     OTop可以在10秒钟内告诉你这些问题的答案. 在Oracle中收集了会话级的统计值, 这对于性能调整是很有用的. 我们只需要关联V$SESSION和V$SESSTAT, 并计算两个时间点的差值进行降序排列, 就生成了对调优很有用的信息, 可以很容易找出那些会话, 引起了最多的逻辑读或物理读. 我已经用OTop在很短的时间内发现了不少性能问题. 并且用这个工具可以增加你对数据库的了解, 了解不同的时间你的数据库都在做什么. 我只化了几个小时完成了这个工具, 却发现是很有帮助的.

1, 免费下载

2, 安装及命令行选项

    OTop是一个很有用的小工具, 要运行必需安装Oracle客户端, 并配好与服务器的连接字符串, 或在服务器上直接运行. 我一般建一个ANYSQL的用户, 具有"CREATE SESSION","ALTER SESSION"和SELECT_CATALOG_ROLE的角色权限.

C:\MYDUL\utility>dcba -1 -h
AnySQL.net OTop for Oracle, Release 3.0.0
(c) Copyright Lou Fangxin (AnySQL.net) 2004-2006, all rights reserved.

Usage: dcba -[option][value]
          -{1|2|3|4} 1:OTop, 2:OPMon, 3:OTune, 4:OLoad
          -H    print help message
          -U    Oracle user name with select_catalog_role.
          -S    tns alias if remote database.
          -C    number of top SQLs displayed (min 5, max 16384)
          -Q    run in quiet mode, write to file
          -D    directory of output file in quiet mode
          -O    Order by (GETS/CPUT/DISK/SORT/WAIT/REDO/EXEC)
    对于OTop, 默认的时间间隔是10秒, 输出按逻辑读降序来排列, 在输出20次后会退出, 也可以按"Control+C"来中途退出, 并可以使用"-o"选项来指定其他的排序方式. 在这儿我预先指定了一些简写:
  • DISK = physical reads
  • GETS = consistent gets
  • EXEC = execute count
  • CPUT = CPU used by this session
  • SORT = sorts (memory)
  • REDO = redo size
  • WAIT = enqueue waits
  • SENT = bytes sent via SQL*Net to client
    可以用-o"统计名称"来指定其他指标.

3, 如何连接数据库?

    如果你在SQL*Plus中用"sqlplus anysql/anysql@prod"连接的话, 那么运行OTop的命令是"dcba -1 -uanysql/anysql -sprod".
    找出物理读最多的会话? 请执行"dcba -1 -uanysql/anysql -sprod -odisk ".
    找出产生Redo最多的会话? 请执行 "dcba -1 -uanysql/anysql -sprod -oredo ".
    按其他任意统计名称排序的会话? 请执行" dcba -1 -uanysql/anysql -sprod -o"统计名" ".

4, 输出例子

 Top Session ( 16:54:47 - 16:54:53 ) Order by gets
-Statistics-------------------------------------------------------------------------------------
     1     0  logons cumulative   735   122  opened cursors        4     0  user commits
  8567  1427  user calls          826   137  CPU this session      0     0  enqueue waits
    48     8  db block gets      165K   27K  consistent gets    2739   456  physical reads
    55     9  db block changes      0     0  consistent change     0     0  physical writes
     0     0  DBWR buffers scan  2206   367  free buffer req       1     0  free buffer ins
     0     0  CR blocks created   17K  2959  redo size            37     6  redo blks written
  180K   30K  Table scan rows   1125K  187K  Table fetch rowid   744   124  Total parse count
     1     0  Hard parse count   3151   525  execute count     8025K 1337K  bytes via SQL*Net
   529    88  sorts (memory)        0     0  sorts (disk)

-Get/S--Mis/S--Slp/S-IGet/S-IMis/s-SGet/S--Latch------------------------------(Top Latch)-------
   18K    980     17      0      0    963  library cache
  5851    143      0      0      0    143  row cache objects
  7748     74      1      0      0     72  shared pool
  9475     35      1      0      0     34  library cache pin
  6248     26      0      0      0     26  library cache pin allocation

---SID-Serial--VALUE--VAL/S----PCT-----PrevSQL------CurSQL---Host-------------------------------
  1366  40755    61K    10K  37.28  2277403718           0   hostname (username)
  2031   1881    23K   3931  14.37  2277403718  2277403718   hostname (username)
   706  12041    23K   3926  14.35  2277403718  2277403718   hostname (username)
  2677  36301    22K   3768  13.77  2277403718  2277403718   hostname (username)
  1700  64805    10K   1803   6.59           0  1925564194   hostname (username)
   700  44726   2386    397   1.45           0           0   hostname (username)
   864  45587    799    133   0.49   755074748  3481933384   hostname (username)
   141  51698    772    128   0.47           0  3093740634   hostname (username)
   260  47501    711    118   0.43           0           0   hostname (username)
   604  50029    645    107   0.39  3093740634  3093740634   hostname (username)
  1086  42825    587     97   0.36           0  3093740634   hostname (username)
  2400  10629    544     90   0.33  3093740634  3093740634   hostname (username)
   683  23077    463     77   0.28           0  3093740634   hostname (username)
  2124   7060    415     69   0.25  3093740634           0   hostname (username)
   383  60489    400     66   0.24  2254641363  2254641363   hostname (username)
  1993  47707    365     60   0.22           0           0   hostname (username)
    18  21110    338     56   0.21           0           0   hostname (username)
   441  59330    334     55   0.20    97002241  2170752115   hostname (username)
  2313  33672    315     52   0.19           0  1907819273   hostname (username)
    98  27416    312     52   0.19           0           0   hostname (username)

    这里面显示的值皆为两个时间点之前的差值, 第一部份是系统级统计信息的变化, 第二部份是LATCH的信息, 第三部份是Top会话信息.
    在这个例子中, 你可以看到最上面的4个会话贡献了大约全部的逻辑读, 表示这几个会话正在跑的SQL可能是有问题的, 可以根据OTop中给出的SQL的HASH值找到相应的SQL文本, 并进行优化.
    你会发现这是一个不错的工具.

5, 备注

    OTop本身并不会占用较多的资源, 我在2000多个会话的机器上进行测试, OTop中的SQL的运行时间不到一秒.