PostgreSQL技术内幕10:PostgreSQL事务原理解析-日志模块介绍

文章目录

    • 0.简介
    • 1.PG日志介绍
    • 2.事务日志介绍
    • 3.WAL分析
      • 3.1 WAL概述
      • 3.2 WAL设计考虑
        • 3.2.1 存储格式
        • 3.2.2 实现方式
        • 3.2.3 数据完整性校验
        • 3.3 check ponit
    • 4.事务提交日志(CLOG)
      • 4.1 clog存储使用介绍
      • 4.2 slru缓冲池并发控制

0.简介

本文将延续上一篇文章内容,上一篇介绍了PG事务涉及到的模块,本文介绍日志模块,主要介绍PG包含的日志分类,和WAL日志、CLOG的详细介绍。

1.PG日志介绍

在PG中,日志包含三种:

1)pg_log:数据库运行日志,一般用于记录数据库服务状态、sql执行情况和一些错误信息,警告信息。
2)pg_xlog:WAL(Write Ahead Log),即预写日志,记录事务日志信息。
3)pg_clog:事务提交日志,记录事务的元数据。

2.事务日志介绍

常见的事务日志分为两类,即Redo Log和Undo Log,其区别如下:
1)Redo Log:记录修改前的值,Replay时用旧值覆盖当前值,用于回滚。
2)Undo Log:记录修改后的值,Replay时用新值覆盖当前值,用于重做。
事务日志需要在数据真正修改发生之前来做记录,且Replay操作需要保证幂等性,对于PG来说,回滚并不涉及到Undo日志,而是用MVCC来处理,在下一篇会介绍PG的MVCC实现。

3.WAL分析

3.1 WAL概述

如果每次的数据修改都直接去写表文件,那么更新的代价是比较大的,需要去做硬盘随机写入且修改可能是没有顺序的,多次随机寻址和更新页面信息,所以一般会引入Buffer Pool,将数据写入内存,但是面临的问题就是如果在没有刷盘前发生系统故障,就会造成数据丢失,所以需要日志记录,相较于直接更行表文件,WAL Log代价更小。
写入顺序为:先写入WAL Log,在更新内存。在这种情况下,断电或系统故障都能准确恢复数据。
另外,现在WAL Log还可以用来做主从同步,数据备份等。

3.2 WAL设计考虑

对于WAL的设计,下面将介绍一般考虑的点和PG对应的实现

3.2.1 存储格式

数据库中的数据一般分为元数据和数据,元数据和数据可以分开存储,也可以一起存储,如下图:
在这里插入图片描述
对于PG,其WAL被分为多个文件,被称为WAL segment file,每个文件最大是16M。其命名规则是,24个字符被分为三部分:TimeLineID、逻辑文件ID、物理文件ID。每个八位,取值都是0x00000000到0xFFFFFFFF(实际上物理文件id到不了0xFFFFFFFF)。
寻址规则是:32bit的逻辑文件id+8bit的物理文件id+16M的24bit地址,组成一共64bit地址。
其内部层级如下:
在这里插入图片描述
文件中包含N个大小为8K的page,其中有两种page header,一种是XLogLongPageHeaderData,另一种是XLogPageHeaderData,除了第一个page header是XLogLongPageHeaderData,其余都是XLogPageHeaderData。


typedef struct XLogPageHeaderData
{uint16    xlp_magic;    /* magic value for correctness checks */uint16    xlp_info;    /* flag bits, see below */TimeLineID  xlp_tli;    /* TimeLineID of first record on page */XLogRecPtr  xlp_pageaddr;  /* XLOG address of this page *//** When there is not enough space on current page for whole record, we* continue on the next page.  xlp_rem_len is the number of bytes* remaining from a previous page; it tracks xl_tot_len in the initial* header.  Note that the continuation data isn't necessarily aligned.*/uint32    xlp_rem_len;  /* total len of remaining data for record */
} XLogPageHeaderData;typedef struct XLogLongPageHeaderData
{XLogPageHeaderData std;    /* standard header fields */uint64    xlp_sysid;    /* system identifier from pg_control */uint32    xlp_seg_size;  /* just as a cross-check */uint32    xlp_xlog_blcksz;  /* just as a cross-check */
} XLogLongPageHeaderData;

可以看到XLogLongPageHeaderData成员除了XLogPageHeaderData还有三个成员。xlp_sysid对应的是pg_control中的system identifier,而剩下的xlp_seg_size和xlp_xlog_blcksz为固定大小,分别为segment文件的大小(16M)和page的大小(8K)。
在一个page中,page header之后是N个XLog record。XLog record的布局和结构体信息如下:


