openGauss
开源数据库
openGauss社区官网
开源社区
MogDB的线程理解
MogDB 的线程理解
单实例线程
1 业务处理线程 日志写线程,数据写线程,统计线程 2 清理线程,检查点线程,轻量锁检测线程,管理线程 3 审计线程,服务器启动线程,归档线程,告警线程 4 系统日志写线程,子线程回收线程,百分比统计线程,job 线程
主要线程描述和说明
业务处理线程:该线程是负责客户端请求任务的线程,当客户端发出一个连接请求给 postmaster 之后,postmaster 会 fork 出一个后端线程(业务处理线程)来处理客户端的请求,后续这个客户端的所有请求(包括查询和操作)都是有该业务线程来负责。当客户端发送过来一个业务请求的时候,或者 sql 语句的时候,会使用的 sql 引擎对客户端发送的 sql 语句进行语法解析,语义解析,词法分析,sql 改写,sql 优化,查询优化器生成依赖于统计信息最小代价的查询路径计划,SQL 执行器会按照已制定的最优执行计划对 SQL 语句执行,将结果返回给客户端,这期间该业务线程只为该客户端服务。
日志写线程
日志写线程,就是 wal 预写式日志线程,负责将内存中预写式日志中的页数据刷新到预写式 日志文件中,保证已提交的事务不会发生变化,永久保存。该日志和我们主流的数据库的重做日志功能基本类似,里面记录了数据文件的详细的变更操作,在执行 sql 操作的时候会先将这些变更记录到预写式日志中,然后周期性的将数据文件在刷新到数据文件中。
数据写线程
通常我们的理解是将共享内存中的脏页周期性的刷新带数据文件中,分为 pagewriter 和 bgwriter,但是在数据刷新到数据文件中的时候会存在宕机的情况,造成页中断或者页损坏的情况,这样就导致数据库在启动的时候无法启动,为了解决这个问题,MogDB 引入了 double write 的机制,就是在数据写线程(pagewriter)会先将脏数据 copy 到 dobule write 区域并落盘,然后再转发给数据写线程(bgwriter)将数据写入到数据文件中,万一在写入数据的时候发生了也中断或者页损坏的情况下,可以从 dobule write 区域进行数据的恢复,保证数据的安全,那为什么在 MogDB 里面存在页中断或者也损坏呢,那是因为我们的操作系统的快通常都是 4Kb 的。而我们的数据库通常可以使用 8K/16K/32k 的页面,通常是操作系统块的整数倍,MogDB 的数据库大小是 8K,就是 2 个操 作系统的数据块,所以在数据写线程进行数据写入的时候出现宕机就会发生也损坏的情况。
统计线程
统计线程(statcollect)就是收集数据库的信息,包括表的统计信息,索引的统计信息,锁的统计信息,物理资源的统计信息,sql 的统计信息,会话的统计信息,对象以及属性的 统计信息,线程信息,将这些所收集到的统计信息保存到 pg_stat 的文件中,用来进行性能分析,故障诊断,以及性能监控,健康检查以及查询优化器根据这些统计信息制定最小 代价的查询路径计划,SQL 执行器会按照已制定的最优执行计划对 SQL 语句执行。
清理线程
清理线程分为 AutoVacLauncher 和 AutoVacWorker,分别为启动线程和工作线程,首先 在 MogDB 里面表数据的删除不是真正意义的上面的数据删除,而是在原先的表上对该表删除 的行打上了标记,是一个逻辑的删除,可见性是通过 xmin 来判断的,至于可见性判断这里 面不说明,由于 MogDB 是这种的表数据的删除方式,所以在一张大表里面进行频繁的增删改 的操作,特别是删除的操作,就是导致这张表里面存在大量的无用的数据,同时这些无用的数据在 select 操作的时候会增加 io 的次数,同时 io 也需要扫描大量无用的数据,这无疑 是对 io 的浪费,同时 select 的耗时会增加,同时占用大量的磁盘空间,但是也有好处,就是在这种机制下面使用 MVCC 的话,读和写是不会阻塞的,MVCC 机制和这些历史快照实现数 据的读写不冲突。所以需要一个线程对这些过期数据进行清理,并回收存储空间。autovacuum 线程就是这个后台清理线程,负责回收表或 B-Tree 索引中已经删除的行所占据的存储空间,这个线程也是由一个发起线程和一个执行线程组成,AutoVacLauncher 和 AutoVacWorker,当 autovacuum 参数打开后,AutoVacLauncher 线 程会由 Postmaster 线程启动,并且会不断地将数据库需要做 vacuum 的对象信息保存在共享内存中,当表上被删除或更新的记录数超过设定的阈值( 表中(update,delte 记录) >= autovacuum_vacuum_scale_factor* reltuples(表上记录数) +autovacuum_vacuum_threshold ) 时,调用 AutoVacWorker 线程对这个表的存储空间执行回收清理工作。当需要发起数据库 vacuum 的时候,AutoVacLauncher 线程会在共享内存设置相应的 flag,然后发送信号给 Postmaster 线程,postmaster 线程收到信号后,就知道需要启动一个 AutoVacWorker 子线程连接共享内存,AutoVacWorker 子线程将从共享内存获取待清理的任务信息,并执行对象的清理回收工作。
MogDB 的内部线程图观察
