PostgreSQL如何删除不使用的xlog文件

  

一、问题
经常会在复制的时候遇到这样的问题,需要复制的xlog文件找不到了。那么xlog文件什么时候删除?又会删除多少保留多少个xlog文件?都有哪些xlog文件需要保留?本文将从原理上对这些问题进行解读。

  

二,原理
每次检查点后都会根据需要删除或者回收不再需要的xlog文件。
1,首先估算两次检查点之间产生的xlog量,根据这个量会计算出未来最大的日志文件号从而回收不再需要的文件将其重命名为未来即将使用的日志文件号:
1.1 UpdateCheckPointDistanceEstimate估算检查点之前产生的日志量:
如果CheckPointDistanceEstimate & lt;nbytes)//上次估算量比这次估算的小,则更新为这次的估算量
CheckPointDistanceEstimate=nbytes;其他
//否则,适当增加
CheckPointDistanceEstimate=(0.90 CheckPointDistanceEstimate + 0.10 (双)nbytes);
2,计算上一次检查点时,所在的文件段号_logSegNo:
XLByteToSeg (PriorRedoPtr _logSegNo);
3,计算需要保留的文件段号:从该段号_logSegNo开始的文件都不能被删除,之前的需要删除或回收:根据备机请求以及wal_keep_segments计算KeepLogSeg (recptr,和_logSegNo);
 PostgreSQL如何删除不使用的xlog文件

  

4,遍历pg_wal目录下的所有xlog文件,进行删除:RemoveOldXlogFiles
4.1跳过时间线进行比较,如果pg_wal目录下的文件比_logSegNo小则被删除或回收。那么什么条件下次被回收?
——RemoveXlogFile
4.2计算回收文件重命名的未来最大文件段号recycleSegNo:
1)如果本次是第一次检查点,则未来最大段号recycleSegNo=当前段文件号+ 10
2)否则调用函数XLOGfileslop计算:
2.1估算下一次检查点结束时日志位置:
距离=(2.0 + checkpoint_completion_target) CheckPointDistanceEstimate距离
=1.1
recycleSegNo=(XLogSegNo)装天花板(((双)PriorRedoPtr +距离)/XLOG_SEG_SIZE);
2.2 minSegNo=PriorRedoPtr/XLOG_SEG_SIZE + ConvertToXSegs (min_wal_size_mb) - 1;
maxSegNo=PriorRedoPtr/XLOG_SEG_SIZE + ConvertToXSegs (max_wal_size_mb) - 1;
2.3如果(recycleSegNo & lt;minSegNo)
recycleSegNo=minSegNo;
如果recycleSegNo祝辞maxSegNo)
recycleSegNo=maxSegNo;
4.3如果当前段文件号endlogSegNo & lt;recycleSegNo,则调用InstallXLogFileSegment进行回收:
1)在endlogSegNo和recycleSegNo之间找一个免费的槽num,即没有该段文件号的xlog文件
2)将需要删除的文件名命名为该免费槽号的文件名
3)如果没有找到空闲时段则直接删除该文件
——RemoveXlogFile

  

三、代码流程
1,检查点顶层函数CreateCheckPoint:

  
 <代码>
  CreateCheckPoint:
  XLogCtlInsert *插入=,XLogCtl→插入;//标识插入的位置
  curInsert=XLogBytePosToRecPtr(插入→CurrBytePos);//添加页头大小后的位置//(((curInsert) % XLOG_BLCKSZ==0) ?0:(XLOG_BLCKSZ - (curInsert) % XLOG_BLCKSZ))
  freespace=INSERT_FREESPACE (curInsert);//curInsert所在页是否有空闲空间
  如果(freespace==0) {
  如果(curInsert % XLogSegSize==0)//正好一个xlog段文件用完,即将使用下一个段文件,则跳过36字节
  curInsert +=SizeOfXLogLongPHD;//36字节//其他xlog段文件中正好一页用完,即将使用下一页,则跳过20字节
  curInsert +=SizeOfXLogShortPHD;//20字节
  }
  检查点。重做=curInsert;//xlog文件上,实际的即将插入位置
  RedoRecPtr=XLogCtl→插入。RedoRecPtr=checkPoint.redo;
  …//插入检查点记录后末尾位置,即下一个xlog开始的位置
  recptr=XLogInsert (RM_XLOG_ID,关闭?XLOG_CHECKPOINT_SHUTDOWN: XLOG_CHECKPOINT_ONLINE);
  …
  PriorRedoPtr=ControlFile→checkPointCopy.redo;//上一次检查点的起始位置
  …
  如果(PriorRedoPtr !=InvalidXLogRecPtr){//上一次检查点开始到这一次检查点开始,产生的XLOG大小为入参/*
  CheckPointDistanceEstimate:
  1,CheckPointDistanceEstimate=RedoRecPtr - PriorRedoPtr时:0.9 * CheckPointDistanceEstimate + 0.1 * (RedoRecPtr - PriorRedoPtr)
  */UpdateCheckPointDistanceEstimate (RedoRecPtr PriorRedoPtr);//_logSegNo=(PriorRedoPtr)/XLogSegSize
  XLByteToSeg (PriorRedoPtr _logSegNo);
  KeepLogSeg (recptr, _logSegNo);
  _logSegNo——;
  RemoveOldXlogFiles (_logSegNo PriorRedoPtr recptr);  
  

2,两个宏定义

  
 <代码> # define UsableBytesInPage (XLOG_BLCKSZ - SizeOfXLogShortPHD)//注意:不是文件第一页
  #定义UsableBytesInSegment ((XLOG_SEG_SIZE/XLOG_BLCKSZ) * UsableBytesInPage - (SizeOfXLogLongPHD - SizeOfXLogShortPHD)) 

PostgreSQL如何删除不使用的xlog文件