http://space.itpub.net/25105315/viewspace-692962
Direct IO
Direct I/O就是当一个进程对系统文件进行IO操作的时候越过系统的文件写缓冲区和读缓存区。
文件系统缓冲区:当系统读写块设备,为了加快读写速度,系统维护了一个块缓冲区。当系统读
数据的时候,先去缓冲区中读,如果没有,再读写磁盘。当系统写数据的时候,先写数据到缓冲
区中。
Oracle 数据库本身已经有自己的数据缓冲区,如果再加上系统文件的缓冲区。数据就被缓冲了俩
次,系统的内存就被浪费了。而且如果Oracle的
数据库 的块比系统文件的块小,那么就会造成系
统的浪费。比如Oracle的块大小是8K,系统文件的块大小是16K,那么Oracle单个读写一次就浪费
了8K的资源。
启用Direct IO
Linux 内核2.4开始有Direct I/O功能, 也就是raw device裸设备。raw device可以在低级别被直
接地和并发地访问。最终块设备ext3也支持Direct IO。OCFS和ASM/ASMLib本身也支持Direct IO。
当然前提条件是存储设备需要支持VERYIO。
Direct IO可以用mount在整个文件系统范围内启用,也可以在应用中使用O_DIRECT打开文件。
Direct IO操作的块大小是512字节。
下面的c程序使用O_DIRECT写文件。
#define _GNU_SOURCE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BLOCKSIZE 512
int main()
{
void *buffer;
int fd;
int i;
unsigned char *file="testfile";
char image[512];
//write
for(i=0;i {
image[i]=66;
}//for
posix_**lign(&buffer, BLOCKSIZE, BLOCKSIZE);
memcpy(buffer, image, sizeof(image));
//int f = open(file, O_CREAT|O_TRUNC|O_WRONLY|O_DIRECT,0060);
fd = open(file,O_CREAT|O_RDWR|O_DIRECT,0060);
if (fd == -1)
{
printf("open %s failed ", file);
return (-1);
}
printf("%d",sizeof(image));
write(fd, buffer, BLOCKSIZE);
close(fd);
free(buffer);
return 0;
}
strace的输出结果中包含了O_DIRECT选项。
strace -o dio.out ./dio
open("testfile", O_RDWR|O_CREAT|O_DIRECT, 060) = 3
在oracle中启用Direct IO。
SQL> show parameter filesystem
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
filesystemio_options string NONE
alter system set filesystemio_options = 'DIRECTIO' scope=spfile;
在OPEN DATABASE是运行strace.
strace -o dbw.txt -p 10231
strace的输出结果:选项为O_DIRECT。
open("/u01/app/oracle11g/oradata/db11g42/system01.dbf", O_RDONLY|O_DIRECT|O_LARGEFILE) = 18
alter system set filesystemio_options = 'NONE' scope=spfile;
在OPEN DATABASE是运行strace.
strace -o dbw.txt -p 10419
strace的输出结果:选项为O_SYNC。
open("/u01/app/oracle11g/oradata/db11g42/system01.dbf", O_RDWR|O_SYNC|O_LARGEFILE) = 18
O_SYNC和O_DIRECT二者都是确保写盘。不同在于O_SYNC还要经过内核的buffer,而O_DIRECT是
direct to disk的,使用应用程序自己的buffer。
测试:
环境:Oracle 11.2.0.2 Redhat Linux AS 5
相关的初始化参数:
*.db_writer_processes=4
*.filesystemio_options='DIRECTIO'
*.pga_aggregate_target=419430400
*.sga_max_size=419430400
*.sga_target=419430400
ROWS:9,999,999 rows
AVG_ROW_LEN: 95 bytes
QUERY: CREATE INDEX with parallel 4
Direct IO打开的时候:
[oracle@dbs4 19126]$ free -mt
total used free shared buffers cached
Mem: 1010 521 489 0 6 354
-/+ buffers/cache: 160 850
Swap: 2047 66 1980
Total: 3058 587 2470
256 seconds
Direct IO关闭的时候:
[oracle@dbs4 19126]$ free -mt
total used free shared buffers cached
Mem: 1010 797 212 0 1 631
-/+ buffers/cache: 164 846
Swap: 2047 148 1898
Total: 3058 946 2111
Elapsed: 00:04:20.75
260 seconds
从测试看free内存增加,cache减少。不知道为什么Oracle不将Direct IO设置成默认值。可能
是有些设备不支持。