PostgreSQL长事务概念解析

我们在很多地方应该都听到过长事务的危害,比方说长事务会导致表膨胀之类的。那么在PostgreSQL中什么才算是长事务呢?

首先,在PostgreSQL的官方文档中并没有所谓“长事务”这一定义,似乎大家约定俗称的把一个执行了很长却没有提交的事务认为是“长事务”了,而在不同的数据库中关于长事务的定义往往也不尽相同,那么在PostgreSQL中什么是长事务呢?

打个比方,如下所示,我在一个会话中通过begin开启一个事务,然后执行了个简单的查询语句后迟迟不提交,这算不算长事务呢?

bill=# begin;
BEGIN
bill=*# select 1;
 ?column?
----------
        1
(1 row)

bill=*#

为了搞清楚这个问题,我们不妨想想,为什么我们会提到长事务呢。这是因为pg中的长事务会影响表中垃圾回收,会导致表的年龄增长无法freeze。而我们上面这个会话开启的事务会有影响吗?实际上并不会,我们可以通过pg_stat_activity视图观察:

bill=# select * from pg_stat_activity where pid = 26192;
-[ RECORD 1 ]----+------------------------------
datid            | 16385
datname          | bill
pid              | 26192
leader_pid       |
usesysid         | 16384
usename          | bill
application_name | psql
client_addr      |
client_hostname  |
client_port      | -1
backend_start    | 2022-03-02 11:49:49.433165+08
xact_start       | 2022-03-02 14:34:04.494416+08
query_start      | 2022-03-02 14:34:06.946754+08
state_change     | 2022-03-02 14:34:06.947207+08
wait_event_type  | Client
wait_event       | ClientRead
state            | idle in transaction
backend_xid      |
backend_xmin     |
query            | select 1;
backend_type     | client backend

之所以会导致表膨胀之类的问题,主要是在于backend_xid和backend_xmin两个字段,而上面的事务这两个字段均是空的。

/* ----------
 * LocalPgBackendStatus
 *
 * When we build the backend status array, we use LocalPgBackendStatus to be
 * able to add new values to the struct when needed without adding new fields
 * to the shared memory. It contains the backend status as a first member.
 * ----------
 */
typedef struct LocalPgBackendStatus
{
  /*
   * Local version of the backend status entry.
   */
  PgBackendStatus backendStatus;
  /*
   * The xid of the current transaction if available, InvalidTransactionId
   * if not.
   */
  TransactionId backend_xid;
  /*
   * The xmin of the current session if available, InvalidTransactionId if
   * not.
   */
  TransactionId backend_xmin;
} LocalPgBackendStatus;

backend_xid表示已申请事务号的事务,例如有增删改,DLL等操作的事务。backend_xid从申请事务号开始持续到事务结束。

backend_xmin表示SQL执行时的snapshot,即可见的最大已提交事务。

而表膨胀的原因是什么呢?当数据库中存在未结束的SQL语句或者未结束的持有事务ID的事务,在此事务过程中,或在此SQL执行时间范围内产生垃圾的话,这些垃圾无法回收,导致数据库膨胀。

也就是判断当前数据库中backend_xid和backend_xmin最小的值,凡是超过这个最小值的事务产生的垃圾都不能回收。

因此,我们如果想要监控长事务该怎么写呢?以超过1小时的长事务为例:

select count(*) from pg_stat_activity where state <> 'idle'
and (backend_xid is not null or backend_xmin is not null)
and now()-xact_start > interval '3600 sec'::interval;

所以,对于事务而言,只有当执行了一些DML或者DDL操作后才能算是我们通常说的长事务。否则只能算是我们常说的长连接,当然长连接也有很多弊端,例如占用内存、cpu等资源。

在实际应用中,我们应当做好对长事务的监控,并尽可能的避免其发生。例如一些批量的操作可能会比较容易导致长事务,我们可以尽量将其安排在业务低峰期执行,同时,如果我们的应用中关闭了自动提交,也要在执行完之后加上提交。

