一、DM逻辑结构概述
1、数据库与实例
在DM7之前版本的DM数据库中,“数据库”和“实例”这两个术语经常可以互相替换, 意义也很相近。在DM7以及之后版本的数据库中,“数据库”和“实例”这两个概念之间有 着很大的差别,甚至可以说它们是两个完全不同的实体。
1.1、数据库
磁盘上静态持久化的文件集合,关机仍然存在。由控制文件、数据文件、重做日志、归档日志、配置文件等组成,保存业务数据、元数据。
1.2、实例
dmserver 进程,动态运行态,数据库启动才存在,关闭就消失;由共享内存池 + 一组后台线程构成,是访问数据库的运行入口。
2、达梦逻辑结构
层级关系
数据库 → 表空间 → 数据文件 → 段 Segment → 簇 Extent → 页 Page(最小 IO 单元)
2.1、页 Page(数据块)
DM 最小 IO、存储单元;创建库时指定,支持 4K/8K/16K/32K,创建数据库后不可修改。
页结构:页头控制信息 + 用户数据 + 空闲空间 + 行偏移数组。
2.2、簇 Extent
同一数据文件内连续多个页,默认 16 页;创建库时指定,创建后不可修改。
创建表 / 索引,至少分配 1 个簇;空间耗尽自动分配新簇。
2.3、段 Segment
由若干簇组成;段可以跨多个数据文件,但一个簇只能属于一个数据文件。
分类:
数据段:存储表业务数据
索引段:存储索引
回滚段 ROLL:MVCC,保存事务前镜像
临时段 TEMP:排序、分组、中间结果集
2.4、表空间 Tablespace
由一个或多个 .dbf 数据文件组成,所有对象(表、索引)存放在表空间。
DM 默认 5 个表空间:
SYSTEM:系统字典、元数据,系统核心
MAIN:普通用户默认业务表空间
ROLL:回滚段,事务回滚、MVCC 多版本
TEMP:临时数据:排序、分组、hash join
HMAIN:HUGE 大表专用表空间
对象:表、索引、视图、序列、存储过程、函数、LOB 大对象、同义词。
二、DM物理存储结构
2.1、配置文件
配置文件是DM数据库用来设置功能选项的一些文本文件的集合,配置文件以ini为扩 展名,它们具有固定的格式,用户可以通过修改其中的某些参数取值来达成如下两个方面的 目标: 1. 启用/禁用特定功能项; 2. 针对当前系统运行环境设置更优的参数值以提升系统性能。
2.1.1 dm.ini
dm.ini是数据库启动必须读取的参数文件,控制实例名、内存大小、文件路径、线程配置、日志配置、归档开关等。
参数类型包括:
手动参数:必须修改 dm.ini 并重启生效;
静态参数:可动态修改,但重启后生效;
动态系统级参数:修改后全局即时生效;
动态会话级参数:修改后只影响新会话或当前会话。
2.1.2 dmmal.ini
dmmal.ini是达梦数据库 MAL消息访问层的通信配置文件,主要用于数据守护、MPP、DMDSC 等集群环境中节点之间的内部通信。
dmmal.ini不是单机数据库必须的文件,不会 dminit 自动生成,必须管理员手动创建编写。只有在dm.ini中设置MAL_INI = 1后,数据库启动时才会读取它。 在数据守护、MPP、DMDSC 等集群中,所有节点的dmmal.ini必须完全一致;修改后需要重启数据库实例才能生效。
2.1.3 dmarch.ini
dmarch.ini是达梦数据库的归档配置文件,用于控制数据库重做日志(Redo Log)的归档策略。当dm.ini中设置ARCH_INI = 1时,数据库启动时会读取此文件来确定归档目标、归档方式、归档文件命名规则等。
2.1.4 dm_svc.conf
dm_svc.conf是达梦数据库的客户端服务名配置文件,它不是数据库服务器端的配置文件,而是放在应用服务器或客户端机器上,用来管理“应用如何连接数据库集群”;DM 软件安装的时候自动生成。
2.1.5 sqllog.ini
sqllog.ini是达梦数据库的 SQL 跟踪日志配置文件,用来控制数据库把哪些 SQL、以什么格式、写到哪个目录、按什么规则切换和保留。
2.1.6 dmrep.ini
dmrep.ini 是达梦高级复制(逻辑复制)的配置文件,注意区分:数据守护 DataWatch 是物理 redo 日志复制;高级复制是逻辑表级复制;由系统自动生成的配置文件,管理员不需要也不应该手动编辑它。
2.1.7 dmllog.ini
dmllog.ini:逻辑日志配置文件,高级复制(逻辑复制)必需,用于捕获表 DML 变更(INSERT/UPDATE/DELETE),生成逻辑日志,作为高级复制数据源。
2.1.8 dmtimer.ini
dmtimer.ini是达梦数据库的 定时器配置文件,主要用于 异步备库 和 异步数据复制 场景。
2.2、控制文件
2.2.1 dm.ctl
控制文件属于数据库文件(不是实例 ini 配置文件),二进制文件,dminit 建库自动生成,记录整个数据库元数据信息,数据库启动 MOUNT 阶段必须读取该文件。
它记录了数据库必要的初始信息,其中主要包含以下内容:
1. 数据库名称;
2. 数据库服务器模式;
3. OGUID 唯一标识;
4. 数据库服务器版本;
5. 数据文件版本;
6. 数据库的启动次数;
7. 数据库最近一次启动时间;
8. 表空间信息,包括表空间名,表空间物理文件路径等,记录了所有数据库中使用的 表空间,数组的方式保存起来;
9. 控制文件校验码,校验码由数据库服务器在每次修改控制文件后计算生成,保证控 制文件合法性,防止文件损坏及手工修改。
查询控制文件所在位置
SELECT PARA_NAME,PARA_VALUE FROM V$DM_INI WHERE PARA_NAME='CTL_PATH';
2.2.2dmtemp.ctl
数据库第一次 OPEN 打开时自动生成,专门记录 TEMP 临时表空间、临时数据文件信息;删除实例重启会重新生成
2.3 数据文件
数据文件后缀`.dbf`,是数据库物理存储,真正存放业务数据、索引、回滚段;属于数据库文件,信息登记在`dm.ctl`控制文件中。
逻辑层级关系:数据库 → 表空间 → 一个 / 多个 dbf 数据文件 → 段 Segment → 簇 Extent → 页 Page(最小 IO 单元)
注意:一个 dbf 文件只能归属一个表空间;一个表空间可以拥有多个 dbf 数据文件
按数据组织形式,包含以下几类内容:
B树数据:最通用的行存储形式,普通表、分区表、B树索引的物理存储都是B树结构。
堆表数据:以挂链形式存储,支持最多128个链表,插入效率高,rowid即时生成无需占磁盘空间。
列存储数据:按列组织,每列含数据段和控制段,适合特定分析场景。
位图索引:每个索引项指向多行数据,而非一行。
ROLL文件:回滚表空间的数据文件,保存事务回滚记录,整个文件就是一个段。
TEMP文件:临时数据文件,当查询的临时结果集内存放不下时,落到TEMP.DBF中,用户创建的临时表也存于此。
2.4、重做日志文件
重做日志又叫联机重做日志,属于数据库物理文件,信息登记在`dm.ctl`控制文件;记录所有 DDL/DML 对数据页的修改,实例崩溃恢复核心依赖。
基本特征:
1. 数量:每个数据库至少 2 个重做日志文件,dminit 建库默认生成 2 个(DAMENG01.log、DAMENG02.log),默认大小 256M。
2. 写入机制:循环覆盖写。写满一个自动切换下一个,全部写完回到第一个,旧内容被覆盖;达梦不支持手动切换重做日志,仅系统自动切换(和 Oracle 不同)。
3. 核心作用
实例崩溃恢复 Crash Recovery:断电、实例异常宕机,重启实例;前滚(重做)已提交事务,回滚未提交事务,保证数据一致性。
归档模式下,作为归档日志 .arc 数据源;
数据守护物理复制数据源,传输 REDO 日志做主备同步。
4. 写入原理:写日志优先原则:内存缓冲区脏页刷入磁盘数据文件前,对应的 REDO 日志必须先写入联机重做日志文件。
5. 日志 LSN(日志序列号):每产生一条 REDO 日志 LSN 递增,用来标记日志顺序,故障恢复、主备同步依赖 LSN 匹配。
2.5、归档日志文件
归档日志文件本质上是联机重做日志的历史持久化副本。数据库开启归档模式后,REDO 日志在切换或写入时会被复制到归档目录,形成不可覆盖、按时间顺序保存的归档文件。
基础要点
1. 产生前提:数据库开启归档模式 ARCHIVE=1 ;非归档模式不会生成 arc 归档文件。
2. 写入时机:联机重做日志写满发生切换,归档线程把即将被覆盖的 redo 内容拷贝生成归档文件。
3. 存储特性:归档日志不会循环覆盖,永久保存,直到手动删除 / 达到 ARCH_SPACE_LIMIT 上限自动删除最早归档。
4. 核心用途
PITR 时间点恢复:恢复到故障发生前任意时间点;非归档只能恢复到备份时刻。
数据守护集群主备同步数据源(实时 / 即时 / 异步归档)。
联机物理备份必须开启归档,否则只能做脱机备份。
Logmnr 日志挖掘,解析 DML 变更。
2.6、逻辑日志文件
达梦的逻辑日志文件是数据复制(DMDRS)功能专用的流式文件,用来记录复制源端的逻辑操作,然后发给从库去 "照做"。
2.7、物理逻辑日志文件
物理逻辑日志文件是达梦里的一个专用概念:它不是单独一类文件,而是按特定格式追加到重做日志里的逻辑操作信息,专门给DBMS_LOGMNR做日志挖掘使用。
2.8、备份文件
达梦备份分为 物理备份、逻辑备份;物理备份由dmrman工具完成,逻辑备份是dexp导出。备份文件不属于数据库运行必需文件,属于灾难恢复介质,数据库正常运行不读取备份文件。
2.9、跟踪日志文件
达梦里的跟踪日志文件不是重做日志,也不是归档日志,而是用于诊断、调试、性能分析的文本日志。它主要分成两类:一类是 SQL 跟踪日志,一类是 事件/Trace 跟踪文件。
trace 跟踪日志:实例运行异常、堆栈、报错、内部线程信息(系统级跟踪)
sqllog.ini:SQL 语句跟踪,记录执行的 SQL(业务 SQL 级别)
trace 看数据库进程内部崩溃、异常;sqllog 看业务执行的 SQL。
2.10、事件日志文件
达梦的事件日志文件是记录数据库实例运行状态和关键事件的文本日志,也常被称为“实例日志”或“系统日志”。它和 SQL 跟踪日志不同,不需要额外开启,实例启动后就会自动生成。
命名格式:dm_实例名_年月.log
2.11、数据重演文件
达梦的数据重演文件是数据库通信捕获重演功能的产物,捕获数据库与客户端之间的通信消息(真实业务负载)生成文件;可在测试环境回放,复现该时间段的数据库操作,用于问题复现、系统调试与性能调优。
三、DM内存结构
DM 内存整体分为共享内存(实例启动分配,所有会话共享)、运行时私有内存(会话 / SQL 执行时动态申请)两大块;四大组成:内存池、缓冲区、排序区、哈希区。
3.1、内存池
内存池用来减少频繁向操作系统申请、释放内存的开销;有以下两种:
1. 共享内存池(主内存池)
参数:MEMORY_POOL,实例启动时一次性向 OS 申请大块内存。
作用:数据库内部小块内存申请从这里分配,减少频繁操作系统调用;内存不足时可自动扩展,空闲可收缩。
用途:存放各种内核小对象、控制结构、字典、SQL 缓存等零碎内存需求。
2. 运行时内存池(私有池)
会话内存池:建立连接时创建,会话断开释放;保存会话事务信息、上下文。
虚拟机内存池:SQL 执行时创建,语句执行结束释放;存放 SQL 执行相关虚拟机结构。
特点:会话私有,其他会话不可见。
3.2、缓冲区
3.2.1、数据缓冲区
作用:缓存磁盘数据文件(dbf)的数据页镜像,减少磁盘 IO;读数据优先访问内存缓冲区。
管理三条链表:
1. 自由链:空闲未使用内存页
2. LRU 链:已使用页面,内存不足按 LRU 淘汰(最近最少使用)
3. 脏链:已经修改、还没刷回磁盘的脏数据页;检查点 / FLUSH 线程负责把脏页刷盘
数据缓冲区内部又细分为四种类型:
NORMAL:默认缓冲区,处理未特殊指定的数据页,由 BUFFER 参数控制大小
KEEP:让指定表/表空间的数据页常驻内存,几乎不被淘汰,需在建表空间时显式指定
RECYCLE:供临时表空间使用,由 RECYCLE 参数控制,大量使用临时表或排序时可调大
FAST:存放反复访问的热页,由 FAST_POOL_PAGES 控制(单位为页数),系统自动管理,用户不能指定
3.2.2、日志缓冲区
存放重做日志的内存区域。为了避让磁盘 I/O 拖慢事务,日志先写入缓冲区,再由刷盘线程统一落盘。由RLOG_BUF_SIZE控制(单位为日志页个数,默认 1024 页,必须是 2 的 N 次方),内存从共享内存池中申请。
3.2.3、字典缓冲区
存数据字典信息(模式、表、列、索引等元数据)。每次操作都涉及字典信息,缓存命中率高可显著减少 I/O。由DICT_BUF_SIZE控制(单位 MB,默认约 20M),采用 LRU 算法淘汰。
3.2.4、SQL 缓冲区
存 SQL 执行计划、原始语句及结果集,用于软解析——相同 SQL 再次执行时直接复用计划。由CACHE_POOL_SIZE控制,需配合USE_PLN_POOL(非 0 时启用计划重用)才能生效。
3.3、排序区
排序区属于SQL 执行阶段的私有内存(不是共享内存),供单个 SQL 语句使用;用于排序类操作:ORDER BY、GROUP BY、DISTINCT、UNION、MERGE JOIN等。
传统排序机制:SORT_FLAG = 0
每个排序操作最多使用 SORT_BUF_SIZE 大小的内存。超过后会把中间结果写入临时表空间,使用磁盘排序。
优点:单个 SQL 排序内存受限,不容易拖垮整体实例。
缺点:大排序容易频繁刷盘,响应时间变长。
新排序机制:SORT_FLAG = 1
排序操作在全局排序区中按需申请,最多扩展到 SORT_BUF_GLOBAL_SIZE。
优点:大排序可以一次性获得更多内存,减少刷盘。
缺点:如果某条异常 SQL 占用过多排序内存,可能耗尽全局排序区,后续排序会话会报 -544: 超出全局排序空间。
3.4、哈希区
达梦的哈希区是一个虚拟缓冲区,专门服务于 HASH JOIN(哈希连接) 和 HAGR(哈希分组) 等需要动态构建哈希表的操作。它本身不是一块预分配的真实内存,而是一套“配额管理机制”,实际运行时从共享内存池中按需借用内存。
3.5、SSD缓冲区
达梦的SSD 缓冲区是内存与磁盘之间的一个二级缓存层,它本身不是内存缓冲区,而是把 SSD 文件当作缓存介质,用来承接数据缓冲区淘汰出来的数据页,减少直接访问机械磁盘或远端存储的 I/O。
四、管理DM线程
DM 数据库是单进程多线程架构:一个 dmserver 进程,内部包含大量线程;分为监听线程、工作线程、IO 线程、调度线程、日志相关线程、其他辅助后台线程。
4.1、监听线程
达梦的监听线程是数据库对外连接的第一道入口,线程名为 dm_lsnr_thd。
核心职责
监听线程只在配置端口上循环监听,默认端口为 5236,端口范围是 1024–65534。
当客户端发起连接请求时,监听线程被唤醒,生成一个会话申请任务,加入工作线程的任务队列,由工作线程继续处理。
它的典型特征是:
优先级高:比普通线程优先级更高,保证连接响应更短。
最后启动、最先关闭:实例启动完成后才启动,实例关闭时首先被关闭。
按需唤醒:没有连接请求时通常处于休眠状态,有连接时才被唤醒。
数量固定:一般只有 1 个监听线程,不可像工作线程那样通过参数扩容。
4.2、工作线程
DM 工作线程分为两类:会话工作线程、任务工作线程,属于 dmserver 后台线程。参数WORKER_THREADS(会话工作线程数量)、TASK_THREADS(任务工作线程数量)。
一、会话工作线程
作用
负责处理客户端会话提交的 SQL 请求,执行 SQL、返回结果,处理用户业务操作。
两种工作模式,由 STHD_FLAG 控制:
1. 非线程池模式(默认):一会话一线程
会话建立之后,固定分配一条会话工作线程;该会话所有 SQL 都由这条线程处理;会话断开,线程回收。优点:减少线程切换开销。
2. 线程池模式
线程池内固定一批会话工作线程;多个会话共用线程池,会话请求进入任务队列,空闲线程领取任务处理。适合大量短连接场景,节省线程资源。
来源:监听线程收到连接,建立会话,把会话任务交给会话工作线程。
二、任务工作线程
作用
处理数据库内部异步后台任务,不处理用户 SQL。
典型任务:
备份、还原异步任务
审计异步写入
部分 DDL 后台处理
各种内核异步消息任务
4.3、IO线程
IO 线程负责数据文件(dbf)的磁盘读写:
1. 读:将磁盘上的数据页加载到数据缓冲区 BUFFER;
2. 写:将 BUFFER 里的脏数据页刷入磁盘数据文件 dbf
IO 线程通常在以下场景被唤醒:
数据页不在数据缓冲区,需要从磁盘读入;
缓冲区满、系统关闭时,需要把部分脏页写入磁盘;
检查点到来时,需要把脏页集中刷盘。
大多数情况下,IO 线程处于睡眠状态,只有收到 IO 请求才会被唤醒,完成后继续休眠。
4.4、调度线程
调度线程是数据库的后台总管线程,每秒执行一轮轮询,负责处理数据库各类定时、管理类任务。
主要工作内容
1. 触发自动检查点;
2. 会话超时检测,断开长时间空闲的会话;
3. 清理 SQL 缓存、执行计划缓存;
4. 内存池 / 缓冲区动态扩展、收缩;
5. 触发器定时调度;
6. 唤醒等待状态的工作线程;
7. 收集系统统计信息。
注意:调度线程只是触发检查点,脏页真正刷盘交给 IO 线程执行,调度线程本身不做 IO 刷盘。
4.5、日志FLUSH线程
负责将重做日志缓冲区(RLOG_BUF)中的 REDO 日志记录,写入磁盘上的联机重做日志文件 (*.log)。遵循写日志优先原则。
主要工作
1. 当重做日志缓冲区写满 / 事务提交 / 检查点触发时,FLUSH 线程启动,把 redo 落盘到联机日志。
2. 实时归档场景:在写入本地联机日志之前,先将 REDO 发送给实时备库;收到备库确认后,再写入本地联机日志。
3. 生成的联机日志文件写满后,切换下一个联机日志,同时通知归档线程执行归档。
4.6、日志归档线程
当联机重做日志文件(.log)写满发生日志切换后,** 归档线程将已经写满的联机日志文件复制生成归档日志文件(.arc)**,完成本地归档、异步远程归档任务。
工作要点
1. 触发时机:联机日志文件写满,发生日志切换,日志 FLUSH 线程通知归档线程。
2. 任务:把已切换完成的联机日志拷贝到归档目录,生成 .arc 归档日志;支持本地归档、异步远程归档。
3. 不处理实时归档:实时归档的 REDO 发送工作是**日志 FLUSH 线程完成,不属于归档线程。
4. 归档失败会触发挂起实例(取决于归档相关配置,ARCH_SUSPEND_FLAG),防止联机日志被覆盖丢失。
4.7、日志APPLY线程
达梦的日志 APPLY 线程是数据守护备库特有的线程,负责把从主库接收到的 REDO 日志在备库上重做,从而保持主备数据一致。日志 APPLY 线程只存在于备库实例中,主库没有这个线程。
工作要点
1. 接收来源:
实时 / 即时归档:接收主库 FLUSH 线程传输过来的 REDO 记录;
异步归档:读取传输到备库的归档文件 *.arc 。
2. 按照LSN 序列号顺序,在备库重做数据页修改(物理重演)。
3. 备库重演修改数据页的过程中,备库自身也会生成属于备库的 REDO 日志。
4. 视图 V$RLOG_APPLY 查看重演进度、当前应用 LSN、延迟。
4.8、定时器线程
达梦的定时器线程是一个专门处理“按时间点/时间间隔触发任务”的后台线程,默认不启动,需要把dm.ini中的TIMER_INI设为 1 后,实例启动时才会创建该线程。
主要工作内容
线程启动后,每秒扫描定时器链表,判断定时任务是否到达触发时间;满足条件,则把任务交给任务工作线程执行。
负责三类任务:
1. 作业调度(DBMS_JOB 定时任务,定时备份、定时统计等)
2. 逻辑日志异步归档
3. 数据守护主库(PRIMARY)异步归档日志发送
4.9、逻辑日志归档线程
达梦的逻辑日志归档线程是日志归档线程dm_rsyswrk_thd内部的一类子线程,专门处理逻辑日志相关的归档和发送任务。只有开启数据复制功能,实例才会创建逻辑日志归档线程,分为:本地逻辑日志归档线程、远程逻辑日志归档线程。
本地逻辑日志归档线程
1. 从本地归档任务队列取出任务,**生成逻辑日志,写入逻辑日志文件(llog)。
2. 如果配置同步异地归档,生成远程归档任务放入任务队列,交给远程逻辑日志归档线程。
逻辑日志(llog):记录行级 DML 操作,用于高级复制,不是 REDO 重做日志。
远程逻辑日志归档线程
1. 读取远程归档任务,执行同步 / 异步发送逻辑日志到复制目标端。
2. 目标端拿到 llog 逻辑日志,执行逻辑重演(执行 DML 语句),完成数据复制。
4.10、MAL系统相关线程
MAL 系统是 DM实例间高速通信系统,基于 TCP/IP;用于数据守护、MPP、远程归档、DSC等多实例场景;单实例单机环境不启用 MAL,不会创建 MAL 线程。 MAL 包含 3 类核心线程:MAL 监听线程、MAL 发送工作线程、MAL 接收工作线程
MAL 监听线程
作用:监听 MAL 端口(dmmal.ini 中 MAL_PORT),接收其他数据库实例的 MAL 连接请求(不是客户端连接!客户端连接是 dm_lsnr_thd 监听 5236)。
收到对端实例连接请求,建立 MAL 链路,交给 MAL 收发线程处理实例间消息。
2. MAL 发送工作线程
负责向外发送 MAL 消息包:REDO 日志包、集群消息、控制消息;
典型场景:主库通过 MAL 把 REDO 包发给备库;MPP 节点间交换消息。
3. MAL 接收工作线程
接收其他实例发来的 MAL 数据包;
收到 REDO 包,投递到 APPLY 重演线程做物理重演;集群消息交给对应内核模块处理。
4.11、其他线程
不属于前面核心业务 / IO / 日志类,属于辅助管理、审计、跟踪、关闭相关线程。
1. PURGE 线程 dm_purge_thd
作用:清理回滚段 UNDO 页面,回收过期回滚页,释放回滚段空间。
事务结束后,旧版本数据保留用于 MVCC;当事务不再需要该回滚页时,PURGE 线程自动清理。
不删除正在使用的回滚页,保障查询的读一致性。
2. 审计线程 dm_audit_thd
作用:异步写入审计记录到审计文件 / 审计表。
用户开启审计功能后,会话产生的审计信息先放到内存队列,审计线程负责落盘持久化;不拦截 SQL,只负责审计信息写入。
不开审计,该线程不工作。
3. 退出线程 dm_quit_thd
作用:数据库正常关闭时执行收尾工作。
处理实例关闭流程:停止业务线程、刷新缓冲区、关闭各类文件、释放资源,完成实例正常退出。异常宕机不会走这个线程。
4. 跟踪日志线程 dm_trctsk_thd
作用:事件日志 ELOG、TRACE 跟踪日志异步写入磁盘。
内核产生事件日志、trace 信息放入队列,该线程负责写入事件日志文件,避免业务线程直接写日志造成性能损耗。
5. 检查点线程 dm_chkpnt_thd
作用:配合调度线程管理检查点,记录 CKPT_LSN,维护检查点信息;协助完成检查点相关内核标记,脏页刷盘由 IO 线程执行。