最近深入理解了Checkpoint的相关逻辑,再来看WAL日志的一些设置,又有了新的收获。

1.回顾pg_xlogdump出来的wal日志信息;

2.wal中FPI的占比很高问题分析;

3.重申full_page_writes的作用;

4.解决wal日志很大的问题,使用压缩更靠谱。不建议将full_page_writes设置为false来提升性能,就像把fsync设置为false提升性能一样是不合理的。

先来看一段WAL日志记录,我们通过pg_xlogdump来解析:

apple=# create table test(id int);
CREATE TABLE
execute query success, query is create table test(id int);
apple=# select pg_current_xlog_location();
pg_current_xlog_location
--------------------------
0/8004B738
(1 row) apple=# insert into test values(1);
INSERT 0 1
apple=# insert into test values(2);
INSERT 0 1
apple=# insert into test values(3);
INSERT 0 1
execute query success, query is select pg_current_xlog_location();
apple=# checkpoint;
CHECKPOINT
apple=# select pg_current_xlog_location();
pg_current_xlog_location
--------------------------
0/8004B8E0
(1 row)
apple=# \q
appledeMacBook-Pro-2:pg_xlog apple$ pg_xlogdump -p ./ -s 0/8004B738 -e 0/8004B8E0
rmgr: Heap len (rec/tot): 3/ 59, tx: 718239, lsn: 0/8004B738, prev 0/8004B710, desc: INSERT+INIT off 1, blkref #0: rel 1663/16384/53523 blk 0
rmgr: Transaction len (rec/tot): 8/ 34, tx: 718239, lsn: 0/8004B778, prev 0/8004B738, desc: COMMIT 2019-03-28 11:02:44.115417 CST
rmgr: Heap len (rec/tot): 3/ 59, tx: 718240, lsn: 0/8004B7A0, prev 0/8004B778, desc: INSERT off 2, blkref #0: rel 1663/16384/53523 blk 0
rmgr: Transaction len (rec/tot): 8/ 34, tx: 718240, lsn: 0/8004B7E0, prev 0/8004B7A0, desc: COMMIT 2019-03-28 11:02:46.022003 CST
rmgr: Heap len (rec/tot): 3/ 59, tx: 718241, lsn: 0/8004B808, prev 0/8004B7E0, desc: INSERT off 3, blkref #0: rel 1663/16384/53523 blk 0
rmgr: Transaction len (rec/tot): 8/ 34, tx: 718241, lsn: 0/8004B848, prev 0/8004B808, desc: COMMIT 2019-03-28 11:02:48.293447 CST
rmgr: XLOG len (rec/tot): 80/ 106, tx: 0, lsn: 0/8004B870, prev 0/8004B848, desc: CHECKPOINT_ONLINE redo 0/8004B870; tli 1; prev tli 1; fpw true; xid 0/718242; oid 61709; multi 1; offset 0; oldest xid 931 in DB 19697; oldest multi 1 in DB 19697; oldest/newest commit timestamp xid: 0/0; oldest running xid 0; online

解释一下pg_xlogdump各个字段的意思:

rmgr: Heap
PostgreSQL内部将WAL日志归类到20多种不同的资源管理器。这条WAL记录所属资源管理器为Heap,即堆表。除了Heap还有Btree,Transaction等。
len (rec/tot): 3/ 59
WAL记录的总长度是59字节,其中main data部分是3字节(只计数main data可能并不合理,本文的后面会有说明)。
tx: 718239
事务号
lsn: 0/8004B738
本WAL记录的LSN
prev 0/8004B710
上条WAL记录的LSN
desc: INSERT+INIT off 1
这是一条insert类型的记录(每个资源管理器最多包含16种不同的WAL记录类型,),tuple在page中的位置为1。
blkref #0: rel 1663/16384/53523 blk 0
引用的第一个page所属的对表文件为1663/16384/53523,块号为0(即ctid的前半部分)。通过oid2name可以查到是哪个堆表。 apple=# select pg_relation_filepath('test');
pg_relation_filepath
----------------------
base/16384/53523
(1 row)

再回顾一下pg_xlogdump的使用方法:

appledeMacBook-Pro-2:service_list apple$ pg_xlogdump --help
pg_xlogdump decodes and displays PostgreSQL transaction logs for debugging. Usage:
pg_xlogdump [OPTION]... [STARTSEG [ENDSEG]] Options:
-b, --bkp-details output detailed information about backup blocks
-e, --end=RECPTR stop reading at log position RECPTR
-f, --follow keep retrying after reaching end of WAL
-n, --limit=N number of records to display
-p, --path=PATH directory in which to find log segment files
(default: ./pg_xlog)
-r, --rmgr=RMGR only show records generated by resource manager RMGR
use --rmgr=list to list valid resource manager names
-s, --start=RECPTR start reading at log position RECPTR
-t, --timeline=TLI timeline from which to read log records
(default: 1 or the value used in STARTSEG)
-V, --version output version information, then exit
-x, --xid=XID only show records with TransactionId XID
-z, --stats[=record] show statistics instead of records
(optionally, show per-record statistics)
-?, --help show this help, then exit

