问题出现

我们在线上巡检中发现,一个实例的pg_xlog目录,增长到4G,很是疑惑。刚开始怀疑是日志归档过慢,日志堆积在pg_xlog目录下面,未被清除导致。于是检查归档目录下的文件,内容如下。但发现新近完成写入的日志文件都被归档成功了(即在pg_xlog/archive_status里面,有对应的xxx.done文件)。

ls -lrt pg_xlog
...
-rw------- xxxx xxxx Jun : 0000000100000035000000DE
-rw------- xxxx xxxx Jun : 0000000100000035000000DF
drwx------ xxxx xxxx Jun : archive_status
-rw------- xxxx xxxx Jun : 0000000100000035000000E0 ls -lrt pg_xlog/archive_status
...
-rw------- xxxx xxxx Jun : 0000000100000035000000DE.done
-rw------- xxxx xxxx Jun : 0000000100000035000000DF.done
-rw------- xxxx xxxx Jun : 0000000100000035000000E0.done

仔细观察,奇怪的是,pg_xlog里面还有一些日志文件,其文件名对应了还没产生的日志号!如下所示,当前正在被写入的日志号为100000035000000E0左右,却出现了名为1000000360000000C的日志文件名,更蹊跷的是,其修改时间还在很早以前,就是说不是新近创建或修改过的,如下面的文件修改或创建时间是在当前时间的一个小时之前:

ls -lrt pg_xlog
....
-rw------- xxxx xxxx Jun : 00000001000000360000000C
-rw------- xxxx xxxx Jun :
....

这是怎么回事呢?难道是“幽灵日志”?下面我们要搞清楚两个问题:1)为什么会出现”幽灵日志“?2)PG正常情况下日志空间大小是多少?

PG日志创建清理机制

要回答上述问题,需要先摸清PG的日志创建、保持和清理机制。与此直接相关的模块有:日志写入(WAL writer)进程和日志归档(archiver)进程。其实检查点(checkpointer)进程和日志发送进程(WAL sender)也与此有关。

WAL writer负责异步把WAL日志刷入磁盘;与此同时,其他普通后台进程,也可能会同步的将WAL日志刷入磁盘,我们先从分析它们入手。从代码里面不难看出,它们将日志写入新的日志文件时,有如下函数调用:

XLogWrite -> XLogFileInit ->BasicOpenFile

BasicOpenFile负责打开一个新的日志文件,如果文件不存在,则新建文件。而其代码注释里面提到“Try to use existent file (checkpoint maker may have created it already)”,即打开的文件可能已经被checkpointer进程创建。

于是我们将目光转向checkpointer。其主要函数CheckpointerMain的逻辑如下:

  1. 检查是否有checkpoint request信号;
  2. 检查是否checkpoint timeout时间已到;
  3. 调用CreateCheckPoint做检查点操作;
  4. 调用WaitLatch等待checkpoint timeout或checkpoint request信号。

重点内容都在CreateCheckPoint函数中,其逻辑如下:

  1. 检查上次检查点后是否有WAL日志写入,如果没有直接返回;
  2. 调用CheckPointGuts将WAL日志fsync到磁盘;注意其中的CheckPointBuffers函数,会根据checkpoint_completion_target的值做一定的delay,使fsync操作的完成时间占两个检查点之间时间间隔的比例,约为checkpoint_completion_target;
  3. 在WAL中插入检查点日志信息;
  4. 取系统前一次检查点的日志位置指针,即此指针之前的日志文件,都可以删除了;
  5. 由KeepLogSeg根据wal_keep_segments和replication slot的情况计算要额外保留的日志;
  6. 由RemoveOldXlogFiles做真正的日志删除,而神奇的是RemoveOldXlogFiles并未实际删除文件,而是将其回收,即将老文件rename成新文件,做了日志文件预分配;
  7. 完成检查点返回。

可以看到,在这里出现日志删除、预分配等逻辑。也就是说PG的日志文件可能是在做检查点操作时预分配的!预分配的文件名使用了“未来”的目前还不存在的日志号,这就解释了我们之前遇到的“幽灵日志”情况,也回答了我们的第一个问题。

当然,需要说明的是,日志的保留和删除还和是否被archiver进程归档成功有关。

日志空间大小

继续看第二个问题。前面提到的日志空间暴增让我们如临大敌,那么PG日志到底最多会占用多少空间?我们遇到的涨到3G情况正常吗?

