内存数据库概览-1992
简介
内存与磁盘的不同点:
- 访问时间存在量级差别;
- 内存是易丢失的,而磁盘是可持久化的。 当然,可能发展出可持久化的内存介质;
- 磁盘是块存储, 而内存是非块存储的;
- 磁盘的顺序访问要比随机访问效率高得多,而内存访问则几乎是相等的;
- 内存离处理器近,直接被其访问,而磁盘则不会。 所以,内存数据更易受软件错误攻击。
内存数据库需要首先回答三个问题:
-
假定整个数据库是可以放入内存的,这个假定是否合理?
对于一些应用来讲,是的。 首先,应用的数据规模是慢慢增长的,前期是肯定可以放入内存的。 再者,对于实时性要求高的应用,数据就一定要放进内存中。
对于大规模数据的应用, 则需要使用分库、分表、分区等方法来达到放入内存的目的。
-
如果缓存只够大,内存库和磁盘库有什么区别?
如果内存够大,那么磁盘库的所有数据也是可以放入到内存中的。 即使如此,也还是有区别的,磁盘库的设计是基于磁盘存储的,而内存库的设计 是基于内存存储的,各种数据结构的优化程度不一样,性能也差别非常大。例如,索引结构、记录结构、缓存结构等。
-
是否可以假定通过引入特殊硬件内存就是非易失性的和可靠的?
不可以,即使是硬件的存在也只能是尽最大可能地提升可靠性,即无法将其消减为0.
基于内存存储的影响
并发控制
磁盘库的并发控制一般是基于锁的,并且一般会使用一个哈希表来记录锁信息,键值是记录的唯一地址标识。加锁对象的粒度可以较小,例如:记录、字段等。
而对于内存库,这种小粒度的锁的争抢没什么优势。 正因如此,内存库一般使用大粒度的锁,例如对整个表加锁,最极端的情况会对整个库加锁。 锁的模式也会较简单得多。 一般会使用内存中的位来作为锁标识。
这里需要专门处理读写冲突,提供一种处理协议。
提交处理
为了应对介质故障,一会要记日志、作备份。在事务提交之前,记录一定是要写入日志的。内存库只有checkpoint和写日志会与磁盘打交道。相对于磁盘库,与磁盘打交道的影响对于性能的影响更严重、更明显。有几种方案用来解决此问题:
- 使用stable main memory来作为写日志的内存与磁盘的缓存。 专门线程用于异步写,不阻塞事务提交时间。
- 使用precommit方法。 一旦日志记录写入日志,不再等待该信息写入磁盘,而是直接释放事务锁。 这种方法只是减少了阻塞时间 ,并不会降低响应时间 。
- 组提交。
访问方法
磁盘库中的B树索引不再适合于内存库。而是使用哈希、T树等结构。 索引中可以直接存储指向数据的指针,而不再是数据本身。
数据表示
数据记录可以利用指针的有效性进行表示,元组可以表示为一个指针集合,每一个指针指向一个数值的内存。 由于一个数据只存储一次,这相当于隐含性地压缩。 另外,指针对于处理变长数据也是简化的。
恢复
恢复有几个组件,第一个是用于做备份、保持数据最新的进程,第二个是从故障中恢复的进程。
在内存库中,检查点和故障恢复是仅需要访问磁盘副本数据的唯一理由。 所以,对磁盘数据的访问可以依据检查点进行裁判和定制。其中一个经验就是,以大块数据来写磁盘。
检查点尽可能少地去打断事务处理。 对于需要打断事务处理的问题,可以使用模糊检查点的方法来做到非同步。
对于恢复时长,可以使用按需加载的方法,将不必要的数据延后加载。关键点是,不知道这个方法有多大性能提升,在某些情况下可能不适合。还有一些方法,是提升磁盘IO性能。
性能
内存库的性能模型与磁盘 库的性能模型不太一样,一个在于磁盘io,另一个在于处理时间 。
内存库系统
主要的内存数据库有OBE, HALO, TPK, MM-DBMS, MARS, System M, Fast Path。