--对-b说明一下:Data portion of XLOG record is classified into either backup block (entire page) or non-backup block (different data by operation).

我们再关注一下对WAL的统计信息:

appledeMacBook-Pro-2:data apple$ pg_xlogdump -p pg_xlog -z -s 0/80000098 -e 0/8001B9D0
Type N (%) Record size (%) FPI size (%) Combined size (%)
---- - --- ----------- --- -------- --- ------------- ---
XLOG 1 ( 1.08) 28 ( 1.01) 0 ( 0.00) 28 ( 0.03)
Transaction 5 ( 5.38) 216 ( 7.76) 0 ( 0.00) 216 ( 0.20)
Storage 1 ( 1.08) 40 ( 1.44) 0 ( 0.00) 40 ( 0.04)
CLOG 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
Database 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
Tablespace 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
MultiXact 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
RelMap 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
Standby 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
Heap2 2 ( 2.15) 64 ( 2.30) 6236 ( 5.89) 6300 ( 5.80)
Heap 57 ( 61.29) 1734 ( 62.28) 37060 ( 35.00) 38794 ( 35.69)
Btree 27 ( 29.03) 702 ( 25.22) 62604 ( 59.12) 63306 ( 58.25)
Hash 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
Gin 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
Gist 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
Sequence 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
SPGist 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
BRIN 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
CommitTs 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
ReplicationOrigin 0 ( 0.00) 0 ( 0.00) 0 ( 0.00) 0 ( 0.00)
-------- -------- -------- --------
Total 93 2784 [2.56%] 105900 [97.44%] 108684 [100%]

各个列的解释:

各个列的解释:
Type:xlog中的日志类型
N: 次数及占比
Record size:记录的大小及占比
FPI size: full page image大小及占比
combined size: 记录和FPI的大小总和

我们看到WAL中的FPI占比非常大,到了97.44%,真正记录Record的信息才2.56%,那么为什么会这样呢,这样合理吗?

FPI的来源是设置了full_page_writes=on,每个Checkpoint之后的修改的数据页都会记录到wal中,导致wal中的FPI占比就很大。

因此,有人就说加大两个Checkpoint点之间的时间间隔,可以减少FPI的占比,这是不合理的,官网上说是每个Checkpoint之后改变的page都会写入到wal,而很多人理解为Checkpoint之后,第一个被修改的page才会写入到wal,这是错误的的理解:

When this parameter is on, the PostgreSQL server writes the entire content of each disk page to WAL during the first modification of that page after a checkpoint.

那么这里又引申出为什么要设置full_page_writes=on?

当一个崩溃发生在Checkpoint过程中,导致部分page中数据已经刷新了,某些page中的数据可能才写了一半。那么我们在重启数据库进行恢复时,会从上一个完成的Checkpoint点开始回放,如果没有FPI,则会基于已经刷新的page进行修改,这是错误的。

这是典型的部分写问题,我们应该从两个方面理解部分写:

1)某个page只写了一部分,就发生了crash;

2)这一批要刷新的page,只有一部分被更新了,仍然有一部分没有写入。

针对1)中的情况,我们可以选用支持原子写的文件系统来解决,我们保证写page的操作是原子的,要么失败,要么成功。目前有ZFS文件系统,ext4的事务写也可以解决,设置data=journal。

针对2)中的情况,单纯使用文件系统的原子写还是无法解决,因此只有通过full_page_writes=on来解决。

针对2)的情况,可以使用集群的方式,从备库进行恢复。

那么说到最后,我们可以这么总结吗:如果有高可用集群,那么我们可以将full_page_writes设置为false来提升性能???

下面是一个非官方的统计:设置了full_page_writes=on,数据库的TPS会减少30%以上,WAL日志大小会增加500%以上,对page更新越稀疏,问题越严重。

针对WAL日志增加太多的情况,我们可以使用wal_compression=on来进行压缩,一般可以减少50%左右,且TPS也有少量的提升。

再次强调,设置checkpoint_timeout没有用处,因为每个被改变的page都会写入到wal中。

后续引申出Checkpoint的工作原理、fsync的设置问题、double write来替代full_page_writes,找机会再记录一下。

 

