共享内存是数据库服务器线程和进程之间通过共享对内存池的访问权来共享数据的一种操作系统功能,共享内存可以起到:减小内存使用和磁盘I/O;在进程间执行高速通信,在informix数据库中,共享内存主要分为常驻部分和虚拟部分;
其中常驻内存大小分布是固定的,不需要动态修改,而虚拟内存部分可以随着系统会话线程的需要而动态分配。
我们知道在常驻内存中最核心的部分就是共享内存缓冲池。缓冲池在数据库中存储从磁盘读取的数据库空间也的缓冲区,也是共享内存常驻部分的最大分配,但是缓冲池空间毕竟有限,不可能同时缓存磁盘中所有数据页,所以缓冲池采用了LRU算法来交换空间
在informix中每个LRU队列有一对已连接的列表组成,即FLRU列表,来跟踪队列中可用的或未修改的页;MLRU列表来跟踪队列中已修改的页,其实在这些队列中存储的也就是指向缓冲池中数据空间页的指针。查看LRU队列使用情况可以通过onstat -R,
informix@bogon[demo_on]:~$ onstat -R
IBM Informix Dynamic Server Version 11.50.UC6DE -- On-Line -- Up 16:28:21 -- 61572 Kbytes
Buffer pool page size: 2048
8 buffer LRU queue pairs priority levels
# f/m pair total % of length LOW HIGH
0 f 125 100.0% 125 121 4
1 m 0.0% 0 0 0
2 f 125 100.0% 125 121 4
3 m 0.0% 0 0 0
4 F 125 100.0% 125 111 14
5 m 0.0% 0 0 0
6 f 125 100.0% 125 111 14
7 m 0.0% 0 0 0
8 f 125 100.0% 125 123 2
9 m 0.0% 0 0 0
10 f 125 100.0% 125 111 14
11 m 0.0% 0 0 0
12 f 125 100.0% 125 111 14
13 m 0.0% 0 0 0
14 f 125 100.0% 125 111 14
15 m 0.0% 0 0 0
0 dirty, 1000 queued, 1000 total, 1024 hash buckets, 2048 buffer size
start clean at 60.000% (of pair total) dirty, or 74 buffs dirty, stop at
50.000%
下面是onconfig文件中缓冲池配置信息:
BUFFERPOOL size=2K,buffers=1000,lrus=8,lru_min_dirty=50.000000,lru_max_dirty=60.000000
通过以上信息可以分析,缓冲池配置单位为个数,然后乘以页大小就是这个缓冲池的总大小,而在缓冲池内部采用LRU方式管理需要将buffers分成几个长度固定的队列,如上设置为LRUS个数为8,所以每个LRU链表队列上实际分配1000/8也就是125个buffer,而配置的LRUS队列实际是被分成了2个LRU对也就是上面我们提到的FLRU和MLRU,FLRU中存放被读入内存中空闲的或未被修改的的页,修改后通常我们称为脏页,将要被移除FLRU队列到MLRU队列上,等到检查点后MLRU上的脏页都被刷新到磁盘,此时MLRU队列上的链表都是空闲都被移动到FLRU,会话在请求将数据读入缓冲池中时,必须先搜寻内存中是否存在这个数据,这个需要通过buffer pool中另一个数据结构hash链表来定位,在此不涉及,如果不存在就需要将数据读入缓冲池中,需要先搜寻FLRU链表上是否有足够的内存空间,在搜寻过程中需要给LRU队列加锁,防止在这个过程中链表被修改,多个LRU链表可以同时提供多个线程会话服务,同时lru_min_dirty和lru_max_dirty这两个参数又限定了LRU队列上脏数据页可以到达的范围,搜寻到一个链表的脏数据页达到了lru_max_dirty就需要相应的线程刷新数据到磁盘。这里还涉及到3个概念就是前台写入、LRU写入,快写入。当sqlexec线程在LRU队列中 无法搜索到空闲的或者未修改的缓冲区时,为了腾出空间,sqlexec线程将一次清仓一个页来容纳要将磁盘读取的数据,这就是所谓的前台写,显然这种性能是很差的,而正常情况下LRU队列中脏数据到达了lru_max_dirty指定的百分比时就会发生LRU写入,这种事通过页清除线程完成,这种的效率就比较高效,而如果在检查点期间由页清除线程执行写入,或者在可能情况下在共享内存缓冲池中的每个页已修改时执行,这个时候就称为块写入,由于检查点期间用户线程必须等待检查点完成,所以,页清除线程不会与大量的线程一起争夺CPU时间,所以这种清除方式是最高效的。合理的调整缓冲池中数据的清除,可以通过:
informix@bogon[demo_on]:~$ onstat -F
IBM Informix Dynamic Server Version 11.50.UC6DE -- On-Line -- Up 16:57:59 -- 61572 Kbytes