到此这篇关于PostgreSQL长事务概念解析的文章就介绍到这了,更多相关PostgreSQL长事务内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • PostgreSQL长事务与失效的索引查询浅析介绍

    最近刚写了一篇文章介绍了下长事务,以及一些长事务常见的危害,如无法及时的垃圾回收导致表膨胀之类的问题,最近刚好又碰到一个问题也是长事务所导致的. 上周六早上接到同事电话,说某个库CPU一直很高,看了下全是某张大表的全表扫描导致,但是奇怪的是相关的查询都有用到索引列,不知道为啥查询全部都没走索引. 当我连上去查看时发现确实如此,如果只是某个查询不走索引那可能是SQL本身写的有问题,但是这张表相关的所有SQL都不走索引,那自然会想到是索引本身的原因了.那是不是索引失效了呢?经过检查发现这张表上的索引

  • PostgreSQL游标与索引选择实例详细介绍

    之前有写过一个案例,order by limit因为数据分布不均而选择了错误的索引,这是由于优化器没法判断数据的分布关系,默认认为数据分布是均匀的所导致的. 而除了limit,当我们在使用游标时也要注意有可能会出现类似的情况.而往往这类在存储过程中的SQL我们更难发现其选择了错误的执行计划,所以需要注意. 1.建测试表 bill=# create table tbl (id int, c1 int, c2 int, c3 int, c4 int); CREATE TABLE 2.写入一批随机数据

  • PostgreSQL长事务概念解析

    我们在很多地方应该都听到过长事务的危害,比方说长事务会导致表膨胀之类的.那么在PostgreSQL中什么才算是长事务呢? 首先,在PostgreSQL的官方文档中并没有所谓“长事务”这一定义,似乎大家约定俗称的把一个执行了很长却没有提交的事务认为是“长事务”了,而在不同的数据库中关于长事务的定义往往也不尽相同,那么在PostgreSQL中什么是长事务呢? 打个比方,如下所示,我在一个会话中通过begin开启一个事务,然后执行了个简单的查询语句后迟迟不提交,这算不算长事务呢? bill=# beg

  • MySQL索引事务详细解析

    目录 一.索引 1.概念 2.作用 3.缺陷 4.使用场景 5.使用 1.查看索引 2.创建索引 3.删除索引 6.案例 二.事务 1.为什么使用事务 2.事务的概念 3.使用 4.特性 一.索引 1.概念 索引是一种特殊的文件,包含着对数据表里所有记录的引用指针,可以对表中的一列或者多列创建索引,并指定索引的类型,各类索引有各自的数据结构实现. (这里对于索引也只是简单了解,写了些皮毛) 更浅显易懂的来说:数据库的数据保存在硬盘,硬盘不知道具体保存在哪个位置,索引就是用来告诉硬盘数据在哪个位置

  • Java线程安全基础概念解析

    Java线程安全初步了解.JAVA线程安全从总体上来说,是指Java对象在多线程运行环境下的一种特性,表现为常规(区别于特殊调用情况)情况下每次调用都能得到正确的逻辑结果.从本质上来说,将对象的方法行为加上了同步控制逻辑,而调用者无须做其他额外的同步控制就可以安全放心的使用对象. 1.线程安全的定义 当多个线程访问一个对象时,如果不用考虑这些线程在运行时环境下的调度和交替执行,也不需要进行额外的同步,或者在调用方进行任何其他的协调操作,调用这个对象的行为都可以获得正确的结果,那这个对象就是线程安

  • PostgreSQL数据库事务实现方法分析

    本文实例讲述了PostgreSQL数据库事务实现方法.分享给大家供大家参考,具体如下: 事务简介 事务管理器:有限状态机 日志管理器 CLOG:事务的执行结果 XLOG:undo/redo日志 锁管理器:实现并发控制,读阶段采用MVCC,写阶段采用锁控制实现不同的隔离级别 事务是所有数据库系统的一个基本概念. 一次事务的要点就是它把多个步骤捆绑成了一个单一的,不成功则成仁的操作. 其它并发的事务是看不到在这些步骤之间的中间状态的,并且如果发生了一些问题, 导致该事务无法完成,那么所有这些步骤都完

  • java数据结构之树基本概念解析及代码示例

    Java中树的存储结构实现 一.树 树与线性表.栈.队列等线性结构不同,树是一...节点与节点之间的父子关系,可以为每个节点增加一个parent域,用以记录该节点的父点 树是一种抽象数据类型(ADT)或是实作这种抽象数据类型的数据结构,用来模拟具有树状结构性质的数据集合.它是由n(n>0)个有限节点组成一个具有层次关系的集合.把 它叫做"树"是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的. 树定义和基本术语 定义 树(Tree)是n(n≥0)个结点的有限集T,并且当

  • mybatis开启spring事务代码解析

    1.事务 Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的.最终都是调用数据库连接来完成事务的开启.提交和回滚. 2.模块 那么在对于spring事务而言,几个不可或缺的模块就是数据源.事务管理器以及事务编程 3.xml配置 <!--事务管理器--> <bean id="springTransactionManager" class="org.springframework.jdbc.datasourc

  • MySQL中的长事务示例详解

    前言: 『入门MySQL』系列文章已经完结,今后我的文章还是会以MySQL为主,主要记录下近期工作及学习遇到的场景或者自己的感悟想法,可能后续的文章不是那么连贯,但还是希望大家多多支持.言归正传,本篇文章主要介绍MySQL长事务相关内容,比如说我们开启的一个事务,一直没提交或回滚会怎样呢,出现事务等待情况应该如何处理,本篇文章将给你答案. 注意:本篇文章并不聚焦于谈论事务隔离级别以及相关特性.而是介绍长事务相关危害以及监控处理方法.本文是基于MySQL5.7.23版本,不可重复读(RR)隔离级别

  • MySQL 事务概念与用法深入详解

    本文实例讲述了MySQL 事务概念与用法.分享给大家供大家参考,具体如下: 事务的概念 MySQL事务是一个或者多个的数据库操作,要么全部执行成功,要么全部失败回滚. 事务是通过事务日志来实现的,事务日志包括:redo log和undo log. 事务的状态 活动的(active) 事务对应的数据库操作正在执行过程中时,我们就说该事务处在活动的状态. 部分提交的(partially committed) 当事务中的最后一个操作执行完成,但由于操作都在内存中执行,所造成的影响并没有刷新到磁盘时,我

  • 深入了解mysql长事务

    前言: 本篇文章主要介绍MySQL长事务相关内容,比如说我们开启的一个事务,一直没提交或回滚会怎样呢,出现事务等待情况应该如何处理,本篇文章将给你答案. 注意:本篇文章并不聚焦于谈论事务隔离级别以及相关特性.而是介绍长事务相关危害以及监控处理方法.本文是基于MySQL5.7.23版本,不可重复读(RR)隔离级别所做实验.(语句为\G可以使查询结构显示更易读,但只可以在mysql命令行使用.) 1.什么是长事务 首先我们先要知道什么是长事务,顾名思义就是运行时间比较长,长时间未提交的事务,也可以称

随机推荐