PostgreSQL之辅助进程
pg进程的状态图是一个有意思的地方,有时间整理一把。
今天看代码处,发现了关于pgstat和syslogger二者比较有趣的的地方:
- pgstat用于集中式地汇总其他进程发送来的统计信息, syslogger则用于集中式地汇总其他进程发送来的日志信息;
- pgstat的搜集信息采用了一些必要的控制和采样的算法,而syslogger则是不加过滤地把所有的日志信息取过来然后写入到日志文件中去;
- 二者都是通过IPC管道的方式来实现的;
- 进程退出的方式有所区别。pgstat需要postmaster进程信号通知,然后它会把尚在内存中的数据赶紧写到磁盘中去,才退出;而syslogger不需要postmaster进程的信号通知,而是直接等到管道中没有任何数据可读的时候,自己乖乖地退出。
彩蛋
- syslogger为什么可以使用这种乖乖退出的方式呢?
很明显地,这种方式的退出需要保证日志数据是不能丢失的(当然,其实在crash的情况下,丢失部分日志也是没有关系的;但正常情况下肯定是不允许的)。那么,正常情况下,是如何保证日志数据不丢失呢?通过以下几点来保证的
- pipe在4096字节之内的写入是原子性的,而写入端通过对较大日志进行拆分来保证所有日志是会写入管道的;
- 接收端总是会通过select/poll来保证所有写入的数据是可以读取走的,最终保证管道中的数据是可以全部读了出来的;
- 接收端对于要写入的日志是直接一条一条写入的,而不会再次使用缓存进行大块的写入。这样就保证了立即读取到的数据可以立即写文件。(当然,它使用了操作系统中的cache,在进程crash的情况下,则OS来完成数据的真正写盘了)
这样,端到端地就保证了日志信息的不丢失。如果说,写盘使用大块数据写入的效率会更好的话,那么就需要对写文件的数据再次缓存(从其它进程接收过来的日志是以消息协议组装的,它是带有协议头信息的,需要把头信息去掉)。在这种情况下,syslogger需要在自行退出之前特别地处理一下已缓存的数据,把它写盘。在进程crash的情况下,这一部分日志数据就会真正地丢失了。