WAL机制

持久性指事务提交后对系统的影响必须是永久的,即使系统意外宕机,也必须确保事务修改的数据已真正永久写入到永久存储中。

最简单的实现方法,是在事务提交后立即将修改的数据写到磁盘。但磁盘和内存之间的IO操作是最影响数据库性能的。

WAL(Write Ahead Logging),预写日志,即在数据修改后写到磁盘前,先把日志写到磁盘。确保重做日志时可以恢复事务的一致性状态,而不会有部分执行的事务状态。

WAL机制的引入,即保证了事务持久性和数据完整性,又尽量地避免了频繁IO对性能的影响。

使用WAL可以显著地减少写磁盘的次数,因为只需要把日志文件刷新到磁盘就可以保证事务被提交,而不需要把事务修改的数据立即写入磁盘。

日志文件是连续写的,所以同步log的花销远小于刷新数据页的花销。

当服务器在处理大量并行小事务时,log文件一次fsync就可以提交多个事务。

postgresql数据库可以通过调整WAL参数控制日志写入磁盘的先后顺序。先将日志写入磁盘能够完全保证数据的完整性,在崩溃时可以恢复最近的事务;后写入磁盘,很难保证在崩溃时事务能够得到恢复,数据的结果也很难保证是真实正确的。

因为WAL可以在宕机后恢复数据库文件内容,JFS(journaled file systems)对于数据文件或WAL文件的可靠存储就不是必要的了。JFS甚至会影响系统性能,尤其当它要把文件系统数据刷新到磁盘时。

WAL日志文件

http://www.postgres.cn/news/viewone/1/96

WAL日志文件在pg_wal(PG10,默认为/var/lib/pgsql/10/data/pg_wal/)目录下,一般情况下,每个文件为16M大小。

文件名称为16进制的24个字符组成,每8个字符一组,格式timeline+logId+logSeg,每组的意义如下:

  1. 00000001 00000000 000000BC
  2. -------- -------- --------
  3. 时间线 LogId LogSeg
  4. 时间线:英文为timeline,是以1开始的递增数字,如1,2,3...
  5. LogId32bit长的一个数字,是以0开始递增的数字,如0,1,2,3...
  6. LogSeg32bit长的一个数字,是以0开始递增的数字,如0,1,2,3...

PostgreSQL中会用两个十六进制的数字中间用斜杠“/”分隔表示WAL日志位置,即表示LSN(WAL日志的位置,即Log Sequence Number)

WAL写放大

PostgreSQL在写入频繁的场景中,可能会产生大量的WAL日志,而且WAL日志量远远超过实际更新的数据量,这种现象叫做“WAL写放大”。

造成WAL写放大的主要原因有2点。

  1. checkpoint之后第一次修改页面,需要在WAL中输出整个page,即全页写(full page writes)。全页写的目的是防止在意外宕机时出现的数据块部分写导致数据库无法恢复。
  2. 更新记录时如果新记录位置(ctid)发生变更,索引记录也要相应变更,这个变更也要记入WAL。更严重的是索引记录的变更又有可能导致索引页的全页写,进一步加剧了WAL写放大。

过量的WAL输出会对系统资源造成很大的消耗,因此需要进行适当的优化。

  1. 磁盘IOWAL写入是顺序写,通常情况下硬盘对付WAL的顺序写入是绰绰有余的。所以一般可以忽略。
  2. 网络IO:对局域网内的复制估计还不算问题,远程复制就难说了。
  3. 磁盘空间:如果做WAL归档,需要的磁盘空间也是巨大的。

WAL记录的构成

主要占空间是"block data"。一条WAL记录可能不涉及数据块,也可能涉及多个数据块。

"block data"的内容可能是下面几种情况之一

  1. full page image
  2. 如果是checkpoint之后第一次修改页面,则输出整个page的内容(即full page image,简称FPI)。但是page中没有数据的hole部分会被排除,如果设置了wal_compression = on还会对这page上的数据进行压缩。
  3. buffer data
  4. 不需要输出FPI时,就只输出page中指定的数据。
  5. full page image + buffer data
  6. 逻辑复制时,即使输出了FPI,也要输出指定的数据

WAL日志解析

查看日志命令

  1. /usr/pgsql-10/bin/pg_waldump /var/lib/pgsql/10/data/pg_wal/00000001000000280000005F -b
  2. ......
  3. rmgr: Heap len (rec/tot): 68/ 68, tx: 103824377, lsn: 28/5F4CBB38, prev 28/5F4CBAF0, desc: HOT_UPDATE off 24 xmax 103824377 ; new off 43 xmax 0
  4. blkref #0: rel 1663/26173/27777 fork main blk 968682
  5. ......

