头图

数据库管理系统是一种对内存申请和释放操作频率很高的软件,如果每次对内存的使用都使用操作系统函数来申请和释放,效率会比较低,加入自己的内存管理是DBMS系统所必须的。通常内存管理系统会带来以下好处:

  • 申请、释放内存效率更高;
  • 能够有效地了解内存的使用情况;
  • 易于发现内存泄露和内存写越界的问题。

达梦数据库管理系统的内存结构主要包括内存池、缓冲区、排序区、哈希区等。根据系统中子模块的不同功能,对内存进行了上述划分,并采用了不同的管理模式。

视频讲解如下:
https://www.bilibili.com/video/BV1zRF5eaEfE/?aid=113917481195...

一、 内存池

DM Server的内存池包括共享内存池和其他一些运行时内存池。动态视图v$mem_pool详细记录了当前系统中所有的内存池的状态,可通过查询这个动态视图掌握DM Server的内存使用情况。

SQL> select name,sum(total_size) from v$mem_pool group by name;

# 输出的信息如下:

行号     NAME                               SUM(TOTAL_SIZE)     
---------- ---------------------- --------------------
1          SHARE POOL 000                 524288000
2          BACKUP POOL                    4194304
3          RT_MEMOBJ_VPOOL                49283072
4          MON ITEM ARR                   134217728
5          LARGE_MEM_SQL_MONITOR          2097152
6          DSQL BIND DATA HISTORY     10485760
7          CYT_CACHE                      327680
8          XMAL SYS                       65536
9          XBOX SYS                       65536
10         DICT CACHE                     52428800
11         TRX                            704512
12         INJECT HINT                    65536
13         CHECK POINT                    131072
14         HUGE AUX                       65536
15         SQL CACHE MANAGERMENT      104857600
16         MEM FOR PIPE                   65536
17         FLASHBACK SYS                  22879992
18         DBLINK POOL                  131072
19         NSEQ CACHE                   65536
20         PARALLEL LOADER POOL         65536
21         POLICY GRP                   2162688
22         PURG_POOL                    65536
23         DSQL STAT HISTORY            15728640
24         DSQL ET POOL                 11534336
25         SESSION                          30736384
26         RT_HEAP                          344064
27         VIRTUAL MACHINE              12910592

27 rows got

内存池又分为共享内存池和运行时内存池。

1.1 共享内存池

共享内存池是DM Server在启动时从操作系统申请的一大片内存。在DM Server的运行期间,经常会申请与释放小片内存,而向操作系统申请和释放内存时需要发出系统调用,此时可能会引起线程切换,降低系统运行效率。采用共享内存池则可一次向操作系统申请一片较大内存,即为内存池,当系统在运行过程中需要申请内存时,可在共享内存池内进行申请,当用完该内存时,再释放掉,即归还给共享内存池。

DM系统管理员可以通过DM Server的配置文件(dm.ini)来对共享内存池的大小进行设置,共享池的参数为MEMORY_POOL,该配置默认为500M。如果在运行时所需内存大于配置值,共享内存池也可进行自动扩展,INI参数MEMORY_EXTENT_SIZE指定了共享内存池每次扩展的大小,参数MEMORY_TARGET则指定了共享内存池扩展到超过该值后,空闲时会收缩到的大小。

SQL> select para_name,para_value from v$dm_ini 
    where para_name in ('MEMORY_POOL','MEMORY_TARGET','MEMORY_EXTENT_SIZE');

# 输出的信息如下:
行号     PARA_NAME                  PARA_VALUE
---------- ------------------ ----------
1          MEMORY_POOL                500
2          MEMORY_TARGET              15000
3          MEMORY_EXTENT_SIZE     32

1.2 运行时内存池

除了共享内存池,DM Server的一些功能模块在运行时还会使用自己的运行时内存池。这些运行时内存池是从操作系统申请一片内存作为本功能模块的内存池来使用,如会话内存池、虚拟机内存池等。

二、 缓冲区

DM数据库中的缓冲区分为数据缓冲区、日志缓冲区、字典缓冲区和SQL缓冲区。

2.1 数据缓冲区

数据缓冲区是DM Server在将数据页写入磁盘之前以及从磁盘上读取数据页之后,数据页所存储的地方。这是DM Server至关重要的内存区域之一,将其设定得太小,会导致缓冲页命中率低,磁盘IO频繁;将其设定得太大,又会导致操作系统内存本身不够用。

SQL> select para_name,para_value from v$dm_ini
     where para_name in ('BUFFER','KEEP','FAST','RECYCLE');

# 输出的信息如下:
行号             PARA_NAME PARA_VALUE
---------- --------- ----------
1              BUFFER        1000
2              KEEP          8
3              RECYCLE       300

# PARA_VALUE的数值为默认值分别对应 NORMAL缓冲区大小、KEEP缓冲区大小、
# RECYCLE缓冲区大小数据页总数。

DM数据库中有四种类型的数据缓冲区,分别是 NORMAL、KEEP、FAST、RECYCLE。下表说明了每种数据缓冲区的作用。
image.png

