DM 服务器使用“对称服务器构架”的单进程、多线程结构。这种对称服务器构架在有效地利用了系统资源的同时又提供了较高的可伸缩性能,这里所指的线程即为操作系统的线程。服务器在运行时由各种内存数据结构和一系列的线程组成,线程分为多种类型,不同类型的线程完成不同的任务。线程通过一定的同步机制对数据结构进行并发访问和处理,以完成客户提交的各种任务。DM 数据库服务器是共享的服务器,允许多个用户连接到同一个服务器上,服务器进程称为共享服务器进程。
我会简单介绍一下DM 服务器中的主要进程和线程,首先,DM 服务器中的进程主要分为主进程和辅助进程:
·主进程(dmserver)
dmserver 是 DM 数据库的核心进程,负责启动数据库服务、管理线程以及处理所有数据库操作。
·辅助进程(dmap)
dmap 是辅助进程,主要用于支持第三方备份和提升备份还原效率。
DM 进程中主要包括监听线程、IO 线程、工作线程、调度线程、日志线程等,以下分别对它们进行介绍:
·监听线程(Listener Thread)
监听线程主要的任务是在服务器端口上进行循环监听,一旦有来自客户的连接请求,监听线程被唤醒并生成一个会话申请任务,加入工作线程的任务队列,等待工作线程进行处理。它在系统启动完成后才启动,并且在系统关闭时首先被关闭。为了保证在处理大量客户连接时系统具有较短的响应时间,监听线程比普通线程优先级更高。
·工作线程(Worker Thread)
工作线程是 DM 服务器的核心线程,负责服务器各种类型任务的处理,会从任务队列中取出任务并执行,并负责处理所有实际的数据操作,如SQL解析、查询执行等。工作线程的数量会根据会话连接数动态调整。工作线程包括任务工作线程和会话工作线程等。
任务工作线程负责处理服务器内部生成并加入对应任务队列的各项任务,如调度线程生成的清理缓存任务、异步执行的任务等,其初始个数由 INI 参数 TASK_THREADS 指定。任务工作线程空闲时从任务队列依次摘取任务并进行处理,当任务队列中的任务堆积时,系统会增加任务工作线程数量以减少任务堆积。
会话工作线程负责处理会话的请求任务,分为非线程池模式和线程池模式,由 INI 参数 STHD_FLAG 控制。非线程池模式下每一个会话对应一个会话工作线程,一个会话上的任务全部由同一个工作线程完成,这样减少了线程切换的代价,提高了系统效率。线程池模式初始工作线程个数由 INI 参数 WORKER_THREADS*STHD_THREAD_NUM 指定,由会话轮询线程接收所有用户请求,加入会话任务队列,会话工作线程从会话任务队列依次摘取请求任务进行处理。
·IO线程(IO Thread)
当事务需要的数据页不在缓冲区中时,如果在工作线程中直接对那些数据页进行读写,将会使系统性能变得非常糟糕,而把 IO 操作从工作线程中分离出来则是明智的做法。IO 线程的职责就是处理这些 IO 操作,将内存中的脏数据写入磁盘文件,实现数据的持久化。通常情况下,DM Server 需要进行 IO 操作的时机主要有以下三种:
(1)需要处理的数据页不在缓冲区中,此时需要将相关数据页读入缓冲区;
(2)缓冲区满或系统关闭时,此时需要将部分脏数据页写入磁盘;
(3)检查点到来时,需要将所有脏数据页写入磁盘。
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 操作。
·调度线程(Scheduler Thread)
调度线程用于接管系统中所有需要定时调度的任务。调度线程每秒钟轮询一次,负责的任务有以下一些:
(1)检查系统级的时间触发器,如果满足触发条件则生成任务加到任务工作线程的任务队列由任务工作线程执行;
(2)清理 SQL 缓存、计划缓存中失效的项,或者超出缓存限制后淘汰不常用的缓存项;
(3)执行动态缓冲区检查。根据需要动态扩展或动态收缩系统缓冲池;
(4)自动执行检查点。为了保证日志的及时刷盘,减少系统故障时恢复时间,根据 INI 参数设置的自动检查点执行间隔定期执行检查点操作;
(5)会话超时检测。当客户连接设置了连接超时时,定期检测是否超时,如果超时则自动断开连接;
(6)必要时执行数据更新页刷盘;
(7)唤醒等待的工作线程。
·日志FLUSH线程(Log FLUSH Thread)
任何数据库的修改,都会产生重做 REDO 日志,为了保证数据故障恢复的一致性,REDO 日志的刷盘必须在数据页刷盘之前进行。事务运行时,会把生成的 REDO 日志保留在日志缓冲区中,当事务提交或者执行检查点时,会通知 FLUSH 线程进行日志刷盘,将日志数据写入磁盘,确保事务的持久性和可恢复性。
DM8 的日志 FLUSH 线程进行了优化,在刷盘之前,对不同缓冲区内的日志进行合并,减少了 IO 次数,进一步提高了性能。
·日志归档线程(Log Archive Thread)
日志归档线程包含异步归档线程,负责远程异步归档任务。用于数据复制场景,加快异地访问的响应速度。如果配置了非实时归档,由日志 FLUSH 线程产生的任务会分别加入日志归档线程,日志归档线程负责从任务队列中取出任务,按照归档类型做相应归档处理。
日志归档线程包括本地逻辑日志归档线程和远程逻辑日志归档线程。除了远程实时归档外,本地归档、远程异步归档都可以脱离 FLUSH 线程来做,如果放在 FLUSH 线程中一起做会严重影响系统性能。将日志 FLUSH 线程和日志归档线程分开可以减少不必要的效率损失。
·日志 APPLY 线程(Log APPLY Thread)
在配置了数据守护的系统中,创建了一个日志 APPLY 线程。当服务器作为备库时,每次接收到主库的物理 REDO 日志生成一个 APPLY 任务加入到任务队列,APPLY 线程从任务队列中取出一个任务在备库上将日志重做,并生成自己的日志,保持和主库数据的同步或一致,作为主库的一个镜像。备库数据对用户只读,可承担报表、查询等任务,均衡主库的负载。
·定时器线程(Timer Thread)
在数据库的各种活动中,用户常常需要数据库完成在某个时间点开始进行某种操作,如备份;或者是在某个时间段内反复进行某种操作等。定时器线程就是为这种需求而设计的。
通常情况下,DM Server 需要进行定时操作的事件主要有以下几种:
(1)逻辑日志异步归档
(2)异步归档日志发送(只有在 PRIMARY 模式下,且是 OPEN 状态下)
(3)作业调度
定时器线程启动之后,每秒检测一次定时器链表,查看当前的定时器是否满足触发条件,如果满足,则把执行权交给设置好的任务,如逻辑日志异步归档等。
默认情况下,达梦服务器启动的时候,定时器线程是不启动的。用户可以设置 dm.ini 中的 TIMER_INI 参数为 1 来设置定时器线程在系统启动时启动。
·MAL系统相关线程(MAL Threads)
MAL(Message Access Layer)系统是 DM8 内部的高速通信系统,基于 TCP/IP 协议实现。支持数据守护、数据复制、MPP等功能。包括:
(1)MAL监听线程:监听通信请求。
(2)MAL发送/接收线程:处理消息的发送和接收。
·其他线程
审计线程(Audit Thread):负责将审计日志写入文件。
清理线程(Purge Thread):用于回滚清理操作。
用户会话线程(User Session Thread):处理用户会话相关的操作。
·线程信息的查看
为了增加用户对 DM 数据库内部信息的了解,以及方便数据库管理员对数据库的维护,DM 提供了很多动态性能视图,通过它们用户可以直观地了解当前系统中有哪些线程在工作,以及线程的相关信息,如下:
V$LATCHES:记录当前正在等待的线程信息
V$THREADS:记录当前系统中活动线程的信息
V$PROCESS:记录服务器进程信息
社区地址:https://eco.dameng.com