从日志清理逻辑(重点是KeepLogSegRemoveOldXlogFiles函数)的分析,我们得到下面的结论:

  1. 日志的删除和预分配只在检查点刚完成时进行;
  2. 删除时,保证上一次检查点之后到现在的日志不会被删除;
  3. 保证从目前日志位置往前wal_keep_segments个日志文件不会删除;
  4. 预分配的过程是,对所有不再需要的旧文件重命名为一个未来的日志号,直到预分配的文件数量达到XLOGfileslop,即2*checkpoint\_segments + 1。checkpoint_segments为一个可配置的参数,控制了两个检查点间产生的日志文件数量。

另外,为讨论方便,下面我们先做如下假设:

  1. 有足够多(即大于2*checkpoint_segments + 1)的不再需要的旧日志文件,可以用于预分配;
  2. 每次检查点操作完成的时间,正好占两个检查点之间时间间隔的checkpoint_completion_target(线上目前我们设为0.9)。

设某次检查点操作完成时的时间点为A,则此时做日志预分配的情形如下图所示:

候选被回收的文件是在时间点C之前的、并且大于wal_keep_segments个文件间隔的文件;这些文件将重命名为预分配文件,文件号为从A对应的日志开始递增,直到达到2*checkpoint_segments + 1个文件为止。

做检查点操作过程中,是不断产生新日志文件的,而且两次检查点之间的日志文件数为一个稳定的值,即checkpoint_segments。因此,在时间点B到A之间产生的日志数约为

checkpoint_segments * checkpoint_completion_target

待A时间点预分配完日志文件,并删除其他不需要的日志后,新产生的日志将使用预分配空间,日志空间不会增大,日志空间大小达到一个稳定状态。而此时日志的空间至少为:保留的日志空间 + 预分配空间 + 正在被写入的那个文件,即为:

max(wal_keep_segments, checkpoint_segments + checkpoint_segments*checkpoint_completion_target) +  * checkpoint_segments +  + 

这就是在日志大小达到稳定状态时,所能达到的最大值。所谓“稳定状态”是指,一旦达到这个状态,优先使用预分配空间,一般不会增大;即使日志文件继续增加,也会被删除(如果archiver和wal sender都正常工作的话)。而日志大小也不会明显减少,因为处于预分配状态的日志数量、前一次检查点到当前时间点的日志量都没有大的变化。

回到我们的问题,PG的日志空间占用的正常值,可以用上面的公式计算出来。如果wal_keep_segments为80,checkpoint_segments为64,checkpoint_completion_target为0.9,那么根据公式计算结果为4.02G。即日志空间增加到4G也是正常的。并且可以通过减小checkpoint_segements的值,减少日志空间占用。

几个问题

通过上面分析得出的公式,我们在处理日志时遇到的一些问题就迎刃而解了,例如:

Q: 增加wal_keep_segments会增大日志空间吗?
A: 如果增加wal_keep_segments后,其值仍小于(checkpoint_segments + checkpoint_segments * checkpoint_completion_target),则增加wal_keep_segments并不会增大日志占用空间。

Q: checkpoint_segments与日志空间大小有什么关系?
A: 在wal_keep_segments较小时,checkpoint_segments对日志空间占用有至关重要的影响。日志空间大小基本上可以用4倍checkpoint_segments来估算出来。但当wal_keep_segments较大时,比如是checkpoint_segments的10倍,则checkpoint_segments对日志空间大小的影响相对就小很多了。

思考题

上面的分析中,我们做了两点假设。一个是系统中有足够多的旧日志可供回收,这种情况会出现吗(提示:archiver进程或replication slot对日志删除的影响)?另一个是,检查点操作会及时完成,那么如果检查点操作未及时完成,会出现什么情况?会导致日志空间占用比我们的公式更大吗?

参考:

http://mysql.taobao.org/monthly/2015/06/08/

注:

1、XLOGfileslop:预分配wal文件数量,为:2*checkpoint_segments + 1

2、最后的两个思考题,还未想出答案。