/** The overall layout of an XLOG record is:*    Fixed-size header (XLogRecord struct)*    XLogRecordBlockHeader struct*    XLogRecordBlockHeader struct*    ...*    XLogRecordDataHeader[Short|Long] struct*    block data*    block data*    ...*    main data*/
typedef struct XLogRecord
{uint32    xl_tot_len;    /* total len of entire record */TransactionId xl_xid;    /* xact id */XLogRecPtr  xl_prev;    /* ptr to previous record in log */uint8    xl_info;    /* flag bits, see below */RmgrId    xl_rmid;    /* resource manager for this record *//* 2 bytes of padding here, initialize to zero */pg_crc32c  xl_crc;      /* CRC for this record *//* XLogRecordBlockHeaders and XLogRecordDataHeader follow, no padding */} XLogRecord;typedef struct XLogRecordBlockHeader
{uint8    id;        /* block reference ID */uint8    fork_flags;    /* fork within the relation, and flags */uint16    data_length;  /* number of payload bytes (not including page* image) *//* If BKPBLOCK_HAS_IMAGE, an XLogRecordBlockImageHeader struct follows *//* If BKPBLOCK_SAME_REL is not set, a RelFileLocator follows *//* BlockNumber follows */
} XLogRecordBlockHeader;typedef struct XLogRecordDataHeaderShort
{uint8    id;        /* XLR_BLOCK_ID_DATA_SHORT */uint8    data_length;  /* number of payload bytes */
}      XLogRecordDataHeaderShort;typedef struct XLogRecordDataHeaderLong
{uint8    id;        /* XLR_BLOCK_ID_DATA_LONG *//* followed by uint32 data_length, unaligned */
}      XLogRecordDataHeaderLong;
3.2.2 实现方式

实现方式分为Undo和Redo方式,对于PG来说,记录的是Redo日志。

3.2.3 数据完整性校验

对应数据完整性的校验,使用的是循环校验码的方式,这种方式可以有两种实现方式,一种是对整个日志块进行校验,优势的话就是速度快,缺点有一个记录损坏的话恢复代价大,要整块处理;另外一种是分段校验,对于校验速度比第一种稍慢,但出问题更容易找到出问题的小段来进行恢复,对于PG来说,可以看到,每个XLog Record都有自己的循环校验码。

3.3 check ponit

对于WAL文件和WAL buffer,在执行的过程中,数据量一直在增加,如果数量过多,会影响系统性能,PG清理机制依赖于checkpoint,其主要作用就是脏数据的写回,xlog的回收和更新Redo point(恢复启动的起点)等信息到pg_control文件中。

4.事务提交日志(CLOG)

4.1 clog存储使用介绍

CLOG日志记录的是事务的状态,在内存中是由使用SLRU作为淘汰算法的缓冲池进行缓存,由CLOG日志管理器来进行管理。
在PG事务模块一共定义了事务的四种状态:

#define TRANSACTION_STATUS_IN_PROGRESS    0x00 //事务正在运行中
#define TRANSACTION_STATUS_COMMITTED    0x01 //事务已提交
#define TRANSACTION_STATUS_ABORTED      0x02 //事务被终止
#define TRANSACTION_STATUS_SUB_COMMITTED  0x03 //事务的子事务已提交

可以看到,事务的状态只有四种,使用2byte就可以记录一个事务状态,一个page(8k)可以记录32k个日志记录。其存储文件以4位的16进制数字命名,位于PGDATA/pg_act目录下,内部内容如下:

/* We need two bits per xact, so four xacts fit in a byte --*/
#define CLOG_BITS_P ER_XACT	2  ---个事务占用2个bit位
#define CLOG_XACTS_PER_BYTE 4      --一个字节可以存放4个事务状态
#define CLOG_XACTS_PER_PAGE (BLCKSZ * CLOG_XACTS_PER_BYTE)--一个页块可以存放多少个事务状态
#define CLOG_XACT_BITMASK	((1 << CLOG_BITS_PER_XACT) - 1)#define TransactionIdToPage(xid)	((xid) / (TransactionId) CLOG_XACTS_PER_PAGE) --事务存放在第几页
#define TransactionIdToPgIndex(xid) ((xid) % (TransactionId) CLOG_XACTS_PER_PAGE) --页内的偏移量
#define TransactionIdToByte(xid)	(TransactionIdToPgIndex(xid) / CLOG_XACTS_PER_BYTE)  --页内的第几个字节
#define TransactionIdToBIndex(xid)	((xid) % (TransactionId) CLOG_XACTS_PER_BYTE)  --字节内的偏移量可以看到,有一个事务id之后,可以计算得到页,页内偏移,页内字节和字节内偏移量,从而找到事务状态。

