diff --git "a/content/zh/post/enmo/MogDB\347\232\204\347\272\277\347\250\213\347\220\206\350\247\243.md" "b/content/zh/post/enmo/MogDB\347\232\204\347\272\277\347\250\213\347\220\206\350\247\243.md" new file mode 100644 index 0000000000000000000000000000000000000000..1324d59b58312958e08f4b37855bb4573404e7b3 --- /dev/null +++ "b/content/zh/post/enmo/MogDB\347\232\204\347\272\277\347\250\213\347\220\206\350\247\243.md" @@ -0,0 +1,59 @@ ++++ + +title = "MogDB的线程理解" + +date = "2022-05-24" + +tags = ["MogDB的线程理解"] + +archives = "2022-05" + +author = "云和恩墨交付" + +summary = "MogDB的线程理解" + +img = "/zh/post/enmo/title/img.png" + +times = "10:20" ++++ + +# 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的内部线程图观察 + +![微信截图_20220216123148.png](../images/20220216-522745f1-010b-4ada-9c96-ada272ed6d31.png) diff --git a/content/zh/post/enmo/images/20220216-522745f1-010b-4ada-9c96-ada272ed6d31.png b/content/zh/post/enmo/images/20220216-522745f1-010b-4ada-9c96-ada272ed6d31.png new file mode 100644 index 0000000000000000000000000000000000000000..6d059996cf8be4ee45817e2ae9d384e29c7bb4fb Binary files /dev/null and b/content/zh/post/enmo/images/20220216-522745f1-010b-4ada-9c96-ada272ed6d31.png differ