多线程架构
GaussDB采用单进程多线程架构,这是其高性能和高并发处理能力的关键因素。通过有效的线程调度和管理,GaussDB能够在单个进程中实现高效且稳定的数据处理。线程的种类和功能丰富多样,包括用户线程、系统线程、I/O 线程、日志线程等,线程之间协同工作,共同完成数据库的各项任务。在多线程架构下,更容易实现多个线程资源的共享,例如并行查询和线程池。GaussDB进程架构如图1所示。
多线程具有以下四大主要优势:
优势一:低启动开销
线程的启动开销远小于进程的启动开销。与进程相比,线程是一种更为“节俭”的多任务操作方式。在Linux系统下,启动一个新进程需要分配独立的地址空间,并建立多种数据表来维护其代码段、堆栈段和数据段,这是一种“昂贵”的多任务工作方式。相反,运行于同一进程中的多个线程共享相同的地址空间和大部分数据,因此启动一个线程所需的空间远小于启动一个进程。
优势二:便捷的通信机制
不同进程间具有独立的数据空间,数据传递只能通过通信方式进行,这不仅费时且不方便。而同一进程下的线程共享数据空间,一个线程的数据可以直接被其他线程使用,这不仅快捷而且方便。
优势三:低切换开销
在Linux系统中,进程切换分为两步:切换页目录以使用新的地址空间以及切换内核栈和硬件上下文。对于线程切换,切换页目录以使用新的地址空间是不必要的,只需执行切换内核栈和硬件上下文。因此,线程切换的开销明显小于进程切换。
优势四:较小的系统调用开销
在多线程架构中,系统调用的开销相对较小,因为线程切换仅涉及用户态和内核态之间的切换,而进程切换还需涉及用户态和内核态之间的切换以及地址空间的切换。
主要线程类型
在启动GaussDB时,main函数首先启动服务守护线程Postmaster。随后,Postmaster线程负责启动其他辅助线程,因此Postmaster是所有线程的父线程。当用户的SQL请求到达时,服务守护线程会启动一个worker线程,由该worker线程处理用户请求,执行SQL并返回数据。除了主业务线程外,GaussDB还提供了一些辅助线程,用于实现维护和调度功能。主要线程及其功能介绍如表1所示。
| 线程 | 功能介绍 |
|---|---|
| main thread | 数据库主线程。 主要有两个功能:
|
| worker thread | 工作线程。 GaussDB会根据需要创建多个工作线程来处理SQL语句的执行。每个工作线程都会独立地执行SQL语句,并将结果返回给主线程。 |
| connect thread | 建立连接线程。 GaussDB会根据需要创建多个建立连接线程来处理客户端建立连接请求。建立连接完成后将session移交给工作线程执行SQL语句。只有当enable_thread_pool和enable_connect_thread_pool打开时启用此线程类型。 |
| startup | 数据库启动线程。 数据库启动时,Postmaster主线程会启动第一个子线程,即Startup线程。该线程主要负责完成数据库的日志REDO(重做)操作,以进行数据库的恢复。日志REDO操作结束后,如果数据库不是备机,Startup线程就会退出。如果数据库是备机,Startup线程将持续运行,以处理接收到的新的日志。 |
| background writer | 后台数据写线程。 将数据库数据缓冲区的内容周期性地同步到磁盘上,以确保数据持久性。 |
| checkpointer | 检查点线程。 负责进行检查点操作,完成数据库的周期性检查点和执行检查点命令,以确保数据库的一致性和恢复能力。 |
| WAL writer | 后台WAL写线程。 将日志缓冲区的内容周期性地同步到磁盘上,以确保事务日志的持久性。 |
| system logger | 运行日志写线程。 将各个线程的运行日志信息写入运行日志文件中,以便于系统监控和故障排查。 |
| autovacuum launcher | 垃圾清理启动线程。 主要功能为:通知Postmaster启动一个垃圾清理线程,以及平衡各个垃圾清理线程的负载,以优化系统性能。 |
| autovacuum worker | 垃圾清理线程。 对GaussDB数据库中的垃圾数据进行清理,以释放存储空间和提高系统性能。 |
| archiver | 日志归档线程。 完成归档操作,将在线日志复制到归档目录,以确保日志的长期保存和备份。 |
线程池机制
在系统高并发环境下,由于系统资源争抢(包括外部资源(如CPU、网络、I/O等)以及内部资源(如关键锁结构)),往往会导致系统性能明显劣化,同时系统稳定性下降。因此,需要采用线程池技术实现业务连接(session)和后台服务线程(worker thread)的解耦,以确保资源始终处于可控状态,并保证所有业务有序执行,避免相互之间的资源争抢。GaussDB线程池模型如图2所示。
线程池技术的整体设计思想是将线程资源池化,并在不同连接中直接复用。系统在启动后,会根据当前用户配置启动一定数量的工作线程。一个工作线程可以服务一个或多个连接会话。当有新的请求到达时,线程池会分配一个空闲线程来处理请求。处理完毕后,线程会归还线程池,等待下一个请求的到来。这样可以避免频繁地创建和销毁线程,从而提高系统的响应速度和资源利用率。
GaussDB的线程模型采用了以下设计以实现有效地处理并发请求,提高数据库的性能和响应能力。
- 主线程:负责连接管理和请求调度。
- 工作线程池:处理客户端请求。
- 并发控制机制:保证数据的一致性和并发性。

