当前位置: 首页 > news >正文

postgresql 从应用角度看快照snapshot使用,事务隔离控制不再神密

专栏内容:postgresql内核源码分析
个人主页:我的主页
座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物.

快照使用

快照是事务中使用,配合事务的隔离级别,体现出不同的可见性。
快照在事务中自动获取,我们可以通过查看当前事务的快照和事务号来判断分析。

为了方便演示,我们先创建一张表

postgres=> create table neworder(o_id integer primary key, o_info varchar, o_time timestamp);
CREATE TABLE

快照查询

第一个事务

postgres=*> select txid_current();txid_current
--------------685103
(1 row)

查看当前事务号为685103
注意 txid_current() 每调一次这个函数,会消费一个事务号,在事务中只消费一个。

postgres=*> select pg_current_snapshot();pg_current_snapshot
---------------------685103:685103:
(1 row)

查看当前事务的快照,格式为xmin:xmax:运行中的xid列表。
我们看到xmin,xmax 为685103,说明当前没有运行的事务,最新分发的事务号就是685103

注意 这里并没有分配正在运行的事务号,只有执行写操作后才开始分配
我们在另一个终端开启一个新事务,查看快照,并没有发现685103在正在运行的列表中

postgres=> begin;
BEGIN
postgres=*> select txid_current();txid_current
--------------685104
(1 row)postgres=*>  select pg_current_snapshot();pg_current_snapshot
---------------------685103:685103:
(1 row)postgres=*> end;
COMMIT

第二个事务

  • 在终端一的事务上插入一行数据
postgres=*> insert into neworder values(1,'football',now());
INSERT 0 1

这样做,让此事务有运行中的事务号

  • 我们这里在第二个终端重新开启一个事务
postgres=> begin;
BEGIN
postgres=*> select txid_current();txid_current
--------------685105
(1 row)postgres=*>  select pg_current_snapshot();pg_current_snapshot
----------------------685103:685105:685103
(1 row)

我们看到当前快照中xmin为685103,正在运行的最小事务号;
xmax为685105 ,正在运行中只有一个事务

不同隔离级别的快照

读已提交

我们启动了两个默认为读已经提交的事务

  • 现在在终端二上继续执行
postgres=*> create table neworder1(o1_id int);
CREATE TABLE
postgres=*>  select pg_current_snapshot();pg_current_snapshot
----------------------685103:685105:685103
(1 row)

创建了一张表,快照没有发生变化

  • 终端一上提交事务
postgres=*> commit;
COMMIT
  • 在终端二事务中插入数据
postgres=*> insert into neworder values(2,'basketball',now());
INSERT 0 1
postgres=*>  select pg_current_snapshot();pg_current_snapshot
---------------------685105:685105:
(1 row)

此时查看到的快照发生了变化,xmin为自己事务,当前运行中的事务没有了。

  • 原理
    读已经提交的快照,在每次命令都会获取新的快照,如果有提交的事务,那么就会变为可见
postgres=*> select * from neworder;o_id |   o_info   |           o_time
------+------------+----------------------------1 | football   | 2023-06-21 08:56:43.5416682 | basketball | 2023-06-21 09:15:10.313662
(2 rows)

此时就可以看到前一事务插入的数据

可重复读

  • 终端一启动可重复读事务
postgres=> begin isolation level repeatable read ;
BEGIN
postgres=*> insert into neworder values(3,'delicious food',now());
INSERT 0 1
postgres=*> select txid_current();txid_current
--------------685107
(1 row)postgres=*> select pg_current_snapshot();pg_current_snapshot
---------------------685107:685107:
(1 row)

快照中,此时没有正在运行中的事务,xmin就是自己的事务号

  • 终端二启动可重复读事务
postgres=>  begin isolation level repeatable read ;
BEGIN
postgres=*> insert into neworder1 values(1);
INSERT 0 1
postgres=*> select txid_current();txid_current
--------------685108
(1 row)postgres=*>  select pg_current_snapshot();pg_current_snapshot
---------------------685107:685107:
(1 row)

快照中,此时运行中的事务xmin为685107,xmax也为685107

  • 终端二提交事务
postgres=*> commit;
COMMIT
  • 终端一执行插入
postgres=*> insert into neworder values(4,'delicious tomato',now());
INSERT 0 1
postgres=*> select pg_current_snapshot();pg_current_snapshot
---------------------685107:685107:
(1 row)

事务快照并没有变化

  • 原理
    对于可重复读,每个事务只获取一次快照,这样可见性在事务开始时就已经确定

