--常见等待事件
1.Buffer busy waits
从本质上讲,这个等待事件的产生仅说明了一个会话在等待一个 Buffer(数
据块),但是导致这个现象的原因却有很多种。常见的两种是:
当一个会话视图修改一个数据块,但这个数据块正在被另一个会话修改时。
当一个会话需要读取一个数据块,但这个数据块正在被另一个会话读取到内
存中时。
Oracle 操作的最小单位是块(Block),即使你要修改一条记录,也需要对这
条记录所在的这个数据块做操作。 当你对这个数据块做修改时,其他的会话将
被阻止对这个数据块上的数据做修改(即使其他用户修改的不是当前用户修改的
数据),但是可以以一致性的方式读取这个数据块(from undo)。当前的用户修
改完这个数据块后,将会立即释放掉加在这个数据块上的排他锁,这样另一个会
话就可以继续修改它。 修改操作是一个非常短暂的时间,这种加锁的机制我们
叫 Latch。
当一个会话修改一个数据块时,是按照以下步骤来完成的:
(1)以排他的方式获得这个数据块(Latch)
(2)修改这个数据块。
(3)释放 Latch。
Buffer busy waits 等待事件常见于数据库中存在的热快的时候,当多个用户频
繁地读取或者修改同样的数据块时,这个等待事件就会产生。 如果等待的时间
很长,我们在 AWR 或者 statspack 报告中就可以看到。
2.Buffer latch
内存中数据块的存放位置是记录在一个 hash 列表(cache buffer chains)当中
的。 当一个会话需要访问某个数据块时,它首先要搜索这个 hash 列表,从列表
中获得数据块的地址,然后通过这个地址去访问需要的数据块,这个列表 Oracle
会使用一个 latch 来保护它的完整性。 当一个会话需要访问这个列表时,需要获
取一个 Latch,只有这样,才能保证这个列表在这个会话的浏览当中不会发生变
化。
产生 buffer latch 的等待事件的主要原因是:
(1)Buffer chains 太长,导致会话搜索这个列表花费的时间太长,使其他的
会话处于等待状态。
(2)同样的数据块被频繁访问,就是我们通常说的热快问题。
产生 buffer chains 太长,我们可以使用多个 buffer pool 的方式来创建更多的
buffer chains,或者使用参数 DB_BLOCK_LRU_LATCHES 来增加 latch 的数量,
以便于更多的会话可以获得 latch,这两种方法可以同时使用。
3.Db file scattered read
这个等待事件在实际生产库中经常可以看到,这是一个用户操作引起的等待
事件,当用户发出每次 I/O 需要读取多个数据块这样的 SQL 操作时,会产生这
个等待事件,最常见的两种情况是全表扫描(FTS: Full Table Scan)和索引快
速扫描(IFFS: index fast full scan)。
这个名称中的 scattered( 发散),可能会导致很多人认为它是以 scattered 的方
式来读取数据块的,其实恰恰相反,当发生这种等待事件时,SQL 的操作都是
顺序地读取数据块的,比如 FTS 或者 IFFS 方式(如果忽略需要读取的数据块已
经存在内存中的情况)。
这里的 scattered 指的是读取的数据块在内存中的存放方式,他们被读取到内
存中后,是以分散的方式存在在内存中,而不是连续的。
4.Db file sequential read
这个等待事件在实际生产库也很常见,当 Oracle 需要每次 I/O 只读取单个数
据块这样的操作时,会产生这个等待事件。 最常见的情况有索引的访问(除 IFFS
外的方式),回滚操作,以 ROWID 的方式访问表中的数据,重建控制文件,对
文件头做 DUMP 等。
这里的 sequential 也并非指的是 Oracle 按顺序的方式来访问数据,和 db file
scattered read 一样,它指的是读取的数据块在内存中是以连续的方式存放的。
5.Enqueue
Enqueue 这个词其实是 lock 的另一种描述语。
我们在 AWR 报告中发现长时间的 enqueue 等待事件时,说明数据库中出
现了阻塞和等待,可以关联 AWR 报告中的 enqueue activity 部分来确定是哪一种
锁定出现了长时间等待。
可以使用如下 SQL 查看当前会话等待的 enqueue 名称和类型:
SELECT CHR (TO_CHAR (BITAND (p1, -16777216)) / 16777215)
|| CHR (TO_CHAR (BITAND (p1, 16711680)) / 65535) "Lock",
TO_CHAR (BITAND (p1, 65535)) "Mode"
FROM v$session_wait
WHERE event = 'enqueue';
6.Free buffer waits
当一个会话将数据块从磁盘读到内存中时,它需要到内存中找到空闲的内存
空间来存放这些数据块,当内存中没有空闲的空间时,就会产生这个等待;除此
之外,还有一种情况就是会话在做一致性读时,需要构造数据块在某个时刻的前
映像(image),此时需要申请内存来存放这些新构造的数据块,如果内存中无法
找到这样的内存块,也会发生这个等待事件。
当数据库中出现比较严重的 free buffer waits 等待事件时,可能的原因是:
(1) data buffer 太小,导致空闲空间不够
(2) 内存中的脏数据太多, DBWR 无法及时将这些脏数据写到磁盘中以释
放空间
7.Log file switch(archiving needed)
在归档模式下,这个等待事件发生在在线日志切换(log file switch)时,需
要切换的在线日志还没有被归档进程(ARCH)归档完毕的时候。 当在线日志
文件切换到下一个日志时,需要确保下一个日志文件已经被归档进程归档完毕,
否则不允许覆盖那个在线日志信息(否则会导致归档日志信息不完整)。
出现这样的等待事件通常是由于某种原因导致 ARCH 进程死掉,比如 ARCH
进程尝试向目的地写入一个归档文件,但是没有成功(介质失效或者其他原因),
这时 ARCH 进程就会死掉。 如果发生这种情况,在数据库的 alert log 文件中可
以找到相关的错误信息。
8.Log file switch(checkpoint incomplete)
当一个在线日志切换到下一个在线日志时,必须保证要切换到的在线日志上
的记录的信息(比如一些脏数据块产生的 redo log)被写到磁盘上(checkpoint),
这样做的原因是,如果一个在线日志文件的信息被覆盖,而依赖这些 redo 信息
做恢复的数据块尚未被写到磁盘上(checkpoint),此时系统 down 掉的话, Oracle
将没有办法进行实例恢复。
9.Log file sync
这是一个用户会话行为导致的等待事件,当一个会话发出一个 commit 命令
时,LGWR 进程会将这个事务产生的 redo log 从 log buffer 里面写到磁盘上,以
确保用户提交的信息被安全地记录到数据库中。
会话发出的 commit 指令后,需要等待 LGWR 将这个事务产生的 redo 成功写
入到磁盘之后,才可以继续进行后续的操作,这个等待事件就叫作 log file sync。
当系统中出现大量的 log file sync 等待事件时,应该检查数据库中是否有用
户在做频繁的提交操作。
这种等待事件通常发生在 OLTP 系统上。 OLTP 系统中存在很多小的事务,
如果这些事务频繁被提交,可能引起大量的 log file sync 的等待事件。
10.enq: TX - row lock contention
enq: TX - row lock contention 通常是application级别的问题。
enq是一种保护共享资源的锁定机制,一个排队机制,先进先出(FIFO)。
enq: TX - row lock contention 的产生有几种情况。
<1>Waits for TX in mode 6 :A 会话持有row level lock,B会话等待这个lock释放。
不同的session更新或删除同一个记录。(This occurs when one application is updating or deleting a row that another session is also trying to update or delete. )
解决办法:持有锁的会话commit或者rollback。
<2>In mode 4,唯一索引
表上存在唯一索引,A会话插入一个值(未提交),B会话随后也插入同样的值;A会话提交后,enq: TX - row lock contention消失。
解决办法:持有锁的会话commit或者rollback。
<3>in mode 4 :bitmap
源于bitmap的特性:位图索引的一个键值,会指向多行记录,所以更新一行就会把该键值指向的所有行锁定。
解决办法:commit或者rollback。
<4>其他原因
1.Buffer busy waits
从本质上讲,这个等待事件的产生仅说明了一个会话在等待一个 Buffer(数
据块),但是导致这个现象的原因却有很多种。常见的两种是:
当一个会话视图修改一个数据块,但这个数据块正在被另一个会话修改时。
当一个会话需要读取一个数据块,但这个数据块正在被另一个会话读取到内
存中时。
Oracle 操作的最小单位是块(Block),即使你要修改一条记录,也需要对这
条记录所在的这个数据块做操作。 当你对这个数据块做修改时,其他的会话将
被阻止对这个数据块上的数据做修改(即使其他用户修改的不是当前用户修改的
数据),但是可以以一致性的方式读取这个数据块(from undo)。当前的用户修
改完这个数据块后,将会立即释放掉加在这个数据块上的排他锁,这样另一个会
话就可以继续修改它。 修改操作是一个非常短暂的时间,这种加锁的机制我们
叫 Latch。
当一个会话修改一个数据块时,是按照以下步骤来完成的:
(1)以排他的方式获得这个数据块(Latch)
(2)修改这个数据块。
(3)释放 Latch。
Buffer busy waits 等待事件常见于数据库中存在的热快的时候,当多个用户频
繁地读取或者修改同样的数据块时,这个等待事件就会产生。 如果等待的时间
很长,我们在 AWR 或者 statspack 报告中就可以看到。
2.Buffer latch
内存中数据块的存放位置是记录在一个 hash 列表(cache buffer chains)当中
的。 当一个会话需要访问某个数据块时,它首先要搜索这个 hash 列表,从列表
中获得数据块的地址,然后通过这个地址去访问需要的数据块,这个列表 Oracle
会使用一个 latch 来保护它的完整性。 当一个会话需要访问这个列表时,需要获
取一个 Latch,只有这样,才能保证这个列表在这个会话的浏览当中不会发生变
化。
产生 buffer latch 的等待事件的主要原因是:
(1)Buffer chains 太长,导致会话搜索这个列表花费的时间太长,使其他的
会话处于等待状态。
(2)同样的数据块被频繁访问,就是我们通常说的热快问题。
产生 buffer chains 太长,我们可以使用多个 buffer pool 的方式来创建更多的
buffer chains,或者使用参数 DB_BLOCK_LRU_LATCHES 来增加 latch 的数量,
以便于更多的会话可以获得 latch,这两种方法可以同时使用。
3.Db file scattered read
这个等待事件在实际生产库中经常可以看到,这是一个用户操作引起的等待
事件,当用户发出每次 I/O 需要读取多个数据块这样的 SQL 操作时,会产生这
个等待事件,最常见的两种情况是全表扫描(FTS: Full Table Scan)和索引快
速扫描(IFFS: index fast full scan)。
这个名称中的 scattered( 发散),可能会导致很多人认为它是以 scattered 的方
式来读取数据块的,其实恰恰相反,当发生这种等待事件时,SQL 的操作都是
顺序地读取数据块的,比如 FTS 或者 IFFS 方式(如果忽略需要读取的数据块已
经存在内存中的情况)。
这里的 scattered 指的是读取的数据块在内存中的存放方式,他们被读取到内
存中后,是以分散的方式存在在内存中,而不是连续的。
4.Db file sequential read
这个等待事件在实际生产库也很常见,当 Oracle 需要每次 I/O 只读取单个数
据块这样的操作时,会产生这个等待事件。 最常见的情况有索引的访问(除 IFFS
外的方式),回滚操作,以 ROWID 的方式访问表中的数据,重建控制文件,对
文件头做 DUMP 等。
这里的 sequential 也并非指的是 Oracle 按顺序的方式来访问数据,和 db file
scattered read 一样,它指的是读取的数据块在内存中是以连续的方式存放的。
5.Enqueue
Enqueue 这个词其实是 lock 的另一种描述语。
我们在 AWR 报告中发现长时间的 enqueue 等待事件时,说明数据库中出
现了阻塞和等待,可以关联 AWR 报告中的 enqueue activity 部分来确定是哪一种
锁定出现了长时间等待。
可以使用如下 SQL 查看当前会话等待的 enqueue 名称和类型:
SELECT CHR (TO_CHAR (BITAND (p1, -16777216)) / 16777215)
|| CHR (TO_CHAR (BITAND (p1, 16711680)) / 65535) "Lock",
TO_CHAR (BITAND (p1, 65535)) "Mode"
FROM v$session_wait
WHERE event = 'enqueue';
6.Free buffer waits
当一个会话将数据块从磁盘读到内存中时,它需要到内存中找到空闲的内存
空间来存放这些数据块,当内存中没有空闲的空间时,就会产生这个等待;除此
之外,还有一种情况就是会话在做一致性读时,需要构造数据块在某个时刻的前
映像(image),此时需要申请内存来存放这些新构造的数据块,如果内存中无法
找到这样的内存块,也会发生这个等待事件。
当数据库中出现比较严重的 free buffer waits 等待事件时,可能的原因是:
(1) data buffer 太小,导致空闲空间不够
(2) 内存中的脏数据太多, DBWR 无法及时将这些脏数据写到磁盘中以释
放空间
7.Log file switch(archiving needed)
在归档模式下,这个等待事件发生在在线日志切换(log file switch)时,需
要切换的在线日志还没有被归档进程(ARCH)归档完毕的时候。 当在线日志
文件切换到下一个日志时,需要确保下一个日志文件已经被归档进程归档完毕,
否则不允许覆盖那个在线日志信息(否则会导致归档日志信息不完整)。
出现这样的等待事件通常是由于某种原因导致 ARCH 进程死掉,比如 ARCH
进程尝试向目的地写入一个归档文件,但是没有成功(介质失效或者其他原因),
这时 ARCH 进程就会死掉。 如果发生这种情况,在数据库的 alert log 文件中可
以找到相关的错误信息。
8.Log file switch(checkpoint incomplete)
当一个在线日志切换到下一个在线日志时,必须保证要切换到的在线日志上
的记录的信息(比如一些脏数据块产生的 redo log)被写到磁盘上(checkpoint),
这样做的原因是,如果一个在线日志文件的信息被覆盖,而依赖这些 redo 信息
做恢复的数据块尚未被写到磁盘上(checkpoint),此时系统 down 掉的话, Oracle
将没有办法进行实例恢复。
9.Log file sync
这是一个用户会话行为导致的等待事件,当一个会话发出一个 commit 命令
时,LGWR 进程会将这个事务产生的 redo log 从 log buffer 里面写到磁盘上,以
确保用户提交的信息被安全地记录到数据库中。
会话发出的 commit 指令后,需要等待 LGWR 将这个事务产生的 redo 成功写
入到磁盘之后,才可以继续进行后续的操作,这个等待事件就叫作 log file sync。
当系统中出现大量的 log file sync 等待事件时,应该检查数据库中是否有用
户在做频繁的提交操作。
这种等待事件通常发生在 OLTP 系统上。 OLTP 系统中存在很多小的事务,
如果这些事务频繁被提交,可能引起大量的 log file sync 的等待事件。
10.enq: TX - row lock contention
enq: TX - row lock contention 通常是application级别的问题。
enq是一种保护共享资源的锁定机制,一个排队机制,先进先出(FIFO)。
enq: TX - row lock contention 的产生有几种情况。
<1>Waits for TX in mode 6 :A 会话持有row level lock,B会话等待这个lock释放。
不同的session更新或删除同一个记录。(This occurs when one application is updating or deleting a row that another session is also trying to update or delete. )
解决办法:持有锁的会话commit或者rollback。
<2>In mode 4,唯一索引
表上存在唯一索引,A会话插入一个值(未提交),B会话随后也插入同样的值;A会话提交后,enq: TX - row lock contention消失。
解决办法:持有锁的会话commit或者rollback。
<3>in mode 4 :bitmap
源于bitmap的特性:位图索引的一个键值,会指向多行记录,所以更新一行就会把该键值指向的所有行锁定。
解决办法:commit或者rollback。
<4>其他原因
It could be a primary key problem; a trigger firing attempting to insert, delete, or update a row; a problem with initrans; waiting for an index split to complete; problems with bitmap indexes;updating a row already updated by another session; or something else.
整理自网络