系统启动时,首先根据配置的数据缓冲区大小向操作系统申请一片连续内存并将其按数据页大小进行格式化,并置入“自由”链中。数据缓冲区存在三条链来管理被缓冲的数据页,一条是“自由”链,用于存放目前尚未使用的内存数据页,一条是“LRU”链,用于存放已被使用的内存数据页(包括未修改和已修改),还有一条即为“脏”链,用于存放已被修改过的内存数据页。

2.2 日志缓冲区

日志缓冲区是用于存放重做日志的内存缓冲区。为了避免由于直接的磁盘IO而使系统性能受到影响,系统在运行过程中产生的日志并不会立即被写入磁盘,而是和数据页一样,先将其放置到日志缓冲区中。那么为何不在数据缓冲区中缓存重做日志而要单独设立日志缓冲区呢?主要是基于以下原因:

  1. 重做日志的格式同数据页完全不一样,无法进行统一管理;
  2. 重做日志具备连续写的特点;
  3. 在逻辑上,写重做日志比数据页IO优先级更高。

DM数据库提供了参数RLOG_BUF_SIZE对日志缓冲区大小进行控制,日志缓冲区所占用的内存是从共享内存池中申请的,单位为页数量,且大小必须为2的N次方,否则采用系统默认大小1024页。

SQL> select para_name,para_value from v$dm_ini 
     where para_name='RLOG_BUF_SIZE';

# 输出的信息如下:

行号             PARA_NAME     PARA_VALUE
---------- ------------- ----------
1              RLOG_BUF_SIZE 1024

2.3 字典缓冲区

字典缓冲区主要存储一些数据字典信息,如模式信息、表信息、列信息、触发器信息等。每次对数据库的操作都会涉及到数据字典信息,访问数据字典信息的效率直接影响到相应的操作效率。DM8 采用的是将部分数据字典信息加载到缓冲区中,并采用 LRU 算法进行字典信息的控制。配置参数 DICT_BUF_SIZE 控制缓冲区的大小,默认大小为50M。缓冲区配置得太大,会浪费内存空间;配置得太小,可能会频繁地进行淘汰。

SQL> select para_name,para_value from v$dm_ini 
     where para_name='DICT_BUF_SIZE';

# 输出的信息如下:

行号             PARA_NAME     PARA_VALUE
---------- ------------- ----------
1              DICT_BUF_SIZE 50

2.4 SQL缓冲区

SQL缓冲区提供在执行SQL语句过程中所需要的内存,包括计划、SQL语句和结果集缓存。配置参数USE_PLN_POOL控制是否需要计划重用,非0时启动计划重用,为0时禁用计划重用。配置参数CACHE_POOL_SIZE设置SQL缓冲区的大小,默认值为100M。结果集缓存包括SQL查询结果集缓存和DMSQL程序函数结果集缓存,同时设置参数RS_CAN_CACHE=1且USE_PLN_POOL非0时,才会缓存结果集。

SQL> select para_name,para_value from v$dm_ini 
     where para_name in ('USE_PLN_POOL','CACHE_POOL_SIZE');

# 输出的信息如下:

行号             PARA_NAME       PARA_VALUE
---------- --------------- ----------
1              USE_PLN_POOL          1
2              CACHE_POOL_SIZE     100

三、 排序区

排序缓冲区提供数据排序所需的内存空间。当用户执行SQL语句时,常常需要进行排序,所使用的内存就是排序缓冲区提供的。在每次排序过程中,都首先申请内存,排序结束后再释放内存。配置文件dm.ini中的参数SORT_BUF_SIZE用来指定排序缓冲区的大小。

SQL> select para_name,para_value from v$dm_ini 
     where para_name='SORT_BUF_SIZE';

# 输出的信息如下:

行号             PARA_NAME     PARA_VALUE
---------- ------------- ----------
1              SORT_BUF_SIZE 20

四、 哈希区

DM8 提供了为哈希连接而设定的缓冲区,不过该缓冲区是个虚拟缓冲区。之所以说是虚拟缓冲区,因为系统没有真正创建特定属于哈希缓冲区的内存,是在进行哈希连接时,对排序的数据量进行了计算。如果计算出的数据量大小超过了哈希缓冲区的大小,则使用DM8创新的外存哈希方式;如果没有超过哈希缓冲区的大小,实际上使用的还是内存池来进行哈希操作。配置文件 dm.ini 中的参数 HJ_BUF_SIZE 控制缓冲区大小,建议保留默认值,或设置更大的值。

SQL> select para_name,para_value from v$dm_ini 
     where para_name='HJ_BUF_SIZE';

# 输出的信息如下:

行号             PARA_NAME   PARA_VALUE
---------- ----------- ----------
1              HJ_BUF_SIZE 500

赵渝强老师
36 声望15 粉丝

20年以上的IT行业从业经历,清华大学计算机软件工程专业毕业,京东大学大数据学院院长,Oracle中国有限公司高级技术顾问;曾在BEA、甲骨文、摩托罗拉等世界500强公司担任高级软件架构师或咨询顾问等要职,精通大...