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.mzph.cn/news/879711.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【无标题】Java_Se 数据变量与运算符

标识符、变量、常量、数据类型、运算符、基本数据类型的类型转换等。这些是编程中的“砖块”&#xff0c;是编程的基础。要想开始正式编程&#xff0c;还需要再学“控制语句”&#xff0c;控制语句就像“水泥”&#xff0c;可以把“砖块”粘到一起&#xff0c;最终形成“一座大…

华为OD机试 - 二维伞的雨滴效应(Python/JS/C/C++ 2024 E卷 200分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试真题&#xff08;Python/JS/C/C&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加入华为OD刷题交流群&#xff0c;…

ClickHouse-Kafka Engine 正确的使用方式

Kafka 是大数据领域非常流行的一款分布式消息中间件&#xff0c;是实时计算中必不可少的一环&#xff0c;同时一款 OLAP 系统能否对接 Kafka 也算是考量是否具备流批一体的衡量指标之一。ClickHouse 的 Kafka 表引擎能够直接与 Kafka 系统对接&#xff0c;进而订阅 Kafka 中的 …

镀金引线---

一、沉金和镀金 沉金和镀金都是常见的PCB金手指处理方式&#xff0c;它们各有优劣势&#xff0c;选择哪种方式取决于具体的应用需求和预算。 沉金&#xff08;ENIG&#xff09;是一种常用的金手指处理方式&#xff0c;它通过在金手指表面沉积一层金层来提高接触性能和耐腐蚀性…

【C++】模拟实现vector

在上篇中我们已经了解过的vector各种接口的功能使用&#xff0c;接下来我们就试着模拟实现一下吧&#xff01; 注意&#xff1a;我们在此实现的和C标准库中实现的有所不同&#xff0c;其目的主要是帮助大家大概理解底层原理。 我们模拟vector容器的大致框架是&#xff1a; t…

2024年【四川省安全员B证】新版试题及四川省安全员B证考试试卷

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 四川省安全员B证新版试题参考答案及四川省安全员B证考试试题解析是安全生产模拟考试一点通题库老师及四川省安全员B证操作证已考过的学员汇总&#xff0c;相对有效帮助四川省安全员B证考试试卷学员顺利通过考试。 1、…

【webpack4系列】webpack基础用法(二)

文章目录 entryoutputloaderpluginmode前端构建基础配置关联HTML插件html-webpack-plugin构建 CSS 解析 ES6和React JSX解析 ES6解析 React JSX 解析CSS、Less和Sass解析CSS解析Less解析sass 解析图片和字体资源解析&#xff1a;解析图片资源解析&#xff1a;解析字体资源解析&…

JS - 获取剪切板内容 Clipboard API

目录 1&#xff0c;需求最终效果 2&#xff0c;实现示例 3&#xff0c;注意点1&#xff0c;只支持安全上下文环境2&#xff0c;只能读取当前页面的剪切板3&#xff0c;权限获取问题4&#xff0c;获取内容的 MIME_TYPE 问题1&#xff0c;文本内容2&#xff0c;图片内容 5&#x…

魅思-视频管理系统 getOrderStatus SQL注入漏洞复现

0x01 产品简介 魅思-视频管理系统是一款集成了视频管理、用户管理、手机端应用封装等功能的综合性视频管理系统。该系统不仅以其强大的视频管理功能、灵活的用户管理机制、便捷的手机端应用封装功能以及高安全性和现代化的界面设计,成为了市场上备受关注的视频管理系统之一。…

一个基于 laravel 和 amis 开发的后台框架, 友好的组件使用体验,可轻松实现复杂页面(附源码)

前言 随着互联网应用的发展&#xff0c;后台管理系统的复杂度不断增加&#xff0c;对于开发者而言&#xff0c;既要系统的功能完备&#xff0c;又要追求开发效率的提升。然而&#xff0c;传统的开发方式往往会导致大量的重复劳动&#xff0c;尤其是在构建复杂的管理页面时。有…

Web植物管理系统-下位机部分

本节主要展示上位机部分&#xff0c;采用BSP编程&#xff0c;不附带BSP中各个头文件的说明&#xff0c;仅仅是对main逻辑进行解释 main.c 上下位机通信 通过串口通信&#xff0c;有两位数据验证头&#xff08;verify数组中保存对应的数据头 0xAA55) 通信格式 上位发送11字节…

机器学习:opencv--图像金字塔

目录 一、图像金字塔 1.图像金字塔是什么&#xff1f; 2.有哪些常见类型&#xff1f; 3.金字塔的构建过程 4.图像金字塔的作用 二、图像金字塔中的操作 1.向下采样 2.向上采样 3.注意--无法复原 三、代码实现 1.高斯金字塔向下采样 2.高斯金字塔向上采样 3.无法复…

基于SpringBoot+Vue+MySQL的志愿服务管理系统

系统展示 用户前台界面 管理员后台界面 系统背景 随着社会对志愿服务需求的日益增长&#xff0c;传统的志愿服务管理方式已难以满足高效、透明、精准的管理需求。为提升志愿服务组织的运营效率&#xff0c;优化资源配置&#xff0c;增强志愿者参与度和满意度&#xff0c;开发基…

LinuxC高级作业1

1.已知网址www.hqyj.com截取出网址的每一个部分 2.整理思维导图 3.将配置桥接网络的过程整理成文档 i)) 保证虚拟机提供了桥接模式 菜单栏中 ----> 虚拟机 -----> 设置 -----> 网络适配器 ii) 保证虚拟机可以设置桥接网络 菜单栏中 ----> 编辑 -----> 虚拟网…

