DM8达梦数据库体系结构详解
DM8达梦数据库包含实例和数据库两部分。
实例一般是由一组正在运行的 DM 后台进程/线程(监听线程、工作线程、IO线程、调度线程、日志线程等其他线程)以及一个大型的共享内存(内存池、缓冲区、排序区、哈希区等)组成。
数据库指的是磁盘上存放在 DM 数据库中的数据的集合,一般包括:数据文件、日志文件、控制文件以及临时数据文件等。
DM8数据库的整体架构如下图所示:
![在这里插入图片描述](https://i-blog.csdnimg.cn/blog_migrate/b926e7ce0273e0aeb7b866f277ab014d.png)
1.逻辑结构
DM 数据库为数据库中的所有对象分配逻辑空间,并存放在数据文件中。在 DM 数据库内部,所有的数据文件组合在一起被划分到一个或者多个表空间中,所有的数据库内部对象都存放在这些表空间中。同时,表空间被进一步划分为段、簇和页(也称块)。通过这种细分,可以使得 DM 数据库能够更加高效地控制磁盘空间的利用率。图 1.2 显示了这些数据结构之间的关系。
DM8 中存储的层次结构如下:
数据库由一个或多个表空间组成;
每个表空间由一个或多个数据文件组成;
每个数据文件由一个或多个簇组成;
段是簇的上级逻辑单元,一个段可以跨多个数据文件;
簇由磁盘上连续的页组成,一个簇总是在一个数据文件中;
页是数据库中最小的分配单元,也是数据库中使用的最小的 IO 单元。
在 DM 数据库中,表空间由一个或者多个数据文件组成。DM 数据库中的所有对象在逻辑上都存放在表空间中,而物理上都存储在所属表空间的数据文件中。
1.1 表空间
在创建 DM 数据库时,会自动创建 4 个表空间:SYSTEM 表空间、ROLL 表空间、MAIN 表空间和 TEMP 表空间。
SYSTEM表空间:存放了有关DM数据库的字典信息。用户不能在 SYSTEM 表空间创建表和索引。
MAIN表空间:用户默认表空间,用于存放用户业务数据等。
ROLL表空间:该表空间用来存放事务运行过程中执行 DML 操作之前的值,从而为访问该表的其他用户提供表数据的读一致性视图。该表空间完全由 DM 数据库自动维护,用户无需干预。
TEMP表空间:当用户的 SQL 语句需要磁盘空间来完成某个操作时,DM 数据库会从 TEMP 表空间分配临时段。如创建索引、无法在内存中完成的排序操作、SQL 语句中间结果集以及用户创建的临时表等都会使用到 TEMP 表空间。该表空间也完全由 DM 数据库自动维护。
1.2 段
段是簇的上级逻辑分区单元,它由一组簇组成。在同一个表空间中,段可以包含来自不同文件的簇,即一个段可以跨越不同的文件。而一个簇以及该簇所包含的数据页则只能来自一个文件。由于簇的数量是按需分配的,数据段中的不同簇在磁盘上不一定连续。
段的分类:
- 数据段
表段
索引段 - 回滚段
保存了用于恢复数据库操作的信息。对于未提交事务,当执行回滚语句时,回滚记录被用来做回滚变更。 - 临时段(临时段的分配和释放完全由系统自动控制,用户不能手工进行干预)。
1.3 簇
簇是进行存储空间分配的基本单位,数据页的上级逻辑单元,由同一个数据文件中 16 个或 32 个或 64 个连续的数据页组成。段中第一个区叫初始区,后续分配的区称之为后续区。
在 DM 数据库中,簇的大小由用户在创建数据库时指定,默认大小为 16。和数据页的大小一样,一旦创建好数据库,此后该数据库的簇的大小就不能够改变。
1.4 页
数据页(也称数据块)是 DM 数据库中最小的数据存储单元。页的大小对应物理存储空间上特定数量的存储字节,在 DM 数据库中,页大小可以为 4KB、8KB、16KB 或者 32KB,用户在创建数据库时可以指定,默认大小为 8KB,一旦创建好了数据库,则在该库的整个生命周期内,页大小都不能够改变。图 1.2 显示了 DM 数据库页的典型格式。
页头控制信息包含了关于页类型、页地址等信息。
页的中部存放数据,为了更好地利用数据页,
在数据页的尾部专门留出一部分空间用于存放行偏移数组,行偏移数组用于标识页上的空间占用情况以便管理数据页自身的空间。
在绝大多数情况下,用户都无需干预 DM 数据库对数据页的管理。但是 DM 数据库还是提供了选项供用户选择,使得在某些情况下能够为用户提供更佳的数据处理性能。
FILLFACTOR 是 DM 数据库提供的一个与性能有关的数据页级存储参数,它指定一个数据页初始化后插入数据时最大可以使用空间的百分比(100),该值在创建表/索引时可以指定。设置 FILLFACTOR 参数的值,是为了指定数据页中的可用空间百分比(FILLFACTOR)和可扩展空间百分比(100-FILLFACTOR)。可用空间用来执行更多的 INSERT 操作,可扩展空间用来为数据页保留一定的空间,以防止在今后的更新操作中增加列或者修改变长列的长度时,引起数据页的频繁分裂。当插入的数据占据的数据页空间百分比低于 FILLFACTOR 时,允许数据插入该页,否则将当前数据页中的数据分为两部分,一部分保留在当前数据页中,另一部分存入一个新页中。
对于 DBA 来说,使用 FILLFACTOR 时应该在空间和性能之间进行权衡。为了充分利用空间,用户可以设置一个很高的 FILLFACTOR 值,如 100,但是这可能会导致在后续更新数据时,频繁引起页分裂,而导致需要大量的 I/O 操作。为了提高更新数据的性能,可以设置一个相对较低(但不是过低)的 FILLFACTOR 值,使得后续执行更新操作时,可以尽量避免数据页的分裂,提升 I/O 性能,不过这是以牺牲空间利用率来换取性能的提高。
2.物理结构
物理存储结构包括:用于进行功能设置的配置文件;用于记录文件分布的控制文件;用于保存用户实际数据的数据文件、重做日志文件、归档日志文件、备份文件;用来进行问题跟踪的跟踪日志文件等。
2.1 数据文件
数据文件是数据库中最重要的文件类型,是真实数据存储的地方,该文件以 dbf 为扩展名。
2.2 控制文件
控制文件是一个二进制文件,每个 DM 数据库都有一个名为 dm.ctl 的控制文件。它记录了数据库必要的初始信息,其主要包含以下内容:
1、 数据库名称
2、 数据库服务器模式
3、 OGUID唯一标识
4、 数据库服务器版本
5、 数据文件版本
6、 数据库的启动次数
7、 数据库最近一次启动时间
8、 表空间信息,包含表空间名,表空间物理文件路径等,记录了所有数据库中使用的表空间,数组的方式。
9、 控制文件校验码,校验码由数据库服务器在每次修改控制文件后计算生成,保证控制文件合法性,防止文件损坏或手动修改。
控制文件可通过dmctlcvt工具将控制文件与txt文件相互转换进行编辑操作。
2.3 重做日志文件
DM数据库中添加、删除、修改对象或改变数据,数据库都会按照特定的格式将这些操作的执行结果写入到当前的重做日志文件中,每个数据库中至少包含两组重做日志文件。重做日志文件也称为联机日志文件。主要用于数据库的备份与恢复。
其特点如下:
循环使用
每组一个日志文件
只能增加日志组,不能删除
各日志文件大小一致
文件状态分为活动或不活动两种。
2.4 归档日志文件
日志文件分为联机日志文件和归档日志文件。
在归档模式下,数据库会同时将重做日志写入联机日志文件和归档日志文件中分别进行存储。采用归档模式会对系统性能产生影响,但系统在归档模式下运行会更安全。
2.5 配置文件
配置文件是达梦数据库用来设置功能选项的文本文件的集合,配置文件以 ini 为扩展名,它们具有固定的格式。用户可以通过修改配置文件中的某些参数值来达到启用/禁用特定功能项的目标,且可以针对当前系统运行环境设置更优的参数值以提升系统性能
dm.ini 文件是 DM 数据库启动所必须的配置文件,通过配置该文件可以设置 DM 数据库服务器的各种功能和性能选项。
dmmal.ini 是 MAL 系统的配置文件。需要用到 MAL 环境的实例,所有站点的 dmmal.ini 需要保证验证一致。
dmarch.ini 用于本地归档和远程归档的配置。
3.内存结构
3.1 内存池
3.1.1共享内存池
启动时按照参数MEMORY_POOL设置的值向操作系统申请数据库使用的内存
维护数据库系统内部内存的分配与释放。
参数MEMORY_EXTENT_SIZE指定共享内存池每次扩展的大小,单位为MB。
参数MEMORY_TARGET指定共享内存池扩展到设置的值时,收缩可回收空间。
优点:
不依赖操作系统内存管理;
减少对操作系统内存的调用。
3.1.2 运行时内存池
部分功能模块在运行时会使用运行时内存池
3.2 缓冲区
3.2.1 数据缓冲区
数据缓冲区是 DM Server 在将数据页写入磁盘之前以及从磁盘上读取数据页之后,数据页所存储的地方。这是 DM Server 至关重要的内存区域之一,将其设定得太小,会导致缓冲页命中率低,磁盘 IO 频繁;将其设定得太大,又会导致操作系统内存本身不够用。
系统启动时,首先根据配置的数据缓冲区大小向操作系统申请一片连续内存并将其按数据页大小进行格式化。
数据缓冲区存在三条链来管理被缓冲的数据页:
一条是“自由”链,用于存放目前尚未使用的内存数据页,
一条是“LRU”链,用于存放已被使用的内存数据页(包括未修改和已修改),
一条即为“脏”链,用于存放已被修改过的内存数据页。
DM Server的数据缓冲区中有四种类型:
NORMAL:主要是提供给系统处理的一些数据页,没有特定指定缓冲区的情况下,默认缓冲区为 NORMAL;
KEEP:其特性是对缓冲区中的数据页很少或几乎不怎么淘汰出去,主要针对用户的应用是否需要经常处在内存当中,如果是这种情况,可以指定缓冲区为 KEEP。
RECYCLE:供临时表空间使用,
FAST:根据用户指定的 FAST_POOL_PAGES 大小由系统自动进行管理,用户不能指定使用 RECYCLE 和 FAST 缓冲区的表或表空间。
其中,用户可以在创建表空间或修改表空间时,指定表空间属于 NORMAL 或 KEEP 缓冲区。
3.2.2日志缓冲区
存放重做日志的缓冲区
重做日志比数据页IO优先级更高
由RLOG_BUF_SIZE参数进行控制,大小必须为2的N次幂。
该缓冲区的内存从共享池中申请。
3.2.3 字典缓冲区
缓存数据字典信息,如模式信息、表信息、列信息、触发器信息等。
由参数DICT_BUF_SIZE控制大小,默认配置大小为5M。
采用LRU算法。
系统表到内存中的映射。
加速对数据字典的信息查询。
3.2.4 SQL缓冲区
提供在执行SQL语句过程中所需要的内存,包括执行计划、SQL语句和结果集缓存。
由参数USE_PLN_POOL确定执行计划是否复用。
由参数CACHE_POOL_SIZE确定SQL缓存大小。
开启结果集缓存RS_CAN_CACHE=1且USE_PLN_POOL非0。
3.3 排序区
排序区提供数据排序所需要的内存空间,由SORT_BUF_SIZE参数决定大小。每次排序过程中,都首先申请内存,排序结束后再释放内存。当排序缓冲区空间不足时,会申请使用TEMP表空间。
排序缓冲区提供数据排序所需要的内存空间。当用户执行 SQL 语句时,常常需要进行排序,所使用的内存就是排序缓冲区提供的。在每次排序过程中,都首先申请内存,排序结束后再释放内存。
DM Server 提供了参数来指定排序缓冲区的大小,参数 SORT_BUF_SIZE 在 DM 配置文件 dm.ini 中,系统管理员可以设置其大小以满足需求,由于该值是由系统内部排序算法和排序数据结构决定,建议使用默认值 2M。
3.4 哈希区
DM8 提供了为哈希连接而设定的缓冲区,不过该缓冲区是个虚拟缓冲区。
DM Server 在 dm.ini 中提供了参数 HJ_BUF_SIZE 来进行控制,由于该值的大小可能会限制哈希连接的效率,所以建议保持默认值,或设置为更大的值。
4.线程结构
DM 服务器使用“对称服务器构架”的单进程、多线程结构。这种对称服务器构架在有效地利用了系统资源的同时又提供了较高的可伸缩性能。DM 数据库服务器是共享的服务器,允许多个用户连接到同一个服务器上,服务器进程称为共享服务器进程。
DM 进程中主要包括监听线程、IO线程、工作线程、调度线程、日志线程等,以下分别对它们进行介绍。
4.1 工作线程
工作线程是 DM 服务器的核心线程,它从任务队列中取出任务,并根据任务的类型进行相应的处理,负责所有实际的数据相关操作。
DM8 的初始工作线程个数由配置文件指定,随着会话连接的增加,工作线程也会同步增加,以保持每个会话都有专门的工作线程处理请求。为了保证用户所有请求及时响应,一个会话上的任务全部由同一个工作线程完成,这样减少了线程切换的代价,提高了系统效率。当会话连接超过预设的阀值时,工作线程数目不再增加,转而由会话轮询线程接收所有用户请求,加入任务队列,等待工作线程一旦空闲,从任务队列依次摘取请求任务处理。
4.2 监听线程
监听线程主要的任务是在服务器端口上进行循环监听,一旦有来自客户的连接请求,监听线程被唤醒并生成一个会话申请任务,加入工作线程的任务队列,等待工作线程进行处理。它在系统启动完成后才启动,并且在系统关闭时首先被关闭。为了保证在处理大量客户连接时系统具有较短的响应时间,监听线程比普通线程优先级更高。
4.3 IO线程
在数据库活动中,IO 操作历来都是最为耗时的操作之一。当事务需要的数据页不在缓冲区中时,如果在工作线程中直接对那些数据页进行读写,将会使系统性能变得非常糟糕,而把 IO 操作从工作线程中分离出来则是明智的做法。IO 线程的职责就是处理这些 IO 操作。
通常情况下,DM Server 需要进行 IO 操作的时机主要有以下三种:
需要处理的数据页不在缓冲区中,此时需要将相关数据页读入缓冲区;
缓冲区满或系统关闭时,此时需要将部分脏数据页写入磁盘;
检查点到来时,需要将所有脏数据页写入磁盘。
IO 线程在启动后,通常都处于睡眠状态,当系统需要进行 IO 时,只需要发出一个 IO 请求,此时 IO 线程被唤醒以处理该请求,在完成该 IO 操作后继续进入睡眠状态。
IO 线程的个数是可配置的,可以通过设置 dm.ini 文件中的 IO_THR_GROUPS 参数来设置,默认情况下,IO 线程的个数是 2 个。同时,IO 线程处理 IO 的策略根据操作系统平台的不同会有很大差别,一般情况下,IO 线程使用异步的 IO 将数据页写入磁盘,此时,系统将所有的 IO 请求直接递交给操作系统,操作系统在完成这些请求后才通知 IO 线程,这种异步 IO 的方式使得 IO 线程需要直接处理的任务很简单,即完成 IO 后的一些收尾处理并发出 IO 完成通知,如果操作系统不支持异步 IO,此时 IO 线程就需要完成实际的 IO 操作。
4.4 日志FLASH线程
任何数据库的修改,都会产生重做 REDO 日志,为了保证数据故障恢复的一致性,REDO 日志的刷盘必须在数据页刷盘之前进行。事务运行时,会把生成的 REDO 日志保留在日志缓冲区中,当事务提交或者执行检查点时,会通知 FLUSH 线程进行日志刷盘。由于日志具备顺序写入的特点,比数据页分散 IO 写入效率更高。日志 FLUSH 线程和 IO 线程分开,能获得更快的响应速度,保证整体的性能。DM8 的日志 FLUSH 线程进行了优化,在刷盘之前,对不同缓冲区内的日志进行合并,减少了 IO 次数,进一步提高了性能。
如果系统配置了实时归档,在 FLUSH 线程日志刷盘前,会直接将日志通过网络发送到实时备库。如果配置了本地归档,则生成归档任务,通过日志归档线程完成。
4.5 调度线程
调度线程用于接管系统中所有需要定时调度的任务。调度线程每秒钟轮询一次,负责的任务有以下一些:
检查系统级的时间触发器,如果满足触发条件则生成任务加到工作线程的任务队列由工作线程执行;
清理 SQL 缓存、计划缓存中失效的项,或者超出缓存限制后淘汰不常用的缓存项;
检查数据重演捕获持续时间是否到期,到期则自动停止捕获;
执行动态缓冲区检查。根据需要动态扩展或动态收缩系统缓冲池;
自动执行检查点。为了保证日志的及时刷盘,减少系统故障时恢复时间,根据 INI 参数设置的自动检查点执行间隔定期执行检查点操作;
会话超时检测。当客户连接设置了连接超时时,定期检测是否超时,如果超时则自动断开连接;
必要时执行数据更新页刷盘;
唤醒等待的工作线程。
4.6 日志 APPLY 线程
在配置了数据守护的系统中,创建了一个日志 APPLY 线程。当服务器作为备库时,每次接收到主库的物理 REDO 日志生成一个 APPLY 任务加入到任务队列,APPLY 线程从任务队列中取出一个任务在备库上将日志重做,并生成自己的日志,保持和主库数据的同步或一致,作为主库的一个镜像。备库数据对用户只读,可承担报表、查询等任务,均衡主库的负载。
4.7 归档线程
日志归档线程包含异步归档线程,负责远程异步归档任务。如果配置了非实时归档,由日志 FLUSH 线程产生的任务会分别加入日志归档线程,日志归档线程负责从任务队列中取出任务,按照归档类型做相应归档处理。
将日志 FLUSH 线程和日志归档线程分开的目的是为了减少不必要的效率损失,除了远程实时归档外,本地归档、远程异步归档都可以脱离 FLUSH 线程来做,如果放在 FLUSH 线程中一起做会严重影响系统性能。
4.8线程信息的查看
为了增加用户对 DM 数据库内部信息的了解,以及方便数据库管理员对数据库的维护,DM 提供了很多动态性能视图,通过它们用户可以直观地了解当前系统中有哪些线程在工作,以及线程的相关信息。相关动态视图见表 4.1。
达梦社区:https://eco.dameng.com