快照对于系统字典的隔离

在使用对应的表后,对于读写会产生冲突,导致阻塞;
如果没有使用要修改的表,则不会产生冲突。

读已提交

如果事务没有操作过该表,在另一事务修改提交,就可以看到修改;

先启动事务1,操作表neworder1,然后在事务2操作neworder的表定义,提交事务2后,在事务1进行查看。

事务1

postgres=> begin;
BEGIN
postgres=*> insert into neworder1 values(5);
INSERT 0 1

事务2 修改数据字典

postgres=> begin;
BEGIN
postgres=*>
postgres=*> alter table neworder drop column o_time;
ALTER TABLE
postgres=*> commit;
COMMIT

事务1 查询数据字典的同步,可以看到neworder已经没有了o_time列

postgres=*> select * from neworder;o_id |      o_info
------+------------------1 | football2 | basketball3 | delicious food4 | delicious tomato10 | potato
(5 rows)postgres=*> commit;
COMMIT

可重复读

和上面顺序一样,先启动事务1,操作表neworder1,然后在事务2操作neworder的表定义,提交事务2后,在事务1进行查看。

事务1

postgres=> begin;
BEGIN
postgres=*> insert into neworder1 values(5);
INSERT 0 1

事务2 修改数据字典,增加列o_time

postgres=> begin isolation level repeatable read ;
BEGIN
postgres=*> alter table neworder add column o_time timestamp;
ALTER TABLE
postgres=*> commit;
COMMIT

事务1 查询数据字典的同步

postgres=*> select * from neworder;o_id |      o_info      | o_time
------+------------------+--------1 | football         |2 | basketball       |3 | delicious food   |4 | delicious tomato |10 | potato           |
(5 rows)postgres=*> select pg_current_snapshot();pg_current_snapshot
---------------------685125:685125:
(1 row)postgres=*> select txid_current();txid_current
--------------685125
(1 row)postgres=*>

与预期不一样的事情发了 这里在可重复读时,系统字典的更新可以被看到了。
这一点在源码分析时,没有被关注到。

导出快照

快照还可以保存,被重复使用,有点像科幻中保存记忆一样。
下面我们来看看如何使用这一特异功能。

导出介绍

开启事务1,保存事务1的快照,然后在别一个事务中应用此快照,那么这两个事务看到的内容是一样的。

事务1 启动可重复读事务,并导出快照

postgres=> begin isolation level repeatable read ;
BEGIN
postgres=*> insert into neworder1 values(5);
INSERT 0 1postgres=*> select pg_current_snapshot();pg_current_snapshot
---------------------685125:685125:
(1 row)postgres=*> select txid_current();txid_current
--------------685125
(1 row)postgres=*> select * from neworder;o_id |      o_info      | o_time
------+------------------+--------1 | football         |2 | basketball       |3 | delicious food   |4 | delicious tomato |10 | potato           |
(5 rows)postgres=*> SELECT pg_export_snapshot();pg_export_snapshot
---------------------00000004-00000058-1
(1 row)

使用旧快照

旧快照能被使用的前提是,生成旧快照必须有事务在使用,否则快照就是一个过期快照

事务2 在启动事务2前,向neworder表中插入数据,然后启动事务2,在其中使用保存的快照

postgres=> insert into neworder values(100,'test dic',now());
INSERT 0 1
postgres=> insert into neworder values(101,'erase',now());
INSERT 0 1
postgres=> select * from neworder;o_id |      o_info      |           o_time
------+------------------+----------------------------1 | football         |2 | basketball       |3 | delicious food   |4 | delicious tomato |10 | potato           |100 | test dic         | 2023-06-22 10:50:35.238614101 | erase            | 2023-06-22 10:55:12.268132
(7 rows)
postgres=> BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGINpostgres=*> set transaction snapshot '00000004-00000058-1';
SET
postgres=*> select * from neworder;o_id |      o_info      | o_time
------+------------------+--------1 | football         |2 | basketball       |3 | delicious food   |4 | delicious tomato |10 | potato           |
(5 rows)postgres=*>  select pg_current_snapshot();pg_current_snapshot
---------------------685125:685125:
(1 row)

结尾

非常感谢大家的支持,在浏览的同时别忘了留下您宝贵的评论,如果觉得值得鼓励,请点赞,收藏,我会更加努力!

作者邮箱:study@senllang.onaliyun.com
如有错误或者疏漏欢迎指出,互相学习。

注:未经同意,不得转载!

相关文章:

postgresql 从应用角度看快照snapshot使用,事务隔离控制不再神密