PgSQL · 追根究底 · WAL日志空间的意外增长的更多相关文章

  1. PostgreSQL WAL日志详解

    wal日志即write ahead log预写式日志,简称wal日志.wal日志可以说是PostgreSQL中十分重要的部分,相当于oracle中的redo日志. 当数据库中数据发生变更时:chang ...

  2. postgresql如何维护WAL日志/归档日志

    WAL日志介绍 wal全称是write ahead log,是postgresql中的online redo log,是为了保证数据库中数据的一致性和事务的完整性.而在PostgreSQL 7中引入的 ...

  3. 主库的wal日志已经被归档或异常丢失如何搭建从库

      关键字:wal日志归档  搭建从库 restore_command master 194.1 slave 194.4 wal归档目录 /backup/pgsql/pg_arch/ xlog目录 / ...

  4. 关于ASE日志空间示数不正常的解决办法

        最近某系统的ASE数据库出现了异常,经过各种努力,终于把数据库正常又起起来了.但是经过检查,发现在查看剩余日志空间的时候(sp_helpsegment 'logsegment'),发现显示出来 ...

  5. SQLServer数据库中开启CDC导致“事务日志空间被占满,原因为REPLICATION”的原因分析和解决办法

    本文出处:http://www.cnblogs.com/wy123/p/6646143.html SQLServer中开启CDC之后,在某些情况下会导致事务日志空间被占满的现象为:在执行增删改语句(产 ...

  6. STL—vector空间的动态增长

    vector空间的动态增长     当添加元素时,如果vector空间大小不足,则会以原大小的两倍另外配置一块较大的新空间,然后将原空间内容拷贝过来,在新空间的内容末尾添加元素,并释放原空间.vect ...

  7. 归档日志空间满导致DB启动失败

    现象 登录失败 告警日志: 由此可知,归档日志空间已满 解决方式: 一.增大归档日志空间 1.启动数据库至nomount [oracle@CentOS ~]$ sqlplus / as sysdba ...

  8. PostgreSQL日志号LSN和wal日志文件简记

    弄明白日志号的原理之后,一段时间又有点忘记了,干脆整理一遍: (一)wal文件命名规则 1)在$PGDATA目录下面的pg_xlog目录中存放着xlog日志文件(10.1之后变为了pg_wal): t ...

  9. WAL日志文件名称格式详解

    转自:http://blog.osdba.net/534.html WAL日志文件名称格式详解 PostgreSQL的WAL日志文件在pg_xlog目录下,一般情况下,每个文件为16M大小: osdb ...

随机推荐

  1. JS 基础事件的用法

    // 1.9以上用on // 案例一 // $('#btn').on('click', function(){ // //console.log(1); // alert('测试...'); // } ...

  2. D.T SOFTWARE (1) 软件架构直播答疑课程

    今晚的d.t课程 1项目需求 PPTP服务搭建完成PPTP服务器的搭建,用户重新拨号获得新IP后,要求拔PPTP VPN成功时,也获取到新的公网IP,而且能通过代理上网.VNC服务安装用户可以通过VN ...

  3. 用javascript正则表达式来格式化金额

    <html><head><script> function a() { var amount = "-22334.334455"; //if(/ ...

  4. linux命令:rm

    1.介绍: rm用来删除文件或者目录,对于链接文件,只删除了链接,不删除源文件.rm是一个非常危险的命令,像rm -rf /这个命令运行后,后果不堪设想. 2.命令格式: rm [选项] 文件/目录 ...

  5. 2、网页制作Dreamweaver(图片热点、frameset框架)

    图片热点 1.方法: <img  usemap="名字"> <map name="名字"> <area shape="r ...

  6. aspx页面图片用作html中img的url

    背景:如果无法直接访问保存图片的服务器,我们可以先制作一个aspx页面用来接受服务器发送过来的图片,然后html页面请求aspx页面.对图片服务器起一定的缓冲保护作用,预防对黑客攻击造成危害. 注意: ...

  7. pscp详解

    pscp详解 在linux中,我们常用scp命令传输文件: 如以下实例,我们想把当前服务器文件abc.sql传输到192.168.1.1服务器上,我们可以执行以下命令: scp /home/perso ...

  8. 了解magento数据库

    网址是:http://www.magereverse.com/,不同版本都有

  9. Magento速度优化

    一.Magento Compiler可以提高 25% 到 50% 速度 Magento的性能一直是大家比较关心的焦点,现在Magento最新的版本 1.3.2.2 增加了 Magento Compil ...

  10. 第三个sprint第一天

    一.例会人员:李泳江,邵家文,周伟雄,谢洪跃 日期:6月16号   例会内容: 1.更新核心功能 例会地点:宿舍 二.任务展示 编号 名称 时间 已用时间 是否完成 1 画出算法流程图 4小时 4小时 ...