4.2 slru缓冲池并发控制

因为slru(最近最少使用)的概念是比较容易理解的,下面主要描述PG在slru的缓冲池上实现并发控制的方式。
对于SLRU缓冲池,PG使用了两种锁来进行并发控制。
1)ControlLock:整个缓冲区的控制锁(读写锁)。
2) buffer_locks:每个缓冲区页面锁(读写锁)。
一次读取到slru的流程
获取ControlLock的全局锁-》挑选出替换的缓存,更新缓存的状态为正在读-》获取缓存的写锁-》释放ControlLock的全局锁,因为刷新磁盘的时间会很长,这里释放全局锁提高并发性能-》从文件中读取数据到缓存-》重新获取ControlLock全局锁,因为接下来要修改缓存的状态-》设置缓存的状态为有效状态-》释放ControlLock全局锁-》释放缓存的写锁,并且设置缓存为最近访问。
可以看到PG采用了分页控制的方式提高了并发操作的性能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/147593.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

59.【C语言】内存函数(memmove函数)

目录 2.memove函数 *简单使用 部分翻译 *模拟实现 方案1 方案2 1.有重叠 dest在src左侧 dest在src右侧 2.无重叠 代码 2.memove函数 *简单使用 memove:memory move cplusplus的介绍 点我跳转 对比第59篇的memcpy函数 对比memmcpy函数的介绍如下区别: 部分翻译 m…

金刚石切削工具学习笔记分享

CVD钻石-合成单晶钻石之一 金刚石具有极高的硬度和耐磨性、较低的摩擦系数、较高的弹性模量、较高的热导率、较低的热膨胀系数、与有色金属的亲和力较小等优点&#xff0c;是目前最硬的工具材料&#xff0c;主要分为单晶金刚石和聚晶金刚石两大类。单晶金刚石又分为天然单晶金…

常用卫星学习

文章目录 Landsat-8 Landsat-8 由一台操作陆地成像仪 &#xff08;OLI&#xff09; 和一台热红外传感器 &#xff08;TIRS&#xff09;的卫星&#xff0c;OLI 提供 9 个波段&#xff0c;覆盖 0.43–2.29 μm 的波长&#xff0c;其中全色波段&#xff08;一般指0.5μm到0.75μm左…

CentOS Stream 9部署MariaDB

1、更新系统软件包 sudo dnf update 2、安装MariaDB软件包&#xff08;替代mysql&#xff09; sudo dnf install mariadb-server 3、安装MariaDB服务 sudo systemctl enable --now mariadb 4、检查MariaDB服务状态 sudo systemctl status mariadb 5、配置MariaDB安全性 sudo my…

锐捷 睿易路由器存在RCE漏洞

漏洞描述 锐捷Ruijie路由器命令执行漏 漏洞复现 FOFA: icon_hash"-399311436" 点击左下角的“网络诊断”&#xff0c;在“Tracert检测”的“地址”框中&#xff0c;输入127.0.0.1;ls&#xff0c;接着点击“开始检测”&#xff0c;会在检测框中回显命令执行结果。…

代码编辑器 —— SourceInsight实用技巧

目 录 Source insight 重要性一、创建项目二、代码浏览三、代码同步 Source insight 重要性 Source Insight 是一款功能强大的代码编辑器&#xff0c;在软件开发中占据着重要地位。 Source Insight 能够帮助开发者更高效地解读和修改代码&#xff0c;提高开发效率和代码质量。…

LeetCode_sql_day31(1384.按年度列出销售总额)

目录 描述 1384.按年度列出销售总额 数据准备 分析 法一 法二 代码 总结 描述 1384.按年度列出销售总额 Product 表&#xff1a; ------------------------ | Column Name | Type | ------------------------ | product_id | int | | product_name | var…

CentOS Stream 9部署docker,并开启API

1、安装docker &#xff08;1&#xff09;安装Docker的依赖项和存储库 sudo dnf install -y dnf-plugins-core sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo &#xff08;2&#xff09;安装Docker sudo dnf install -y docke…

网站建设中,网站设计的未来发展趋势是什么

网站建设中&#xff0c;网站设计的未来发展趋势是多方面的&#xff0c;涵盖了技术革新、用户体验优化以及市场需求变化等多个维度。以下是对网站设计未来发展趋势的详细预测&#xff1a; 移动优先与响应式设计&#xff1a;随着移动设备的普及&#xff0c;未来的网站设计将更加注…

