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

这篇具有很好参考价值的文章主要介绍了postgresql 从应用角度看快照snapshot使用,事务隔离控制不再神密。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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.541668
    2 | 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 | football
    2 | basketball
    3 | delicious food
    4 | delicious tomato
   10 | 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 1

postgres=*> 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.238614
  101 | erase            | 2023-06-22 10:55:12.268132
(7 rows)
postgres=> BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN

postgres=*> 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
如有错误或者疏漏欢迎指出,互相学习。

注:未经同意,不得转载!文章来源地址https://www.toymoban.com/news/detail-498283.html

到了这里,关于postgresql 从应用角度看快照snapshot使用,事务隔离控制不再神密的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Elasticsearch的Snapshot and Restore(快照备份与恢复)

    简介:  Elasticsearch提供的Snapshot api就是从正在运行的集群中获取备份用的,可以根据情况选择整个集群,也可以指定index和data stream。Elasticsearch是以增量的方式获取Snapshot,节约了时间和空间,小开销意味着可以适当增加备份的频率。每一个Snapshot在逻辑上相互独立,所以删除

    2024年03月24日
    浏览(43)
  • elasticsearch snapshot快照指定多个索引并行备份——筑梦之路

    Curl 命令方式对elasticsearch备份和恢复—— 筑梦之路_筑梦之路的博客-CSDN博客 之前也写过使用API请求的方式对ES数据进行快照方式备份,这里主要对之前的内容进行完善和补充。 快照包含构成索引的磁盘上数据结构的副本。这意味着快照只能还原为可以读取索引的 Elasticsearc

    2024年02月11日
    浏览(41)
  • elasticsearch snapshot快照备份到minio对象存储S3 —— 筑梦之路

    minio 最新版 elasticsearch 7.9 访问minio web:http://ip:9001 ,创建用户和桶,示例如下: 参考:elasticsearch snapshot快照指定多个索引并行备份——筑梦之路_筑梦之路的博客-CSDN博客

    2024年02月09日
    浏览(38)
  • 【Spring Boot】事务的隔离级别与事务的传播特性详解:如何在 Spring 中使用事务?不同隔离级别的区别?

    事务这个词在学习 MySQL 和多线程并发编程的时候,想必大家或多或少接触过。 那么什么是事务呢? 事务是指一组操作作为一个不可分割的执行单元,要么全部成功执行,要么全部失败回滚。在数据库中,事务可以保证数据的一致性、完整性和稳定性,同时避免了数据的异常

    2024年02月13日
    浏览(43)
  • Maven 打包时,依赖配置正确,但是类引入出现错误,一般是快照(Snapshot)依赖拉取策略问题

    问题描述 : 项目打包时,类缺少依赖,操作 pom.xml - Maven - Reload project ,还是不生效,但是同事(别人)那里正常。 问题出现的环境 : 可能项目是多模块项目,结构例如: 可能继承另一个项目(项目是快照版本),例如: 可能依赖是快照版本,例如: 问题分析 : Maven 查

    2024年01月23日
    浏览(38)
  • Spring 事务的使用、隔离级别、@Transactional的使用

            Spring事务是Spring框架提供的一种机制,用于管理应用程序中的数据库事务。         事务是一组数据库操作的执行单元,要么全部成功提交,要么全部失败回滚,保证数据的一致性和完整性。 Spring事务提供了声明式事务和编程式事务两种方式: 编程式事务:

    2024年02月15日
    浏览(46)
  • 深入了解 Spring boot的事务管理机制:掌握 Spring 事务的几种传播行为、隔离级别和回滚机制,理解 AOP 在事务管理中的应用

    🎉🎉欢迎光临,终于等到你啦🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟持续更新的专栏 《Spring 狂野之旅:从入门到入魔》 🚀 本专栏带你从Spring入门到入魔   这是苏泽的个人主页可以看到我其他的内容哦👇👇 努力的苏泽 http://suzee.blog.csdn

    2024年03月21日
    浏览(83)
  • 事务和事务的隔离级别

    1.4.1.为什么需要事务 事务是数据库管理系统(DBMS)执行过程中的一个逻辑单位(不可再进行分割),由一个有限的数据库操作序列构成(多个DML语句,select语句不包含事务),要不全部成功,要不全部不成功。 A 给B 要划钱,A 的账户-1000元, B 的账户就要+1000元,这两个up

    2024年02月13日
    浏览(45)
  • 【MySQL】事务及其隔离性/隔离级别

    需要云服务器等云产品来学习Linux的同学可以移步/--腾讯云--/--阿里云--/--华为云--/官网,轻量型云服务器低至112元/年,新用户首次下单享超低折扣。   目录 一、事务的概念 1、事务的四种特性 2、事务的作用 3、存储引擎对事务的支持 4、事务的提交方式 二、事务的启动、回

    2024年02月12日
    浏览(49)
  • 数据库——事务,事务隔离级别

    什么是事务? 事务是逻辑上的一组操作,要么都执行,要么都不执行。 事务最经典也经常被拿出来说例子就是转账了。假如小明要给小红转账1000元,这个转账会涉及到两个关键操作就是:将小明的余额减少1000元,将小红的余额增加1000元。万一在这两个操作之间突然出现错误

    2024年02月11日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包