大家好,欢迎来到IT知识分享网。
浅谈数据库系统中的cache
转自:http://www.hellodb.net/2010/08/db-storage.html
Cache和Buffer是两个不同的概念,简单的说,Cache是加速“读”,而buffer是缓冲“写”,前者解决读的问题,保存从磁盘上读出的数据,后者是解决写的问题,保存即将要写入到磁盘上的数据。在很多情况下,这两个名词并没有严格区分,常常把读写混合类型称为buffer cache,本文后续的论述中,统一称为cache。
Oracle中的log buffer是解决redo写入的问题,而data buffer cache则解决data block的读写问题。对于Oracle来说,如果IO没有在SGA中命中,都会发生物理IO,Oracle并不关心底层存储的类型,可能是一套存储系统,可能是本地磁盘,可能是RAID 10,也可能是RAID 5,可能是文件系统,也可能是裸设备,或是ASM。总之,Oracle把底层的存储系统称为存储子系统。
在存储系统中,cache几乎无处不在(在后面的论述中,我们统称为cache),文件系统有cache,存储有cache,RAID控制器上有cache,磁盘上也有cache。为了提高性能,Oracle的一个写操作,很有可能写在存储的cache上就返回了,如果这时存储系统发生问题,Oracle如何来保证数据一致性的问题。
Oracle数据库最重要的特性是:Write ahead logging,在data block在写入前,必须保证首先写入redo log,在事务commit时,同时必须保证redo log被写入。Oracle为了保证数据的一致性,对于redo log采用了direct IO,Direct IO会跳过了OS上文件系统的cache这一层。但是,OS管不了存储这一层,虽然跳过了文件系统的cache,但是依然可能写在存储的cache上。
一般的存储都有cache,为了提高性能,写操作在cache上完成就返回给OS了,我们称这种写操作为write back,为了保证掉电时cache中的内容不会丢失,存储都有电池保护,这些电池可以供存储在掉电后工作一定时间,保证cache中的数据被刷入磁盘,不会丢失。不同于UPS,电池能够支撑的时间很短,一般都在30分钟以内,只要保证cache中的数据被写入就可以了。存储可以关闭写cache,这时所有的写操作必须写入到磁盘才返回,我们称这种写操作为write throuogh,当存储发现某些部件不正常时,存储会自动关闭写cache,这时写性能会下降。
RAID卡上也有cache,一般是256M,同样是通过电池来保护的,不同于存储的是,这个电池并不保证数据可以被写入到磁盘上,而是为cache供电以保护数据不丢失,一般可以支撑几天的时间。还有些RAID卡上有flash cache,掉电后可以将cache中的内容写入到flash cache中,保证数据不丢失。如果你的数据库没有存储,而是放在普通PC机的本地硬盘之上的,一定要确认主机中的RAID卡是否有电池,很多硬件提供商默认是不配置电池的。当然,RAID卡上的cache同样可以选择关闭。
磁盘上的cache,一般是16M-64M,很多存储厂商都明确表示,存储中磁盘的cache是禁用的,这也是可以理解的,为了保证数据可靠性,而存储本身又提供了非常大的cache,相比较而言,磁盘上的cache就不再那么重要。SCSI指令中有一个FUA(Force Unit Access)的参数,设置这个参数时,写操作必须在磁盘上完成才可以返回,相当于禁用了磁盘的写cache。虽然没有查证到资料,但是我个人认为一旦磁盘被接入到RAID控制器中,写cache就会被禁用,这也是为了数据可靠性的考虑,我相信存储厂商应该会考虑这个问题。
至此,我们可以看到Oracle的一个物理IO是经历了一系列的cache之后,最终被写入到磁盘上。cache虽然可以提高性能,但是也要考虑掉电保护的问题。关于数据的一致性,是由Oracle数据库,操作系统和存储子系统共同来保证的。
–EOF–
以下来自冬瓜头:
分享一些东西。磁盘的cache绝对没有被关掉,读io是绝对有cache的,磁盘本身就有预读功能,这个存储系统控制器不会干预,而只会干预写cache。 OS可以通过ioctl来发送scsi mode sense指令从磁盘获取相关cache信息,包括cache是否是write back模式的,是否是write through模式的等等,这些信息磁盘都会告诉控制器。控制器还可以发送指令来告诉磁盘使用何种cache模式,一次性生效,直到断电。
一些外部设备比如Raid适配器、SCSI适配器,都具有自己的缓存,这些缓存如果用来做预读操作,那么没有任何问题,但是如果用Write Back的模式来缓存写数据,那么在这些适配卡没有电池保护其上缓存的情况下,一旦发生供电故障或者Down机,则被缓存的写数据就会永久丢失。在Windows下,Class Driver层有必要知道底层设备是否支持Write Back缓存,如果支持,是否有电池保护等信息。对于没有电池保护的WriteBack模式的设备缓存,Class Driver有两种解决办法:第一种是使用SCSI SYNCHRONIZE CACHE指令来强制让设备将缓存内的所有Dirty写数据写入存储介质中,这种方法需要消耗很多的设备自身的处理资源,因为设备一旦接收到这个指令,就需要全力以赴的执行,而写盘动作是一个慢速动作,在执行这个动作期间,新进入的写IO可能得不到处理,而上层在此时的反应就仿佛设备挂死一般。如果频繁的使用SCSI SYNCHRONIZE CACHE指令,系统整体性能将会非常差。第二种方法则是针对每个写IO使用Write Through标记(FUA置1,即Force Unit Access),这样,设备在从总线上接收这个IO请求写的数据入缓存的同时,将数据写向介质中,只有成功写入了介质,才返回完成信号,而写入完成后,缓存中的这些数据将被视作预读内容处理。使用Write Through的方法虽然也不能提高写性能,但是其相对SCSI SYNCHRONIZE CACHE指令的方式来讲节约了设备处理资源。有些设备并不支持FUA,但是它对待每个写IO都会做Write Through处理,也就是原生的WT模式写缓存。而有些设备则带有电池为其缓存供电,那么这时候,Class Driver就没有必要发起Write Though或者SCSI SYNCHRONIZE CACHE了。
Class Driver使用IOCTL_STORAGE_QUERY_PROPERTY功能函数来向Port Driver查询设备属性信息,其中就有关于写缓存的信息,具体写缓存信息包括:
设备是否具有写缓存
设备具有何种写缓存类型。又包含两种具体类型:Write Back和原生Write Through。
设备是否支持SCSI SYNCHRONIZE CACHE指令。
设备是否具有电池保护。
以上文字来自《大话存储2》,尚未发表,在此也提一下,省的出版之后有人发现之前发过,就说是抄袭,嘿嘿。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/158929.html