linux第一课(操作系统核心)

一.关于linux (1)linux是一款开源的操作系统(是多用户&#xff0c;多任务&#xff0c;多线程)。 (2)一般所说的linux指的是linux核心&#xff0c;即对计算机硬件资源负责调度管理&#xff0c;主要职责是进程管理&#xff0c;内存管理文件系统&#xff0c;设备驱动&#xff0c…

禹神3小时快速上手typescript

一、TypeScript简介 TypeScript 由微软开发&#xff0c;是基于 JavaScript 的⼀个扩展语⾔。TypeScript 包含了 JavaScript 的所有内容&#xff0c;即&#xff1a; TypeScript 是 JavaScrip t 的超集。TypeScript 增加了&#xff1a;静态类型检查、接⼝、 泛型等很多现代开发特…

(计算机毕设)基于SpringBoot+Vue的“乐锄”农产品销售网站的设计与实现

毕业设计&#xff08;论文&#xff09; 博主可接毕设&#xff01;&#xff01;&#xff01; 基于SpringBootVue的“乐锄”农产品销售网站的设计与实现 摘 要 传统的农资采购销售模式&#xff0c;造成农业生产的效率和质量低&#xff0c;人们对食品安全问题关注不断增加&#x…

golang 字符串浅析

go的字符串是只读的 测试源代码 package mainimport ("fmt""unsafe" )func swap(x, y string) (string, string) {return y, x }func print_string(obj *string, msg string) {string_ptr : (*[2]uintptr)(unsafe.Pointer(obj))first_obj_addr : string_…

前后端分离,使用MOCK进行数据模拟开发,让前端攻城师独立于后端进行开发

mock是什么 Mock生成随机数据,拦截Ajax 请求&#xff0c;前后端分离&#xff0c;让前端攻城师独立于后端进行开发。 增加单元测试的真实性 通过随机数据,模拟各种场景。 在实际开发过程中&#xff0c;前端是通过axios来请求数据的&#xff0c;很多时候前端开发者就是通过写固定…

1.Seata 1.5.2 seata-server搭建

一&#xff1a;Seata基本介绍 Seata是一款开源的分布式事务解决方案&#xff0c;致力于在微服务架构下提供高性能和简单易用的分布式事务服务。 详见官网链接&#xff1a;https://seata.apache.org/zh-cn/ 1.历史项目里的使用经验&#xff1a; 之前公司里的oem用户对应的App…