日志管理–日志优化
优化log的顺序:确定一个合理的log_buffer,设置合理的log file 大小,优化磁盘
1.判断io所在的设备是否存在问题:
select total_waits,time_waited,average_wait,time_waited/total_waits as avg
from v$system_event where event = ‘log file parallel write’;
select * from v$sysstat t where t.NAME in (’redo writes’,'redo blocks written’,'redo write time’);
平均值不应该大于1,单位是10毫秒。
2.减少日志产出
1) 直接路径装载(Direct Loader)以及直接路径插入(对insert使用append提示:insert /*+ append*/)。
2) create table table-name NOLOGGING as select …(CTAS)
3) alter table table-name NOLOGGING move tablespace tablespace-name
4) create index index-name NOLOGGING …
5) alter index index-name NOLOGGING rebuild…
6) 分区操作中,可以添加NOLOGGING短语。
7) truncate命令总是以NOLOGGING方式执行。
日志管理–日志等待和统计2
log buffer space
当进程需要向日志缓冲区里拷贝重做记录时(通常需要redo copy和redo allocation两个latch),发现没有足够的可用空间时,则必须等待log buffer space事件。如果一个进程花费了太多的时间在log buffer space等待事件上,这通常是由于下面两个原因:
1) 日志缓冲区尺寸太小。对于一个繁忙的批处理数据库系统里,一个太小的日志缓冲区(小于512K)会导致进程等待log buffer space。
2) LGWR进程太慢了,这也就是物理I/O速度过慢。可以通过检查log file parallel write等待事件的平均等待时间来判断,如果大于10毫秒,则说明LGWR过慢。可以通过增加日志缓冲区的尺寸或加快LGWR的进程来减少log buffer space等待事件。
而较小尺寸的联机日志文件会引起log file switch completion和log file switch (checkpoint incomplete) 这两个等待事件。log file switch completion表示进程正在等待日志切换完成。而当应用程序产生很多重做,然后由LGWR进程非常快得写日志文件并进行日志切换时,这时DBWR进程还没有把脏数据块写入磁盘以通知checkpoint结束时,这个时候产生log file switch (checkpoint incomplete)等待事件。可以通过增加联机日志文件的尺寸来减少log file switch completion和log file switch (checkpoint incomplete)。
使用如下SQL来显示有关日志缓冲区的latch free的misrate是否很大。
select name,gets,misses,to_char((misses/(gets+misses)) * 100,’990.99′) misrate
from v$latch where name in ( ‘redo allocation’ , ‘redo copy’, ‘redo writing’)
如果是redo copy的丢失率很严重,则可以考虑增加隐藏参数:_log_simultaneous_copies的值。该参数定义了redo copy latch的数量,该参数缺省为CPU数量的两倍。从8i起,该参数成为隐藏参数,因为不适合为系统增加过多的redo copy latch,特别是在OLTP环境中。增加该参数可以减少前台对redo copy latch的等待,但是要注意,过多的redo copy latch可能会使得LGWR等待更长的时间。因为前面我们已经知道,LGWR在确定了要写哪些日志块以后,会等待前台进程完成对这些日志块的操作以后,才开始正式写入。所以,如果很多的前台进程都可以获得redo copy latch以后,就可能引起LGWR要等很长时间才能开始正式写入。
如果是redo allocation的丢失率很严重,需要考虑是否有可能减少重做记录的生成。具体可以看下面有关如何减少重做记录的部分。8i以前,存在一个参数:log_small_entry_max_size,该参数说明了当重做记录的尺寸小于该参数指定值时,使用redo allocation latch来保护重做记录拷贝到日志缓冲区的过程,否则,如果重做记录大于该参数值时,使用redo copy latch来保护这个过程。但是从8i以后,取消了该参数,只要拷贝重做记录到日志缓冲区,就获得redo copy latch。
如果是redo writing的丢失率很严重,则说明LGWR写的时间过长,导致其他进程无法获得该latch。这时可以通过减小_log_io_size来增加LGWR写的频率。具体_log_io_size的用法可以参考下面log buffer的设置部分。
其他统计信息:
redo wastage:该记录表示当日志缓冲区的日志块被写入日志文件时,日志块中没有被利用的空间数量,以字节为单位。因为当把重做记录拷贝到日志缓冲区中的日志块时,需要格式化日志块以后才能实际存放日志信息,这样就会“浪费”一些日志缓冲区空间。上例中,我们可以看到为了格式化日志块而浪费了大约 400(520376-519976)个字节的空间。
4) redo log space requests、redo log space wait time:redo log space requests表示对联机日志文件空间请求的次数,redo log space wait time表示在发出请求空间以后的等待时间。这两个统计信息只有在前台进程请求联机日志文件空间未果的情况下才会增加,这时前台进程等待日志切换完成。在没有人为的发出alter system switch logfile命令的前提下,redo log space requests就表示日志切换的总次数。
5) redo buffer allocation retries:表示再次尝试在日志缓冲区中分配可用空间的次数。当进程第一次没能在日志缓冲区中获得可用空间时,该进程必须等待LGWR刷新日志缓冲区或者等待日志切换完成等,然后会再次尝试获取空间。理想情况下,该统计信息应该为0。注意:这里我们可以获得在拷贝到日志块时必须等待的重做记录的数量所占的比例,计算公式为:redo buffer allocation retries / redo entries。该比例应该接近于0,不应大于1%。如果这个值不断变大则说明服务器进程在获得日志块之前必须等待,这时应该增加日志缓冲区,或者提高LGWR写的效率,也就是提高硬盘物理I/O的速度。
日志管理–写入日志等待和统计1
log file sync等待事件
当用户发出提交或回滚语句时会触发LGWR将重做记录写入联机日志文件,这种触发LGWR的方式叫做同步写(sync writes)触发,而其他剩下的触发LGWR的方式叫做后台写(background writes)。log file sync等待事件只与sync writes有关,而log file parallel write等待事件只与background writes有关。关于LGWR写日志的过程参见日志管理–工作原理.
举例来说,一个用户进程可能进行一个非常大的事务,该事务会产生非常多的重做记录,从而引起很多的background writes。不过,用户session所运行的事务永远不会等待这些background writes完成以后才继续进行。一旦用户进程提交或回滚了事务,那么用户进程将触发LGWR,并且等待log file sync等待事件,一直等到LGWR将当前的重做记录,包括提交或回滚标记全都写入联机日志文件里为止。在这个日志同步(log synchronization)的过程中(将日志缓冲区中的重做记录写入联机日志文件的过程通常也叫做日志同步过程),LGWR进程等待sync write结束,这时它的等待事件为:log file parallel write,而用户session也在等待sync write结束,而这时它等待的等待事件为:log file sync事件。
redolog的产生过程和写入文件过程
产生日志的过程:
1) 服务器进程判断buffer cache中是否存在要求被更新的数据块,如果没有,则从数据文件中将数据块调入buffer cache。然后以排他(Exclusive)模式将该数据块钉住(ping)。注意,这里的数据块包括回滚段段头(事务表)、回滚段数据块以及表所对应的数据块等。事务的产生是需要在回滚段的头部分配一个事务槽(slot)的,然后修改事务槽的状态为未提交,然后在回滚段中将数据块的前镜像放进去。对回滚段的修改是受到redo保护的,就是说上面的操作都是被redo记录下来了。
2) 服务器进程构造一组改动向量(change vector)来描述对数据块所做的变化过程。这组改动向量会放在session的PGA中。实际上,这组改动向量也就是重做记录了。
3) 根据重做记录的大小,判断在日志缓冲区中需要多少空间。
4) 判断当前的SCN值,并将其存放到重做记录中。注意,并不是每个重做记录都具有不同的SCN值,不同的重做记录可能会共享相同的SCN值。
5) 进程获得名为redo copy的latch。 这个latch的作用是将pga的log放到logbuffer中,可以同时往logbuffer写日志的并发数默认为cpu个数的两倍,隐藏参数_log_simultaneous_copies,值得获取可以看看eygle关于redo copy latch的说明。
6) 进程获得名为redo allocation的latch。 这个latch看名字就知道是准备在logbuffer中分配空间的,这个latch的个数竟然有20个,为什么要这么多呢,不是并发数为_log_simultaneous_copies吗?
7) 检查当前是否有其他进程生成了比当前持有的SCN更高的SCN值。如果是,则生成一个新的SCN值,并代替第四步所持有的SCN值。
判断是否有足够的空间容纳当前的重做记录,这里足够的空间既包括日志缓冲区,也包括联机日志文件。这时的逻辑比较复杂。
a) 如果联机日志文件中有足够的空间,则判断日志缓冲区是否有足够的空间。
I. 如果日志缓冲区中没有足够的空间,则进程释放redo copy latch和redo allocation latch。然后在下面的两个选项中做一个选择:
(1)如果这时已经有其他进程或其他条件触发了LGWR,则等待LGWR的完成;
(2)如果这时LGWR没有启动,则触发LGWR启动。为了防止多个进程同时触发LGWR,oracle还引入了名为redo writing的latch。当LGWR进程在写重做记录到联机日志文件的过程中,会一直持有redo writing latch,这时任何试图获得该latch的进程都必须等待。实际上,当进程发现没有足够的空间以后,会立即尝试获取redo writing latch。如果不能获得该latch则说明LGWR正在清空日志缓冲区,所以进程会等待,过一段时间再次尝试去获得该latch;如果获得了该latch,则立即检查这时日志缓冲区中是否还有足够的空间,如果有,则释放redo writing latch,并再次尝试获得redo copy latch和redo allocation latch;如果没有,则释放redo writing latch,同时触发LGWR,这时LGWR获得redo writing latch。
II. 如果日志缓冲区中有足够的空间,则从日志缓冲区中分配所需大小的空间,然后释放redo allocation latch,注意这时仍持有redo copy latch。将改动向量拷贝到所分配的日志缓冲区中,将重做记录所对应的脏数据块挂到检查点队列(checkpoint queue)上去(这个是谁去做呢,后台进程、lgwr?)。最后,释放redo copy latch。
b) 如果联机日志没有足够的空间(可能有一部分可用空间,但是不够用。实际这就是有时你会看到归档日志文件的尺寸会小于联机日志文件的尺寸的原因),则进程会检查是否已经有进程已经触发日志切换了,如果有,则当前进程等待,如果没有则触发日志切换。然后,重复第8步。
9) 当在日志缓冲区中写完重做记录以后,检查当前日志缓冲区中的重做记录的数量是否达到限定值,如果是,则必须触发LGWR进程。
10) 最后,进程更新buffer cache中的数据块。
在执行redo copy的过程中,进程以log file sync事件处于等待。
日志从缓存写出到日志文件:
当LGWR进程启动时,
1) 首先会尝试获取redo writing latch,以确保其他前台进程不会继续触发LGWR进程。
2) 然后会获取redo allocation latch(这里有20个,他准备把所有的都抢到手吗,这是不允许的?),这是为了防止前提进程继续分配更多的日志缓冲区,否则日志缓冲区中的待写入日志文件的日志块不断增长,LGWR是无法确定到底应该写多少日志块的。
3) 在获得了redo allocation latch以后,LGWR开始确定应该写哪些日志块到日志文件。从上次LGWR启动(应该是从控制文件中的检查点进度里面得到的吧?)以来所写的最后一个日志块到这个时间点时的最后一个被使用的日志块,这段范围内的日志块都是要被写入日志文件的,其中既包含写满的日志块,也可能包含还没有写满的日志块。特别注意,这个时候,可能还有前台进程正在向这段范围中的日志块拷贝重做记录。因为LGWR启动时,并不会阻碍前台进程获得redo copy latch,也就不会阻碍前台进程拷贝重做记录了。这样的话,LGWR就不会阻碍前台进程向日志缓冲区的其他可用的日志块中拷贝重做记录了。
4) 在确定了要写哪些日志块以后,生成一个新的SCN号。
5) LGWR释放redo allocation latch,并释放redo writing latch。
6) LGWR会等待前台进程完成对LGWR所要写入文件的日志块的更新操作。这是通过判断这些待写的日志块上的redo copy latch是否都被释放来决定的。
7) LGWR将第4步生成的SCN号拷贝进待写的日志块的块头里,触发物理写操作,将这些待写日志块写入联机日志文件里去。
系统监控–io(4)–硬盘
硬盘测试速度工具:
hdparm -Tt /dev/sda
[root@admin ~]# hdparm -Tt /dev/sda
/dev/sda:
Timing cached reads: 18916 MB in 1.99 seconds = 9484.20 MB/sec
Timing buffered disk reads: 586 MB in 3.00 seconds = 195.06 MB/sec
以下是 3块希捷 ES2 SATA 500G 做 Raid 5 的速度
[root@web ~]# hdparm -Tt /dev/sda
/dev/sda:
Timing cached reads: 18896 MB in 1.99 seconds = 9473.25 MB/sec
Timing buffered disk reads: 368 MB in 3.00 seconds = 122.55 MB/sec
以下是 2块希捷 ES SATA 250G Raid 0 的速度
[root@app1 ~]# hdparm -Tt /dev/sda
/dev/sda:
Timing cached reads: 18028 MB in 1.97 seconds = 9149.56 MB/sec
Timing buffered disk reads: 292 MB in 3.02 seconds = 96.54 MB/sec
-a 表示是否关闭磁盘预读取功能。对于大文件读取,这个显然能提高性能。
-A设置硬盘驱动器缓存读取特性。可能就是硬盘缓存开关
–d设置dma
使用DMA和32位传输可以大幅提升系统性能。使用命令如下:
# /sbin/hdparm -c 1 /dev/hda
此命令将第一个IDE硬盘的PCI总线指定为32位,使用 -c 0参数来禁用32位传输。
在硬盘上使用DMA,使用命令:
# /sbin/hdparm -d 1 /dev/hda
关闭DMA可以使用 -d 0的参数。
更改完成后,可以使用hdparm来检查修改后的结果,使用命令:
# /sbin/hdparm -t /dev/had
为了确保设置的结果不变,使用命令:# /sbin/hdparm -k 1 /dev/hda
Hdparm命令的一些常用的其他参数功能
-g 显示硬盘的磁轨,磁头,磁区等参数。
-i 显示硬盘的硬件规格信息,这些信息是在开机时由硬盘本身所提供。
-I 直接读取硬盘所提供的硬件规格信息。
-p 设定硬盘的PIO模式。
-Tt 评估硬盘的读取效率和硬盘快取的读取效率。
-u <0或1>; 在硬盘存取时,允许其他中断要求同时执行。
-v 显示硬盘的相关设定。
系统监控–io(2)–sar
sar可以显示CPU、运行队列、磁盘I/O、分页 (交换区)、内存、CPU中断、网络等性能数据.
-A:所有报告的总和。
-u:CPU利用率
-v:进程、I节点、文件和锁表状态。
-d:硬盘使用报告。
-r:内存的使用情况。
-g:串口I/O的情况。
-b:缓冲区使用情况。
-a:文件读写情况。
-c:系统调用情况。
-R:进程的活动情况。
-y:终端设备活动情况。
-w:系统交换活动
最近评论