​专栏内容:postgresql内核源码分析 个人主页:我的主页 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 快照使用 快照是事务中使用,配合事务的隔离级别,体现出不同的可见性。…...

mysql(mariadb)读写分离部署

目录 一、原理 二、准备环境 三、部署mysql主从复制 1.五台服务器下载mariadb 2.修改master配置文件,重启数据库 3.登录mysql创建replication 4.从服务器登录验证 5.获得master服务器 DB的相关信息 6.备份master原有数据 7.修改slave1、slave2配置 8. 进入…...

ES-工作原理

前言 ​ 搜索引擎是对数据的检索,而数据总体分为两种:结构化数据和非结构化数据。而对于结构化数据,因为他们具有特定的结构,所以一般都是可以通过关系型数据库MySQL/oracle的二维表的方式存储和搜索,也可以建立索引。…...

C++小结(4)

C 字符串 C 提供了两种类型的字符串表示形式: C 风格字符串C 引入的 string 类类型 C 风格字符串 C 风格的字符串起源于 C 语言,并在 C 中继续得到支持。字符串实际上是使用 null 字符 \0 终止的一维字符数组。因此,一个以 null 结尾的字…...

Java框架之spring 的 messaging

写在前面 本文看下spring message相关的内容。 1:Message?Messaging? Message是消息的意思,是一个名词。而Messaging是一个动名词,是将消息发送出去的意思,因此,我们的消息系统是messaging s…...

linux使用grep命令查询nginx的进程情况时总是出现 grep --color=auto nginx

问题: 每次使用ps aux | grep 服务名 命令查询某个服务的进程时,总会出现一条grep --colorauto 服务名 例如: ps aux | grep nginx # 会出现图片中的情况解答: 这是因为grep 也是一条命令,它在输出时,会…...

FFmpeg音视频开发知识点(二)

系列文章目录 FFmpeg音视频开发知识点(一) 文章目录 系列文章目录前言一、AAC音频编码1. ffmpeg编译第三方的libfdk_aac2. S16重采样FLTP 二、AAC音频解码总结 前言 该篇讲解一下,音频编解码中的难点,以及开发过程中遇到问题&am…...

【Java可执行命令】(十)JAR文件签名工具 jarsigner:通过数字签名及验证保证代码信任与安全,深入解析 Java的 jarsigner命令~

Java可执行命令之jarsigner 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用3.1 语法3.1.1 可选参数&#xff1a;jarsigner -keystore < url>3.1.2 可选参数&#xff1a;jarsigner -storepass <口令>3.1.3 可选参数&#xff1a;jarsigner -keypass <口令>3.1.4 可选参…...

c#调用c++ dll,Release版本内存访问错误

最近遇到个比较经典的案例&#xff0c;在c#中调用yara进行文件检测&#xff0c;yara是c编写的一个非常强大库&#xff0c;github有个大佬用c#对其进行了封装&#xff0c;使其能在跨平台下&#xff0c;只需编译yara的so或dll就能直接跑。但总是在Release版本下时不时就崩溃&…...

内网安全:Cobalt Strike 与 MSF 联动( 会话 相互转移 )

内网安全&#xff1a;Cobalt Strike 与 MSF 联动&#xff08; 会话 相互转移 &#xff09; 在渗透中&#xff0c;有时候 Cobalt Strike 会话可能会受限制&#xff0c;所以我们需要把 Cobalt Strike 会话转移到 MSF 上进行后面的渗透。也有的时候会话在 MSF 上&#xff0c;但是…...

性能测试讲解超详细Jmeter

目录 什么是性能 性能测试的目的 功能测试和性能测试 基准测试 负载测试 稳定性测试 压力测试 并发测试 总结 性能测试指标 响应时间 并发数 吞吐量 点击数 错误率 资源使用率 总结 性能测试流程 性能测试需求分析 性能测试计划和方案 ​编辑性能测试用例​编辑 性…...

微服务 – Spring Cloud – Nacos 配置中心

微服务 – Spring Cloud – Nacos 配置中心 文章目录 微服务 – Spring Cloud – Nacos 配置中心打开nacos面板新建配置引入依赖配置文件启动类业务类打开nacos面板新建配置 Data ID: nacos-config-client-dev.yaml Group: DEV-CLOUD2023 config:info: config info lalalal …...

超细,设计一个“完美“的测试用例,用户登录模块实例...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 好的测试用例一定…...

【C#】文件拖拽,获取文件路径

