log file sync等待事件只有一个参数:buffer#。在Oracle10g中该事件被划分到Commit等待类中。处理log file sync事件时请注意以下两点:
1. log file sync等待事件和结束事务(提交或回滚)相关
2. 若进程花费大量时间在log file sync事件上时,通常都说明应用提交次数过多或事务时间太短。
成因,诊断和解决方法
Oracle使用一种被称为生理记录的方法将事务和块变更记录在SGA日志缓冲区中。LGWR进程负责将缓冲区中的内容写入重做日志文件,这通常发生于:
1. 每三秒钟
2. 脏块已经超过了日志缓冲区的1/3或1MB
3. 用户提交或回滚事务
4. 由DBWR进程发起(即所谓的日志预写方式)
因用户提交或回滚而发起的写操作被称为同步写,其他的被称为后台写。log file sync等待事件只与同步写相关。换言之,用户进程在处理一个大事务时会产生很多的日志项,并由此触发LGWR进程执行后台写操作,但是用户会话本身却不需要等待这些后台写操作完成。然后一旦用户进程执行了提交或回滚事务的操作且参数_WAIT_FOR_SYNC设置为TRUE,那么进程就会通知LGWR进程并一直等待log file sync事件直到LGWR把当前的日志项以及提交生成的提交标识都写入日志文件中。在这个日志同步过程中,LGWR进程会一直等待同步写操作的完成,即log fil parallel write事件;而用户会话会一直等待同步进程的完成,即log file sync事件。
一旦某个进程进入log file sync等待,那么它只有两种退出方式。一种就是LGWR通知当前台进程日志同步完成;另一种就是等待超时的情况(通常是1秒),而这时前台进程会检查当前日志SCN号以确定其提交是否已写入磁盘。如果是的话,进程继续执行,否则进程会重新进入等待状态。
注意:永远不要设置_WAIT_FOR_SYNC为FALSE,即使是开发环境或测试环境,否则Oracle根本不能确保实例崩溃时能够恢复已提交的事务。该特性只能做出很假但很漂亮的基线数据来。
一般而言,观察到log file sync司空见惯。它通常会短暂地出现令用户很难留意。但是如果出现大量的log file sync则会拉低整体的响应时间,Oracle会在v$system_event和v$session_event两个视图中都记录下显著的等待统计信息。使用下面的查询找出登录后等待log file sync事件很长的所有当前会话。它结合USER_COMMITS和HOURS_CONNECTED列的值来评估TIME_WAITED的影响:
select a.sid, a.event, a.time_waited, a.time_waited / c.sum_time_waited * 100 pct_wait_time,
d.value user_commits, round((sysdate-b.logon_time)*24) hours_connected
from v$session_event a, v$session b, v$sesstat d,
(select sid, sum(time_waited) sum_time_waited
from v$session_event
where event not in (
'Null event', 'client message', 'KXFX: Execution Message Dequeue - Slave',
'PX Deq: Execution Msg', 'KXFQ: kxfqdeq - normal deqeue', 'PX Deq: Table Q Normal',
'Wait for credit - send blocked', 'PX Deq Credit: send blkd', 'Wait for credit - need buffer to send',
'PX Deq Credit: need buffer', 'Wait for credit - free buffer', 'PX Deq Credit: free buffer',
'parallel query dequeue wait', 'PX Idle Wait', 'slave wait', 'dispatcher timer',
'virtual circuit status', 'pipe get', 'rdbms ipc message', 'rdbms ipc reply', 'pmon timer',
'smon timer', 'PL/SQL lock timer', 'SQL*Net message from client', 'WMON goes to sleep')
having sum(time_waited) >0 group by sid) c
where a.sid=b.sid and a.sid=c.sid and a.sid=d.sid and d.statistic#=(select statistic#
from v$statname where name='user commits')
and a.time_waited > 10000
and a.event = ' log file sync'
order by pct_wait_time, hours_connected;
注意:在RAC环境中LMS后台进程也会产生log file sync等待事件。这是由于Oracle采用预写日志机制的缘故。当前台进程从另一个实例处请求一个数据块时,与该块相关的所有重做项都必须在传输该数据块前被写入到磁盘上。这种情况下,LMS后台进程就会发起日志同步操作并等待log file sync。
下面的章节中将会讨论造成高log file sync等待的三个主要原因
频繁提交
高提交频率是造成后台log file sync等待最主要的原因。用户需要确定产生大量log file sync事件的会话属于批处理程序还是OLTP进程还是中间件的持久层连接。
如果会话是一个批处理进程,那么它很有可能是在一个循环中执行提交操作。找出模块名字并提交给开发人员让他们减少提交次数。这是一个应用的问题,解决的办法就是减少不必要的提交并降低提交的频率。
有些应用开发人员认为如果不经常提交,任务会由于回滚段空间的耗尽而失败那些曾经被死锁问题打击过的人们也被告知要经常性地提交。自然而然地,他们就成为了愿意提交的家伙。其实我们需要做的是要正确地定义事务以及事务结束时提交的内容。事务本身是一系列工作的合集。该合集要么整体成功,要么整体失败。提交或回滚最恰当的位置就是事务结束处。不要为了回滚段空间或死锁问题就引入额外的提交,否则只是治标不治本。如果现有的回滚段都不能满足需求,你作为DBA就有责任提供一个可以满足需求的。如果使用了自动还原管理,那么为回滚表空间分配足够的大小并设置一个合适的回滚保持时间。
引入额外的提交还会产生其他的问题,最著名的就是因回滚(还原)数据被覆盖而引发的ORA-01555:snapshot too old错误。高提交频率还会增加开始和结束事务的开销。每个事务开始时,Oracle分配一个回滚段(被称为回滚段绑定)并更新回滚段头部的事务表。事务结束时该事务表也会被更新,然后执行提交清除工作。对回滚段头部的更新必须记录在日志缓冲区中因为其头部的数据块已被修改。因此最好在应用中做一些必要的调整使得应用只在事务结束时才提交。在循环中的提交可以被移出到循环外这样人物只需要提交一次而不是每次循环都提交。
如果等待了log file sync很长时间的一个会话来自于中间件的持久层连接,那么这种情况就很麻烦了,因为会话服务于多个前端用户。你需要打开10046追踪事件来持续地追踪应用运行状态。在trace file中搜索log file sync。它会告诉你提交的频率。另外,你还需要使用Log Miner工具来探究重做日志。它能展现系统级的提交行为。
在OLTP数据库中,你通常会在系统级而不是在会话级观察到明显的log file sync等待。这可能是由很多OLTP会话短事务造成的。如果真是如此,你能做的就是确保LGWR进程的IO通道顺畅平滑,比如使用异步I/O或将重做日志放到裸设备上或使用专属的IO控制器等。最好是使用固态盘。当然,这是在log file parallel write平均等待时间很差的情况下。否则如果不修改应该,这么做不会带来很大的性能提升。
慢I/O系统
按照下面的SQL查询v$system_event视图以发现LGWR平均等待时间(log file parallel write事件)。10ms或更少的平均时间通常被认为是可接受的:
SQL> select event, total_waits, total_timeouts, time_waited, average_wait
2 from v$system_event
3 where event in ('log file sync', 'log file parallel write');
EVENT TOTAL_WAITS TOTAL_TIMEOUTS TIME_WAITED AVERAGE_WAIT
---------------------------------------- ----------- -------------- ----------- ------------
log file parallel write 32052377 0 26171251 .82
log file sync 35817861 0 44571413 1.24
提升IO吞吐量可以改进log file sync和log file parallel write事件的平均等待时间。然而, 对于一个设计很差且提交过于频繁的应用来说,这不是不改进应用的理由。你可能会混淆数据库层和I/O子系统。请记住,我们不可能在数据库端解决应用的问题。任何对数据库的修改只能让用户认为这是数据库的问题,但真正的问题并不会消失因为主要原因是来自于应用。
也就是说,对于log file sync而言我们有很多办法可以缓解它,比如增加重做日志文件大小,使用光纤连接到存储,使用GB级的以太网或Infiniband网络,高速交换机,专属IO控制器,异步IO或者把日志文件放到RAID0上等。但你要关心的是哪个业务单元需要为新硬件埋单以及提交能有多快。就拿刚才说的那些为例,假设log file parallel write平均等待时间的基线数据为6.1ms,log file sync平均等待时间为9.9ms。那么即使硬件提升了25%或者50%,你还能期待有多少提升呢?平均等待时间即使减少50%换算到会话的响应时间又能改进多少?用户会满意这些许的提升吗?你必须同时评估潜在的收益与新硬件的花销。
事实上不管公司的策略也好还是无权决定购买硬件而言使得我们经常需要妥协。最终,你的重做日志文件很可能在一块与其他系统共享的RAID5上。这对于SAN环境而言几乎是肯定的。存储公司才不会帮你划分出一块足够大的磁盘,而你公司的管理层很可能基于每MB的花销而不是基于性能考量来购买存储。所以,你最终只有拥有很少的硬盘,而且你还被命令必须使得磁盘使用率达到90%。
过大的日志缓冲区
对于有的应用,设置过大的日志缓冲区(大于1MB)也可能会加剧log file sync等待。大缓冲区会减少后台写操作的次数,使得LGWR进程变得“慵懒”因而导致每次需要写更多的日志项到日志文件中。当进程提交时,因为LGWR需要写更多的日志项,所以同步写时间变长。日志缓冲区不能太小使得会话等待log buffer space事件,但也不能太大从而延长了log file sync的等待。一方面你需要一个大缓冲区来应付大量日志产生时的缓冲区空间需求,特别是在日志切换之后;另一方面,你需要一个小缓冲区来增加后台写次数并减少log file sync等待。如果同时满足这两个矛盾的需求?答案就是_LOG_IO_SIZE参数,默认值取LOG_BUFFER的1/3和1MB之间的小者。它是负责通知LGWR进程开始执行写操作的阈值之一。合理地设置该参数可以使你鱼和熊掌兼得。换言之,你可以有一个很大的缓冲区,但_LOG_IO_SIZE很小,这样就增加了后台写从而减少了log file sync等待。当然,没有放之四海而皆准的方法。这种做法也是有开销的。LGWR进程越活跃,其请求的redo copy和redo writeing闩也就越多。
默认情况下,_LOG_IO_SIZE参数在10g中减少到LOG_BUFFER的1/6。这是因为当COMPATIBLE设置为10.0或更高时,_LOG_PARALLELISM_MAX的默认值是2。10g中用LOG_BUFFER除以日志块尺寸(LEBSZ)和kcrfswth的值即可得到_LOG_IO_SIZE。
注意:PROCESSES设置过大也会增加log file sync等待时间。在每个同步操作中,LGWR必须要扫描进程的数据结构以找到哪些会话当前正在等待此事件并写重做日志到磁盘。降低该值可以减少整体的log file sync等待。
1. log file sync等待事件和结束事务(提交或回滚)相关
2. 若进程花费大量时间在log file sync事件上时,通常都说明应用提交次数过多或事务时间太短。
成因,诊断和解决方法
Oracle使用一种被称为生理记录的方法将事务和块变更记录在SGA日志缓冲区中。LGWR进程负责将缓冲区中的内容写入重做日志文件,这通常发生于:
1. 每三秒钟
2. 脏块已经超过了日志缓冲区的1/3或1MB
3. 用户提交或回滚事务
4. 由DBWR进程发起(即所谓的日志预写方式)
因用户提交或回滚而发起的写操作被称为同步写,其他的被称为后台写。log file sync等待事件只与同步写相关。换言之,用户进程在处理一个大事务时会产生很多的日志项,并由此触发LGWR进程执行后台写操作,但是用户会话本身却不需要等待这些后台写操作完成。然后一旦用户进程执行了提交或回滚事务的操作且参数_WAIT_FOR_SYNC设置为TRUE,那么进程就会通知LGWR进程并一直等待log file sync事件直到LGWR把当前的日志项以及提交生成的提交标识都写入日志文件中。在这个日志同步过程中,LGWR进程会一直等待同步写操作的完成,即log fil parallel write事件;而用户会话会一直等待同步进程的完成,即log file sync事件。
一旦某个进程进入log file sync等待,那么它只有两种退出方式。一种就是LGWR通知当前台进程日志同步完成;另一种就是等待超时的情况(通常是1秒),而这时前台进程会检查当前日志SCN号以确定其提交是否已写入磁盘。如果是的话,进程继续执行,否则进程会重新进入等待状态。
注意:永远不要设置_WAIT_FOR_SYNC为FALSE,即使是开发环境或测试环境,否则Oracle根本不能确保实例崩溃时能够恢复已提交的事务。该特性只能做出很假但很漂亮的基线数据来。
一般而言,观察到log file sync司空见惯。它通常会短暂地出现令用户很难留意。但是如果出现大量的log file sync则会拉低整体的响应时间,Oracle会在v$system_event和v$session_event两个视图中都记录下显著的等待统计信息。使用下面的查询找出登录后等待log file sync事件很长的所有当前会话。它结合USER_COMMITS和HOURS_CONNECTED列的值来评估TIME_WAITED的影响:
select a.sid, a.event, a.time_waited, a.time_waited / c.sum_time_waited * 100 pct_wait_time,
d.value user_commits, round((sysdate-b.logon_time)*24) hours_connected
from v$session_event a, v$session b, v$sesstat d,
(select sid, sum(time_waited) sum_time_waited
from v$session_event
where event not in (
'Null event', 'client message', 'KXFX: Execution Message Dequeue - Slave',
'PX Deq: Execution Msg', 'KXFQ: kxfqdeq - normal deqeue', 'PX Deq: Table Q Normal',
'Wait for credit - send blocked', 'PX Deq Credit: send blkd', 'Wait for credit - need buffer to send',
'PX Deq Credit: need buffer', 'Wait for credit - free buffer', 'PX Deq Credit: free buffer',
'parallel query dequeue wait', 'PX Idle Wait', 'slave wait', 'dispatcher timer',
'virtual circuit status', 'pipe get', 'rdbms ipc message', 'rdbms ipc reply', 'pmon timer',
'smon timer', 'PL/SQL lock timer', 'SQL*Net message from client', 'WMON goes to sleep')
having sum(time_waited) >0 group by sid) c
where a.sid=b.sid and a.sid=c.sid and a.sid=d.sid and d.statistic#=(select statistic#
from v$statname where name='user commits')
and a.time_waited > 10000
and a.event = ' log file sync'
order by pct_wait_time, hours_connected;
注意:在RAC环境中LMS后台进程也会产生log file sync等待事件。这是由于Oracle采用预写日志机制的缘故。当前台进程从另一个实例处请求一个数据块时,与该块相关的所有重做项都必须在传输该数据块前被写入到磁盘上。这种情况下,LMS后台进程就会发起日志同步操作并等待log file sync。
下面的章节中将会讨论造成高log file sync等待的三个主要原因
频繁提交
高提交频率是造成后台log file sync等待最主要的原因。用户需要确定产生大量log file sync事件的会话属于批处理程序还是OLTP进程还是中间件的持久层连接。
如果会话是一个批处理进程,那么它很有可能是在一个循环中执行提交操作。找出模块名字并提交给开发人员让他们减少提交次数。这是一个应用的问题,解决的办法就是减少不必要的提交并降低提交的频率。
有些应用开发人员认为如果不经常提交,任务会由于回滚段空间的耗尽而失败那些曾经被死锁问题打击过的人们也被告知要经常性地提交。自然而然地,他们就成为了愿意提交的家伙。其实我们需要做的是要正确地定义事务以及事务结束时提交的内容。事务本身是一系列工作的合集。该合集要么整体成功,要么整体失败。提交或回滚最恰当的位置就是事务结束处。不要为了回滚段空间或死锁问题就引入额外的提交,否则只是治标不治本。如果现有的回滚段都不能满足需求,你作为DBA就有责任提供一个可以满足需求的。如果使用了自动还原管理,那么为回滚表空间分配足够的大小并设置一个合适的回滚保持时间。
引入额外的提交还会产生其他的问题,最著名的就是因回滚(还原)数据被覆盖而引发的ORA-01555:snapshot too old错误。高提交频率还会增加开始和结束事务的开销。每个事务开始时,Oracle分配一个回滚段(被称为回滚段绑定)并更新回滚段头部的事务表。事务结束时该事务表也会被更新,然后执行提交清除工作。对回滚段头部的更新必须记录在日志缓冲区中因为其头部的数据块已被修改。因此最好在应用中做一些必要的调整使得应用只在事务结束时才提交。在循环中的提交可以被移出到循环外这样人物只需要提交一次而不是每次循环都提交。
如果等待了log file sync很长时间的一个会话来自于中间件的持久层连接,那么这种情况就很麻烦了,因为会话服务于多个前端用户。你需要打开10046追踪事件来持续地追踪应用运行状态。在trace file中搜索log file sync。它会告诉你提交的频率。另外,你还需要使用Log Miner工具来探究重做日志。它能展现系统级的提交行为。
在OLTP数据库中,你通常会在系统级而不是在会话级观察到明显的log file sync等待。这可能是由很多OLTP会话短事务造成的。如果真是如此,你能做的就是确保LGWR进程的IO通道顺畅平滑,比如使用异步I/O或将重做日志放到裸设备上或使用专属的IO控制器等。最好是使用固态盘。当然,这是在log file parallel write平均等待时间很差的情况下。否则如果不修改应该,这么做不会带来很大的性能提升。
慢I/O系统
按照下面的SQL查询v$system_event视图以发现LGWR平均等待时间(log file parallel write事件)。10ms或更少的平均时间通常被认为是可接受的:
SQL> select event, total_waits, total_timeouts, time_waited, average_wait
2 from v$system_event
3 where event in ('log file sync', 'log file parallel write');
EVENT TOTAL_WAITS TOTAL_TIMEOUTS TIME_WAITED AVERAGE_WAIT
---------------------------------------- ----------- -------------- ----------- ------------
log file parallel write 32052377 0 26171251 .82
log file sync 35817861 0 44571413 1.24
提升IO吞吐量可以改进log file sync和log file parallel write事件的平均等待时间。然而, 对于一个设计很差且提交过于频繁的应用来说,这不是不改进应用的理由。你可能会混淆数据库层和I/O子系统。请记住,我们不可能在数据库端解决应用的问题。任何对数据库的修改只能让用户认为这是数据库的问题,但真正的问题并不会消失因为主要原因是来自于应用。
也就是说,对于log file sync而言我们有很多办法可以缓解它,比如增加重做日志文件大小,使用光纤连接到存储,使用GB级的以太网或Infiniband网络,高速交换机,专属IO控制器,异步IO或者把日志文件放到RAID0上等。但你要关心的是哪个业务单元需要为新硬件埋单以及提交能有多快。就拿刚才说的那些为例,假设log file parallel write平均等待时间的基线数据为6.1ms,log file sync平均等待时间为9.9ms。那么即使硬件提升了25%或者50%,你还能期待有多少提升呢?平均等待时间即使减少50%换算到会话的响应时间又能改进多少?用户会满意这些许的提升吗?你必须同时评估潜在的收益与新硬件的花销。
事实上不管公司的策略也好还是无权决定购买硬件而言使得我们经常需要妥协。最终,你的重做日志文件很可能在一块与其他系统共享的RAID5上。这对于SAN环境而言几乎是肯定的。存储公司才不会帮你划分出一块足够大的磁盘,而你公司的管理层很可能基于每MB的花销而不是基于性能考量来购买存储。所以,你最终只有拥有很少的硬盘,而且你还被命令必须使得磁盘使用率达到90%。
过大的日志缓冲区
对于有的应用,设置过大的日志缓冲区(大于1MB)也可能会加剧log file sync等待。大缓冲区会减少后台写操作的次数,使得LGWR进程变得“慵懒”因而导致每次需要写更多的日志项到日志文件中。当进程提交时,因为LGWR需要写更多的日志项,所以同步写时间变长。日志缓冲区不能太小使得会话等待log buffer space事件,但也不能太大从而延长了log file sync的等待。一方面你需要一个大缓冲区来应付大量日志产生时的缓冲区空间需求,特别是在日志切换之后;另一方面,你需要一个小缓冲区来增加后台写次数并减少log file sync等待。如果同时满足这两个矛盾的需求?答案就是_LOG_IO_SIZE参数,默认值取LOG_BUFFER的1/3和1MB之间的小者。它是负责通知LGWR进程开始执行写操作的阈值之一。合理地设置该参数可以使你鱼和熊掌兼得。换言之,你可以有一个很大的缓冲区,但_LOG_IO_SIZE很小,这样就增加了后台写从而减少了log file sync等待。当然,没有放之四海而皆准的方法。这种做法也是有开销的。LGWR进程越活跃,其请求的redo copy和redo writeing闩也就越多。
默认情况下,_LOG_IO_SIZE参数在10g中减少到LOG_BUFFER的1/6。这是因为当COMPATIBLE设置为10.0或更高时,_LOG_PARALLELISM_MAX的默认值是2。10g中用LOG_BUFFER除以日志块尺寸(LEBSZ)和kcrfswth的值即可得到_LOG_IO_SIZE。
注意:PROCESSES设置过大也会增加log file sync等待时间。在每个同步操作中,LGWR必须要扫描进程的数据结构以找到哪些会话当前正在等待此事件并写重做日志到磁盘。降低该值可以减少整体的log file sync等待。
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/425993/viewspace-739719/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/425993/viewspace-739719/