由pg_xlogdump统计信息想到的问题的更多相关文章

  1. DDD实践问题之 - 关于论坛的帖子回复统计信息的更新的思考

    之前,在用ENode开发forum案例时,遇到了关于如何实现论坛帖子的回复的统计信息如何更新的问题.后来找到了自己认为比较合理的解决方案,分享给大家.也希望能和大家交流,擦出更多的火花. 论坛核心领域 ...

  2. MySQL 8.0 中统计信息直方图的尝试

    直方图是表上某个字段在按照一定百分比和规律采样后的数据分布的一种描述,最重要的作用之一就是根据查询条件,预估符合条件的数据量,为sql执行计划的生成提供重要的依据在MySQL 8.0之前的版本中,My ...

  3. SQL Server 数据库表的统计信息的更新

             最近在调整基础信息数据时,新增了几个客户类型,意想不到的事情发生了,在使用新增的客户类型作为 查询条件查询报表时,居然出现了超时的现象,但是用其他以前的客户类型查询就没有问题,用一个 ...

  4. Linux性能优化之内存性能统计信息

    关于内存的概念及其原理在任何一本介绍操作系统的书本中都可以查阅到. 理论放一遍,在Linux操作系统中如何查看系统内存使用情况呢?看看内存统计信息有哪些维度. 一.内存使用量 详细使用方法,man f ...

  5. SQL Server 统计信息更新时采样百分比对数据预估准确性的影响

    为什么要写统计信息 最近看到园子里有人写统计信息,楼主也来凑热闹. 话说经常做数据库的,尤其是做开发的或者优化的,统计信息造成的性能问题应该说是司空见惯. 当然解决办法也并非一成不变,“一招鲜吃遍天” ...

  6. SQL Server 执行计划利用统计信息对数据行的预估原理二(为什么复合索引列顺序会影响到执行计划对数据行的预估)

    本文出处:http://www.cnblogs.com/wy123/p/6008477.html 关于统计信息对数据行数做预估,之前写过对非相关列(单独或者单独的索引列)进行预估时候的算法,参考这里. ...

  7. SQL Server2016 新功能实时查询统计信息

    SQL Server2016 新功能实时查询统计信息 很多时候有这样的场景,开发抱怨DBA没有调优好数据库,DBA抱怨开发写的程序代码差,因此,DBA和开发都成为了死对头,无法真正排查问题. DBA只 ...

  8. OstrichNet 简易统计信息收集工具

    Ostrich 是twitter用于监控服务器性能的一个scala库,项目地址https://github.com/twitter/ostrich, 主要功能是收集.展示统计信息, 同时也提供了关闭服 ...

  9. 通过手动创建统计信息优化sql查询性能案例

    本质原因在于:SQL Server 统计信息只包含复合索引的第一个列的信息,而不包含复合索引数据组合的信息 来源于工作中的一个实际问题, 这里是组合列数据不均匀导致查询无法预估数据行数,从而导致无法选 ...

随机推荐

  1. python ros 创建节点订阅robot_pose

    建立文件夹hello_rospy,再在该目录下建立子目录src,cd到该src目录,运行如下命令创建工作包 catkin_create_pkg beginner_tutorials std_msgs ...

  2. python 文件分割

    import sys,os def split(fromfile,todir,chunksize): partnum = inputfile = open(fromfile,'rb')#open th ...

  3. python 生成元组

    #create a tuple l = [(,), (,), (,)] print(list(zip(*l)))

  4. .NET身份证验证

    身份证号码编码规则及校验位校验算法 算法地址:http://jingyan.baidu.com/article/7f41ececff944a593d095c8c.html 简单验证长度 /// < ...

  5. c语言的左移和右移

    转自:https://www.cnblogs.com/myblesh/articles/2431806.html 先说左移,左移就是把一个数的所有位都向左移动若干位,在C中用<<运算符.例 ...

  6. Spring AOP 切面编程记录日志和接口执行时间

    最近客户现在提出系统访问非常慢,需要优化提升访问速度,在排查了nginx.tomcat内存和服务器负载之后,判断是数据库查询速度慢,进一步排查发现是因为部分视图和表查询特别慢导致了整个系统的响应时间特 ...

  7. C#中类的序列化和反序列化

    说明:本文演示将类序列化后写入记事本并从记事本读取反序列化为对象1.首先创建一个类,同时类必须标识为Serializable,如下: [Serializable] public class Regio ...

  8. delphi文件名获取方法

    取文件名 ExtractFileName(FileName); 取文件扩展名: ExtractFileExt(filename); 取文件名,不带扩展名: 方法一:   Function Extrac ...

  9. Sergey's problem CodeForces - 1019C (图论,构造,神题)

    链接 大意: 给定有向图, 求选择一个点集$S$, 使得$S$任意两点不相连, 且对于不属于$S$的任意点$x$, 均存在$S$中的点$y$, 使得$d(x,y)<=2$, $d(x,y)$为从 ...

  10. IP分类

    IP: IP分为公有ip和私有ip. 私有ip分为以下5类: 类别 ip范围 子网掩码 A 1.0.0.0------127.255.255.255 255.0.0.0 B 128.0.0.0---1 ...