oracle 中的 asynchronous I/O

时间:2022-12-05 07:53:52

异步I/O就是对文件进行读写时,不等读写在硬件设备的完成就返回,当硬件读写完成时可通过信号或回调函数通知调用进程,可以批量的读写,这对频繁的文件读写帮助还是很大的,这个不是新技术,操作系统早就有了, 

 

中文写的比较好的

 

http://blog.csdn.net/eroswang/archive/2009/04/20/4095163.aspx

http://www.360doc.com/content/06/0317/16/2459_81071.shtml

http://www.360doc.com/content/09/0714/10/175938_4261067.shtml

 

 

对于异步IO,一种方法是直接调用libc实现,这个是oralce实现的封装,http://oss.oracle.com/projects/libaio-oracle/

 

另一种是glibc的一个封装,参见http://www.gnu.org/software/libc/manual/html_node/index.html中的13.10 Perform I/O Operations in Parallel ,这个可直接用

 

 

glibc中的异步IO存在的问题

 

在aio_read 和aio_write调用时,

It immediately returns after the operation was enqueued or when an error was encountered.

The calling process is notified about the termination of the request according to the aiocbp->aio_sigevent value. the current status of the request can be queried using aio_error and aio_return functions.

As long as the value returned by aio_error is EINPROGRESS the operation has not yet completed. If aio_error returns zero, the operation successfully terminated, otherwise the value is to be interpreted as an error code.

If the function terminated, the result of the operation can be obtained using a call to aio_return. The returned value is the same as an equivalent call to read would have returned.

 

 

问题就出在当aio_read 或 aio_write 返回时,我们是不知道读或写是否成功,要想获得是否成功,一种方法是通过aiocbp->aio_sigevent 中的信号量或其中定义的回调函数,另一种方法是通过aio_erroraio_return这两个函数,

 

下面是 Open POSIX Test Suitehttp://posixtest.sourceforge.net/)中对这两个函数的测试代码

 

if (aio_write(&aiocb) == -1)
 {
  printf(TNAME " Error at aio_write(): %s/n",
         strerror(errno));
  exit(PTS_FAIL);
 }

 do {
  retval = aio_error( &aiocb);
  if (retval == -1)
  {
   printf(TNAME " Error at aio_error(): %s/n",
    strerror(errno));
   exit(PTS_FAIL);
  }
 } while (retval == EINPROGRESS);

 retval = aio_return(&aiocb);

 

 

if (aio_read(&aiocb) == -1)
 {
  printf(TNAME " Error at aio_read(): %s/n",
         strerror(errno));
  exit(PTS_FAIL);
 }

 /* Wait until end of transaction */
 while ((err = aio_error (&aiocb)) == EINPROGRESS);

 err = aio_error(&aiocb);
 ret = aio_return(&aiocb);

 

 

这里面不是通过信号量来检验读写是否成功的,而是通过不停的轮循来达到看读写是否成功的,EINPROGRESS表示操作还在进行中,没完成。

 

glibc的异步IO理论上能提高读写效率,但对于可靠性要求较高的系统,是加上不停的轮循后,是否还能提高,就需要做实验了

 

如果不采用这种方法,而采用第一种方法的话,数据库的事务就需要有所改变,同步的IO,当数据库完成写操作后,就可认为事务结束,但如果异步IO并采用信号量通知的话,就需要在aio_read 或 aio_write 返回后,还需要等待信号量的通知,只有收到信号后,并确认是写成功才能结束事务,这样的话,对于大量并发的读写,IO信号量的处理将是系统的瓶颈之一,如果采用新线程回调函数的方式的话,新线程的创建和消回也是瓶颈,就是采用线程池的话,线程池的大小,也是一个可能出问题的地方,而且这是经过glibc封装了的,用户是看不到的

 

 

 

 oracle直接对libc的异步IO封装是没有信号或回调函数通知的,但它是不需要,还是只提供了轮循一种方式