通过上面的描述,我们知道一条查询SQL执行的主要过程,客户端执行一条SQL前需要先经过连接数据库、解析器、优化器、执行器等阶段,再由执行器返回查询结果,具体过程可以参考下面的简图。
查询SQL是对已有数据的访问和返回,一般情况下不会涉及到数据存储的更新,那么有数据更新的场景是怎么执行的呢?
你是不是也遇到过或者听说过误操作导致数据表被删除或者写乱,需要回到操作前的某一时间点的案例,它是怎么做到的呢?
常见的生产系统都有主备节点,主节点出现故障时可以通过切换备机快速恢复业务,主备之间的数据同步是通过什么来完成的呢?
接下来我们以一条UPDATE SQL来举例,下面的表有一个主键ID1和一个整型字段ID2,两个字符字段C1和C2,下面是更新SQL操作:
postgres=> update t10 set id2=id2+2 where id1=156;
对于一条更新SQL来说,它和查询SQL一样要经过SQL解析、优化、执行等阶段,同时会多出来写WAL(Write Ahead Logging)日志的步骤。顾名思义,数据库在执行更新操作前先写日志,后写数据。
以上面的UPDATE操作为例,执行器从存储读入ID1=156的数据到内存中,并在内存中做ID2+2计算,完成计算后并不马上把这条记录刷新到硬盘,而是先记录一条日志,就告诉客户端这个操作已经完成,继续处理其他任务。
在10版本以前,WAL日志叫做XLOG日志,10版本之后统一更名为WAL。它有以下几个特点,这些特点和数据库运维息息相关:
第一、WAL日志记录物理文件块变更信息,而不是逻辑变化,我们常常有听到能不能把WAL日志解析成SQL,我想看看当时执行的SQL是什么样的,PostgreSQL本身功能是不支持WAL转换成SQL的。好在PostgreSQL是一种开放式设计,开发之后留有很多hook,可以方便的实现很多个性需求。 开源WalMiner插件可以非常方便的把WAL转换成前滚和回滚SQL,下面是工具链接,有兴趣可以尝试下:https://gitee.com/movead/XLogMiner。
第二、固定大小16MB,WAL日志文件序号向上递增,依次顺序写入。
├── pg_wal
│ ├── 000000010000000100000018
│ ├── 000000010000000100000019
│ ├── 00000001000000010000001A
│ └── archive_status
从WAL日志设计看,随着业务不断写数据,日志文件也会一直堆积,那么必然会导致硬盘容量占满,针对这个问题PostgreSQL设计了专门的archive进程做日志归档。在PG12及之前版本中通过wal_keep_segments参数设置保留WAL日志的个数,而在PG13版本中,该参数修改为wal_keep_size。在实际运维过程,经常出现WAL堆积的问题,著名的CheckPoint Skip也会影响WAL归档。
第三、顺序写入,WAL日志按事务提交顺序写入,虽然现在SSD硬盘已经非常普遍的应用,但是顺序写入性能相对随机读写依然有很大优势。
WAL日志非常重要,那么怎么保证它的完整性就是一个重要课题,此处先知道它由synchronous_commit参数控制刷盘策略,后面再聊WAL日志的应用。
如何恢复数据到任意时间点呢,比如说误操作某个表要恢复上午10点?
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。