如何使用oracle提供的SQL_TRACE来跟踪sql的执行情况(2)

发表于:2013-04-15来源:Csdn作者:xuyubotest点击数: 标签:sql执行
线程阻塞是我们在 java 多线程 编程 中经常遇到的问题。由于对后端有限资源的争用以及过度同步等问题,经常会发现 Java dump 中某个资源(锁对象)下有太多

  线程阻塞是我们在 java 多线程编程中经常遇到的问题。由于对后端有限资源的争用以及过度同步等问题,经常会发现 Java dump 中某个资源(锁对象)下有太多的线程处于等待状态,这时候我们通常需要从以下三个方面去诊断这个问题:

  这个锁存在的目的是什么?有没有可能去掉这个锁或者缩小这个锁保护的范围,从而减少线程等待问题发生的几率。

  有哪些线程需要用到这个锁,有没有可能改用其它更好的替代方案。

  当前哪个线程正在持有这个锁,持有的时间是多长,有没有可能缩短持有的时间。

  下面通过实际测试中的dump文件来谈谈如何读懂一个dump文件。

  可以看到一共有4种线程的状态,WAITING,RUNNABLE,TIMED_WAITING (sleeping),BLOCKED。线程阻塞就是BLOCKED。搜索文件中BLOCKED的部分,我们可以看到其中一个:

  "[ACTIVE] ExecuteThread: '91' for queue: 'weblogic.kernel.Default (self-tuning)'" daemon prio=10 tid=0x00002aaae8181000 nid=0x4849 waiting for monitor entry [0x0000000047d4d000]

  java.lang.Thread.State: BLOCKED (on object monitor)

  * 线程名称:

  * 线程类型:daemon

  * 优先级:10,默认是5

  * jvm线程id:jvm内部线程的唯一标识,0x00002aaae8181000

  * 对应系统线程id:和top命令查看的pid对应,不过一个是10进制,一个是16 进制。0x4849

  * 线程状态:BLOCKED

  * 起始栈地址:

  可以看到很多线程状态都是BLOCKED,表示当前线程A正要进入一个同步块,但是被另外一个线程B持有该锁,于是需要等待B,释放锁才有机会重新获取。

  用一种轻松的方式来思考锁,其实挺简单的。数据库中也存在这样的锁。为什么会有锁,打个比喻,一个java对象就像一个大房子,大门永远打开。房子里有很多房间(方法)。这些房间有上锁的和不上锁之分。房门口只放着一把钥匙,这把钥匙可以打开所有上锁的房间。把所有想调用该对象方法的线程比喻成想进入这房子某个房间的人。试想如果只有一个人,肯定是不存在等待别人使用完钥匙归还的时候。如果要是很多人,势必会需要等这把钥匙归还,等钥匙还回来以后,就会有一个人优先得到钥匙。

  由此可以看到,锁是不可避免的,要想正确获取对象的状态,或者修改对象的状态,必须存在这样一种lock。也就意味着,锁的持有时间越久,对性能的影响也就越大,直接结果是大并发情况下,响应时间的延长。回到以前的thread dump,如果通过工具我们发现,线程阻塞比较频繁,并且持续时间很久,不妨多次收集这种转储文件,可以有效的帮助我们分析问题。

  我们刚才看到的转储文件就是XXX测试中捕获到的,通过这些地方,我们发现了一些性能方面的问题。除了线程阻塞,我们分析dump文件还可以找到消耗CPU最多的地方。如果不是windows操作系统,可以通过top(top –H)或者topas命令来查看应用程序的线程信息及占用CPU的情况。找到排序第一位的pid值,按照我们前面解释的,换算成16进制,然后在thread dump日志中搜索该数值nid就能找到耗费CPU的源代码的具体位置,可以精确到行号。

  另外还可以分析是否有很多thread struck在了I/O,例如:

  "New I/O server worker #1-1" prio=10 tid=0x00000000423e0800 nid=0x5bfd runnable [0x00007f7d0a2f4000]

  java.lang.Thread.State: RUNNABLE

  at sun.nio.ch.EPollArrayWrapper.epollWait(Native Method)

  at sun.nio.ch.EPollArrayWrapper.poll(EPollArrayWrapper.java:215)

  或者是thread struck在数据库,例如:

  "[ACTIVE] ExecuteThread: '99' for queue: 'weblogic.kernel.Default (self-tuning)'" daemon prio=10 tid=0x00002aaae8190800 nid=0x4857 runnable [0x0000000048554000]

  java.lang.Thread.State: RUNNABLE

  at java.net.SocketInputStream.socketRead0(Native Method)

  at java.net.SocketInputStream.read(SocketInputStream.java:129)

  at oracle.net.ns.Packet.receive(Packet.java:293)

  at oracle.net.ns.DataPacket.receive(DataPacket.java:92)

  等地方,便于我们定位瓶颈原因。

原文转自:http://blog.csdn.net/xuyubotest/article/details/8158241