最近深入理解了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. 马尔科夫随机场模型(MRF-Markov Random Field)

    原文: http://blog.sina.com.cn/s/blog_92c398b00102vs3q.html 马尔科夫过程​ 隐马尔科夫过程​​ 与马尔科夫相比,隐马尔可夫模型则是双重随机过程,不 ...

  2. Python的函数参数传递

    a = 1 def fun(a): a = 2 fun(a) print a # 1 a = [] def fun(a): a.append(1) fun(a) print a # [1]

  3. Jmeter工具做性能测试 常见的错误汇总

    在Win机器上用Jmeter做性能测试,汇总下我自身遇到的错误和解决方案 java.net.BindException: Address already in use: JVM_Bind 原因分析:压 ...

  4. MongoDB(课时16 分页显示)

    3.4.2.11 数据分页显示 在MongoDB里面的数据分页显示也是符合于大数据要求的操作函数: skip(n):表示跨过多少数据行 limit(n):取出的数据行的个数限制 范例:分页显示(比如显 ...

  5. LIBS+=

    ZC: “LIBS+=”是要结合“LIBPATH += ”一起使用的?类似下面的用法: ZC: “LIBS+=”指明lib文件的名称,“LIBPATH += ”指明lib文件的路径.最后还要把DLL文 ...

  6. Unix网络编程_卷1卷2

    1. UNIX 网络编程(第2版)第1卷:套接口API和X/Open 传输接口API PDFhttp://www.linuxidc.com/Linux/2014-04/100155.htm UNIX网 ...

  7. mysql 超大数据/表管理技巧

    如果你对长篇大论没有兴趣,也可以直接看看结果,或许你对结果感兴趣.在实际应用中经过存储.优化可以做到在超过9千万数据中的查询响应速度控制在1到20毫秒.看上去是个不错的成绩,不过优化这条路没有终点,当 ...

  8. eclipse开发go语言入门案例

    1.配置eclipse下配置GO语言的插件 点击eclipse的“Help”菜单,找到“Install New Software…”菜单项.如下图: 点击“Install New Software…” ...

  9. AngularJs filter 过滤器基础【转】

    Filter Ng里的过滤器. currency:把一个数字格式化成货币模式(如$1,234.56).当没有提供任何货币符号时,默认使用当前区域的符号. 使用: HTML:{{ currency_ex ...

  10. m_Orchestrate learning system---三十三、公共变量多弄成全局变量

    m_Orchestrate learning system---三十三.公共变量多弄成全局变量 一.总结 一句话总结:比如班级id,小组id,这样省事,而且减少数据库的访问,加快访问速度,而且节约代码 ...