1.Parse 阶段常见的等待事件:
- Library cache pin
这个等待事件和library cache lock 一样是发生在共享池中并发操作引起的事件。通常来讲,如果Oracle 要对一些PL/SQL 或者视图这样的对象做重新编译,需要将这些对象pin到共享池中。 如果此时这个对象被其他的用户特有,就会产生一个library cache pin的等待。
这个等待事件也包含四个参数:
Handle address: 被加载的对象的地址。
Lock address: 锁的地址。
Mode: 被加载对象的数据片段。
Namespace: 被加载对象在v$db_object_cache 视图中namespace名称。
- Library cache pin
这个等待事件和library cache lock
一样是发生在共享池中并发操作引起的事件。通常来讲,如果Oracle 要对一些PL/SQL
或者视图这样的对象做重新编译,需要将这些对象pin到共享池中。 如果此时这个对象被其他的用户特有,就会产生一个library cache
pin的等待。
这个等待事件也包含四个参数:
Handle address: 被加载的对象的地址。
Lock address: 锁的地址。
Mode: 被加载对象的数据片段。
Namespace: 被加载对象在v$db_object_cache 视图中namespace名称
- latch:shared pool
- pin S wait on X
- ibrary cache: mutex X/cursor: pin S
2.Execute阶段常见的等待事件:
- db file sequential read
这个等待事件在实际生产库也很常见,当Oracle 需要每次I/O只读取单个数据块这样的操作时,会产生这个等待事件。 最常见的情况有索引的访问(除IFFS外的方式),回滚操作,以ROWID的方式访问表中的数据,重建控制文件,对文件头做DUMP等。
这里的sequential也并非指的是Oracle 按顺序的方式来访问数据,和db file scattered read一样,它指的是读取的数据块在内存中是以连续的方式存放的。
这个等待事件有三个参数:
File#: 要读取的数据块锁在数据文件的文件号。
Block#: 要读取的起始数据块号。
Blocks:要读取的数据块数目(这里应该等于1)。
- db file scattered read
这个等待事件在实际生产库中经常可以看到,这是一个用户操作引起的等待事件,当用户发出每次I/O需要读取多个数据块这样的SQL 操作时,会产生这个等待事件,最常见的两种情况是全表扫描(FTS: Full Table Scan)和索引快速扫描(IFFS: index fast full scan)。
这个名称中的scattered( 发散),可能会导致很多人认为它是以scattered
的方式来读取数据块的,其实恰恰相反,当发生这种等待事件时,SQL的操作都是顺序地读取数据块的,比如FTS或者IFFS方式(如果忽略需要读取的数据块已经存在内存中的情况)。
这里的scattered指的是读取的数据块在内存中的存放方式,他们被读取到内存中后,是以分散的方式存在在内存中,而不是连续的。
这个等待事件有三个参数:
File#: 要读取的数据块所在数据文件的文件号。
Block#: 要读取的起始数据块号。
Blocks:需要读取的数据块数目。
- Free buffer waits
当一个会话将数据块从磁盘读到内存中时,它需要到内存中找到空闲的内存空间来存放这些数据块,当内存中没有空闲的空间时,就会产生这个等待;除此之外,还有一种情况就是会话在做一致性读时,需要构造数据块在某个时刻的前映像(image),此时需要申请内存来存放这些新构造的数据块,如果内存中无法找到这样的内存块,也会发生这个等待事件。
当数据库中出现比较严重的free buffer waits等待事件时,可能的原因是:
(1) data buffer 太小,导致空闲空间不够
(2) 内存中的脏数据太多,DBWR无法及时将这些脏数据写到磁盘中以释放空间
这个等待事件包含2个参数:
File#: 需要读取的数据块所在的数据文件的文件号。
Block#: 需要读取的数据块块号。
- latch: cache buffers lru chain
Oracle 的 Buffer Cache 是共享内存,可以为众多并发进程并发访问,所以在搜索的过程中必须获取 Latch(Latch是 Oracle 的一种串行锁机制,用于保护共享内存结构),锁定内存结构,防止并发访问损坏内存中的数据(我们必须认识到对于数据的访问、Buffer 的存取就意味着多次的 Latch 访问,而过于严重的 Latch 竞争常常是系统的瓶颈所在.
- buffer busy wait
从本质上讲,这个等待事件的产生仅说明了一个会话在等待一个Buffer(数据块),但是导致这个现象的原因却有很多种。常见的两种是:当一个会话视图修改一个数据块,但这个数据块正在被另一个会话修改时。当一个会话需要读取一个数据块,但这个数据块正在被另一个会话读取到内存中时。Oracle 操作的最小单位是块(Block),即使你要修改一条记录,也需要对这条记录所在的这个数据块做操作。 当你对这个数据块做修改时,其他的会话将被阻止对这个数据块上的数据做修改(即使其他用户修改的不是当前用户修改的数据),但是可以以一致性的方式读取这个数据块(from undo)。当前的用户修改完这个数据块后,将会立即释放掉加在这个数据块上的排他锁,这样另一个会话就可以继续修改它。 修改操作是一个非常短暂的时间,这种加锁的机制我们叫Latch。当一个会话修改一个数据块时,是按照以下步骤来完成的:
以排他的方式获得这个数据块(Latch)
- 修改这个数据块。
- 释放Latch。
- Buffer busy waits等待事件常见于数据库中存在的热快的时候,当多个用户频繁地读取或者修改同样的数据块时,这个等待事件就会产生。如果等待的时间很长,我们在AWR或者statspack 报告中就可以看到。
- 这个等待事件有三个参数。 查看有几个参数我们可以用以下SQL:
SQL> select name, parameter1, parameter2, parameter3 from v$event_name where name='buffer busy waits'; NAME PARAMETER1 PARAMETER2 PARAMETER3 ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- ---------------------------------------------------------------- buffer busy waits file# block# class#
- 在下面的示例中,查询的方法和这个一样,所以其他事件对参数的查询将不做过多的说明。
- File#: 等待访问数据块所在的文件id号。
- Blocks:等待访问的数据块号。
- ID: 在10g之前,这个值表示一个等待时间的原因,10g之后则表示等待事件的类别。
3. Fetch阶段常见的等待事件
- SQL*NET more data to client
当服务器端有太多的数据需要发给客户端时,可能会产生SQL*Net more data to client等待事件,也可能由于网络问题导致服务器无法及时地将信息或者处理结果发送给客户端,同样会产生这个等待。
这个等待时间包含两个参数:
Driver id: 服务器端和客户端连接使用的协议信息。
#bytes: 服务器端向客户端发送消息的字节数。