从零开始:在VSCode中打造完美的C++开发环境

在现代软件开发中&#xff0c;选择一个合适的集成开发环境 (IDE) 至关重要&#xff0c;它不仅能够提高工作效率&#xff0c;还能让编程变得更加轻松愉快。VSCode 凭借其轻量化、高度扩展性以及强大的插件生态&#xff0c;已成为众多开发者的首选。然而&#xff0c;要在 VSCode …

[Redis][Set]详细讲解

目录 0.前言1.常用命令1.SADD2.SMEMBERS3.SISMEMBER4.SCARD5.SPOP6.SMOVE7.SREM 2.集合间操作0.是什么&#xff1f;1.SINTER2.SINTERSTORE3.SUNION4.SUNIONSTORE5.SDIFF6.SDIFFSTORE 3.内部编码1.intset(整数集合)2.hashtable(哈希表) 4.使用场景 0.前言 集合类型也是保存多个字…

ReKep——李飞飞团队提出的让机器人具备空间智能:基于视觉语言模型GPT-4o和关系关键点约束

前言 由于工厂、车厂的任务需求场景非常明确&#xff0c;加之自今年年初以来&#xff0c;我司在机器人这个方向的持续大力度投入(包括南京、长沙两地机器人开发团队的先后组建)&#xff0c;使得近期我司七月接到了不少来自车厂/工厂的订单&#xff0c;比如其中的三个例子&…

数据结构与算法-18算法专向(hash)

话题引入&#xff1a; 给你N&#xff08;1<N<10&#xff09;个自然数,每个数的范围为&#xff08;1~10000000000&#xff09;。现在让你以最快的速度判断某一个数是否在这N个数内&#xff0c;不得使用已经封装好的类&#xff0c;该如何实现。 A[] new int[N1]&#xff…

芝士AI一次过!开题报告通用模板,可直接套用!

在正式写开题报告之前&#xff0c;需要搞清楚以下几个问题。 ①你选择这个论文选题的理由是什么&#xff1f;&#xff08;选题背景&#xff09; ②你打算去研究什么&#xff1f;解决什么问题&#xff1f;&#xff08;研究内容&#xff09; ③该选题目前有哪些研究&#xff0…

新峰商城之订单(二):订单生成

在订单确认页面处理完毕后&#xff0c;此时用户单击“提交订单”按钮&#xff0c;商城系统就对应生成一笔订单数据并保存在数据库中&#xff0c;此即订单生成功能。 在单击“提交订单”按钮后&#xff0c;后端会进行一系列操作&#xff0c;包括数据查询、数据判断、数据整合等&…

构建与优化自定义进程池

1. 什么是进程池&#xff1f; 简单来说&#xff0c;进程池就是预先创建固定数量的工作进程&#xff0c;通过设计任务队列或调度算法来分配任务给空闲的进程 —— 实现“负载均衡”。 2. 进程池框架设计 枚举错误返回值&#xff1a; enum {UsageError 1,ArgError,PipeError };…

人工智能时代的学与教

疫情逐渐散去之后&#xff0c;最最吸引全球目光的应该就是ChatGPT-3了。美国政治家亨利基辛格领衔出版的新书《AI世代与我们人类的未来》(The Age of AI and Our Human Future)中举了一个例子来说明ChatGPT-3的能力。首先让ChatGPT-3阅读关于它自身能力的哲学评论之后&#xff…

【吊打面试官系列-MySQL面试题】MyISAM 表格将在哪里存储,并且还提供其存储格式?

大家好&#xff0c;我是锋哥。今天分享关于【MyISAM 表格将在哪里存储&#xff0c;并且还提供其存储格式&#xff1f;】面试题&#xff0c;希望对大家有帮助&#xff1b; MyISAM 表格将在哪里存储&#xff0c;并且还提供其存储格式&#xff1f; 每个 MyISAM 表格以三种格式存储…

240912-设置WSL中的Ollama可在局域网访问

A. 最终效果 B. 设置Ollama&#xff08;前提&#xff09; sudo vim /etc/systemd/system/ollama.service[Unit] DescriptionOllama Service Afternetwork-online.target[Service] ExecStart/usr/bin/ollama serve Userollama Groupollama Restartalways RestartSec3 Environme…

读取t x t文件生成exce

读取t x t文件生成excel package com.moka.api.custom.core.controller; import com.google.gson.Gson; import com.google.gson.reflect.TypeToken; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.usermode…