解释如下:

  1. rmgr: Heap
  2. PostgreSQL内部将WAL日志归类到20多种不同的资源管理器。这条WAL记录所属资源管理器为Heap,即堆表。除了Heap还有Btree,Transaction等。
  3. len (rec/tot): 68/ 68
  4. WAL记录的总长度是68字节,其中main data部分是68字节(只计数main data可能并不合理,本文的后面会有说明)。
  5. tx: 103824377,事务号
  6. lsn: 28/5F4CBB38,本WAL记录的LSN
  7. prev 28/5F4CBAF0,上条WAL记录的LSN
  8. desc: HOT_UPDATE off 24 xmax 103824377 ; new off 43 xmax 0
  9. 这是一条UPDATE类型的记录(每个资源管理器最多包含16种不同的WAL记录类型),旧tuplepage中的位置为24(即ctid的后半部分),新tuplepage中的位置为43
  10. blkref #0: rel 1663/26173/27777 fork main blk 968682
  11. 引用的第一个page(新tuple所在page)所属的堆表文件为1663/26173/27777,968682(即ctid的前半部分)。通过oid2name可以查到是哪个堆表(需要按照postgresql10-contrib postgresql10-docs)。
  12. -bash-4.1$ /usr/pgsql-10/bin/oid2name -f 968682
  13. From database "postgres":
  14. Filenode Table Name
  15. ----------------------------
  16. 968682 pgbench_accounts

相关参数请点击

postgres--wal的更多相关文章

  1. postgres配置主从流复制

    postgres主从流复制 postgres在9.0之后引入了主从的流复制机制,所谓流复制,就是从库通过tcp流从主库中同步相应的数据.postgres的主从看过一个视频,大概效率为3w多事务qps. ...

  2. Postgres Plus Advanced Server installation

    # setenforce Permissive # ./ppasmeta-9.3.1.3-linux-x64.run --mode text Installation Directory [/opt/ ...

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

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

  4. kill -9 a postgres process

    在postgresql中,不推荐使用Kill -9直接杀掉异常连接,因为直接使用kill -9会引起整个数据库核心进程的重启,同时其他正常程序连接也会被杀掉. 现开启两个psql连接,然后使用Kill ...

  5. Postgres主备切换

    主备查询 主备不会自动切换(即需要实现线上环境主数据库宕掉之后,从数据库能够自动切换为主数据库,需要借用第三方软件,例如heartbeat等) (1)如何查看是primary还是standby 方法1 ...

  6. linux下安装postgresql

    环境:Linux localhost.localdomain 2.6.32-431 GNU/Linux x86_64 Postgresql版本:postgresql.9.5.3 添加开启自启设置:ht ...

  7. PostgreSQL installations

    [root@test02 init.d]# ll /etc/init.d/postgresql-9.5 -rwxr-xr-x. 1 root root 10072 May 15 06:34 /etc/ ...

  8. <<卸甲笔记>>-Oracle线下迁移到PPAS

    迁移原则 1.尽量保持Oracle与PPAS一致,这会使得日后应用程序迁移更为简单 2.迁移前检查PPAS中是否有同名帐号及同名的Schema a)如果有,建议考虑删除或改名 b)如果没有,先手工建立 ...

  9. postgresql流复制配置

    一.配置环境: 示例环境 主机名 IP 角色 系统版本 数据目录 pg版本 db1 192.168.128.128 主库 RedHat5.3 /app/postgreSQL/data 9.1.7 db ...

  10. PostgreSQL Hot Standby的主备切换

    一. 简介:          PG在9.*版本后热备提供了新的一个功能,那就是Stream Replication的读写分离,是PG高可用性的一个典型应用.其中备库是只读库:若主库出现故障:备库这个 ...

随机推荐

  1. pku 2777(经典线段树染色问题)

    Count Color Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 41202   Accepted: 12458 Des ...

  2. 如何配置Java环境,包括JDK,Maven等

    下载JDK并安装 搜索JDK,官网立马就出来了,下载之后个人觉得毕竟开发,毕竟这东西不大,C盘稳一点,安装在C盘可以的 配置 右键打开计算机->属性->高级系统设置->高级-> ...

  3. websocket小荔枝

    关于websocket原理和好处请参考百度,这里只是代码. var ws = new WebSocket('ws://echo.websocket.org/'); ws.onopen = functi ...

  4. 创建 OpenStack云主机 (十五)

    创建过程 创建虚拟网络 创建m1.nano规格的主机(相等于定义虚拟机的硬件配置) 生成一个密钥对(openstack的原理是不使用密码连接,而是使用密钥对进行连接) 增加安全组规则(用iptable ...

  5. gvim代码补全

    gvim 代码自动提示 插件 插件名:AutoComplPop 下载地址:http://www.vim.org/scripts/script.php?script_id=1879 gvim 代码模板补 ...

  6. PHP 边执行边输出

    <?php for ($i = 1; $i <= 5; $i++) { print "#$i 完毕<hr>"; sleep(1); print str_pa ...

  7. POJ2828 Buy Tickets [树状数组,二分答案]

    题目传送门 Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 22611   Accepted: 110 ...

  8. js数组,在遍历中删除元素

    /** * 有效的方式 - 改变下标,控制遍历 */ for (var i = 0; i < arr.length; i++) { if (...) { arr.splice(i, 1); // ...

  9. 洛谷——P1223 排队接水

    P1223 排队接水 题目描述 有n个人在一个水龙头前排队接水,假如每个人接水的时间为Ti,请编程找出这n个人排队的一种顺序,使得n个人的平均等待时间最小. 输入输出格式 输入格式: 输入文件共两行, ...

  10. python strip() 函数和 split() 函数的详解及实例

    strip是删除的意思:split则是分割的意思.strip可以删除字符串的某些字符,split则是根据规定的字符将字符串进行分割. 1.Python strip()函数 介绍 函数原型 声明:s为字 ...