系列文章 【C#】编号生成器&#xff08;定义单号规则、固定字符、流水号、业务单号&#xff09; 本文链接&#xff1a;https://blog.csdn.net/youcheng_ge/article/details/129129787 【C#】日期范围生成器&#xff08;开始日期、结束日期&#xff09; 本文链接&#xff1a;h…...

SAP PI/PO初步了解 2023.07.03

SAP PI/PO 是SAP 提供的一种集成中间件解决方案&#xff0c;用于在组织内部或不同组织之间实现系统的无缝通信和数据交换。它使企业能够以统一高效的方式集成各种应用和系统&#xff0c;无论这些系统的技术平台或数据格式如何。 以下是关于SAP PI/PO的简要概述&#xff1a; 1…...

Java中生产者消费者模型

在Java中&#xff0c;生产者消费者模型是一种常见的多线程编程模型&#xff0c;用于解决生产者和消费者之间的数据交互问题。 简介 生产者&#xff08;Producer&#xff09;负责生成数据&#xff0c;并将数据放入共享的缓冲区&#xff08;队列&#xff09;中。消费者&#xf…...

测试Hyperledger Fabric环境

首先进入fabric-samples目录中的first-networked 子目录 cd fabric-samples/first-network 在first-network目录下有一个自动化脚本byfn.sh,可以使用-help参数查看相应的可 用命令&#xff0c;在命令提示符中输入如下命令&#xff1a; ./byfn.sh --help命令执行成功后&#…...

ClickHouse查询sql长度超超过最大限制

ClickHouse查询sql长度超超过最大限制 Max query size exceeded ClickHouse exception, message: Code: 62. DB::Exception: Syntax error: failed at position 262102 (‘fwm00ud6a3ynu0kaxr.ya0eyemkbzdvrxkhwgchccll’) (line 10406, col 17): fwm00ud6a3ynu0kaxr.ya0eyemk…...

【Axure教程】拖动调整行高列宽的表格

表格是在系统软件中非常常用的工具。表格通常由行和列组成&#xff0c;用于以结构化的方式显示和组织数据。它们在各种场景中都有广泛的应用&#xff0c;包括数据分析、数据录入、报表生成、项目管理和数据可视化等领域。 今天作者就教大家如何在Axure里制作一个能通过鼠标拖动…...

中间件-netty(1)

netty 前言篇 文章目录 一、IO基础篇1.概念1.1 阻塞(Block)和非阻塞(Non-Block)1.2 同步(Synchronization)和异步(Asynchronous)1.3 BIO 与 NIO 对比1.3.1 面向流与面向缓冲1.3.2 阻塞与非阻塞1.3.3 选择器的问世 2.NIO 和 BIO 如何影响应用程序的设计2.1 API调用2.2 数据处理2…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

[特殊字符] 智能合约中的数据是如何在区块链中保持一致的?

&#x1f9e0; 智能合约中的数据是如何在区块链中保持一致的&#xff1f; 为什么所有区块链节点都能得出相同结果&#xff1f;合约调用这么复杂&#xff0c;状态真能保持一致吗&#xff1f;本篇带你从底层视角理解“状态一致性”的真相。 一、智能合约的数据存储在哪里&#xf…...

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

简易版抽奖活动的设计技术方案

1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...

《Qt C++ 与 OpenCV:解锁视频播放程序设计的奥秘》

引言:探索视频播放程序设计之旅 在当今数字化时代,多媒体应用已渗透到我们生活的方方面面,从日常的视频娱乐到专业的视频监控、视频会议系统,视频播放程序作为多媒体应用的核心组成部分,扮演着至关重要的角色。无论是在个人电脑、移动设备还是智能电视等平台上,用户都期望…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(一)

宇树机器人多姿态起立控制强化学习框架论文解析 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架&#xff08;一&#xff09; 论文解读&#xff1a;交大&港大&上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化…...

css3笔记 (1) 自用

outline: none 用于移除元素获得焦点时默认的轮廓线 broder:0 用于移除边框 font-size&#xff1a;0 用于设置字体不显示 list-style: none 消除<li> 标签默认样式 margin: xx auto 版心居中 width:100% 通栏 vertical-align 作用于行内元素 / 表格单元格&#xff…...

Java多线程实现之Thread类深度解析

Java多线程实现之Thread类深度解析 一、多线程基础概念1.1 什么是线程1.2 多线程的优势1.3 Java多线程模型 二、Thread类的基本结构与构造函数2.1 Thread类的继承关系2.2 构造函数 三、创建和启动线程3.1 继承Thread类创建线程3.2 实现Runnable接口创建线程 四、Thread类的核心…...