Phone:18180207355 提供专业Oracle&MySQL数据恢复、性能优化、迁移升级、紧急救援等服务

昨天在看oracle performance firefighting第6章时,主要是讲buffer cache internal,作者提到dbwr进程
在写脏块时是以batch的方式来完成的,这里我在vmware环境验证一下。如下是简单过程,供大家参考!

下面是strace 的log信息,如下:

从上面信息,你可以看出dbwr进程有个3s 唤醒的机制。下面的写的过程:

先来看下linux的函数pwrite64,如下:

ssize_t pwrite(int fd, const void *buf, size_t count, off_t offset);

前面的19其实就是我们的数据文件,22是我们的undotbs文件。 最后一列的数字就是每次dbwr所写脏块到disk的大小(应该是bytes).
如下是fd信息:

从上面跟踪dbwr进程,我们可以得到什么结论? 那就是dbwr进程在将LRU-W 链表上的脏块写入到disk的过程中,
是batch的方式写入的,其实这个想想也应该是这样,如若不然,那dbwr效率就太差了,难道每次写1个block?
这显然是不可能的。 观察最后一列的数值,你或许已经发现一个问题了,那就是这些数值都是block_size的整数倍。
这是无容置疑的问题,因为写入肯定是以block为单位。 这些数值大小不同,那么说明dbwr进程在写入的时候是存在
一定的机制,或许是通过参数来控制(比如每次写100个block),确实是这样。在8i之前是有个参数_db_block_write_batch,
在后面的版本中已经被废弃了,由新的参数_db_large_dirty_queue 来进行控制. 该参数在10g,11g中默认值为25.

我对该参数是这样的理解的,当LRU-W上的脏块超过25时,那么dbwr进程一次性最少写25个,当然也可能写的更多。但是如果说
脏块没有那么多,比如只有8个,那么就有多少写多少。

根据这个来看,我想lgwr进程在写log buffer到logfile的过程中,应该也是以batch的方式进行的。这里我们也可以来进行验证。

下面是跟踪lgwr进程的log信息:

上面涉及到一个linux 函数semtimedop,是用来操作pv的,这里我们不管。重点看下面的pwrite64的操作。

fd 20是我们的redo文件,如下:

说明当前lgwr进程正在写redo03.log,最后一列的数据是每次lgwr写到redo logfile的大小,单位是byte.可以看到,
每次的写入都是512 byte的整数倍. 可见lgwr写buffer到redo logfile也是以batch的形式来完成的。
我猜测这里oracle应该也是有相关参数来控制的,不过在10g中我没有发现。 这里要说明一下的是并不是_log_io_size
参数,该参数默认log buffer的1/3,虽然显示设置是0.

最后来个简单的总结:

1. dbwr进程在将LRU-W链表上的脏块写入到disk的过程中,是以batch的形式来完成的,每次写入多少,这个是通过
参数_db_large_dirty_queue来进行控制(8i以后版本是这样).

2. lgwr进程在将log buffer中的数据写入到logfile中时,也是以batch的信息,每次写入logfile block_size的整数倍。
每次写入的大小是不一定的,可能是存在一个自动调节的机制。

3. 不管是dbwr还是lgwr进程,每次写入数据的大小都受限制于操作系统,换句话讲,操作所支持的每次最大io是1m,
那么既然你LRU-W上有5m的脏块,你也不能一次性写完,你必须分成多次写完。

    分享到:
  • 手板www.gelinbeier.cn

    好专业,看不懂啊

18180207355
加Q咨询