PostgreSQL 如何判断idle in transaction的事务中有没有东西要提交

本文涉及的产品
RDS SQL Server Serverless,2-4RCU 50GB 3个月
推荐场景:
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
简介:

标签

PostgreSQL , idle in transaction , 事务快照 , 修改 , xid


背景

如何判断idle in transaction的事务中有没有东西要提交?

比如在一些情况下,你可能发现数据库中很多idle in transaction的事务,可能是一些僵尸事务,也可能是一些应用框架引起的,连接建立后就开启一个事务,实际上里面啥也没有。

postgres=# select pid, state from pg_stat_activity ;  
  pid  |        state          
-------+---------------------  
 33231 |   
 33233 |   
 50650 | active  
 50723 | active  
 50801 | active  
 54168 | idle in transaction  
 51197 | idle  
 51983 | active  
 33229 |   
 33228 |   
 33230 |   
(11 rows)  

那么如果你需要清理掉一些事务时,如何让他优雅的退出,或者如何快速的清退那些没有什么影响的事务呢?

那就需要判断idle in transaction的事务中有没有东西要提交?

通过pg_stat_activity会话判断

pg_stat_activity会话中有两个字段,backend_xid,backend_xmin用来表示会话是否申请了事务号,以及会话的快照ID。

                if (TransactionIdIsValid(local_beentry->backend_xid))  
                        values[15] = TransactionIdGetDatum(local_beentry->backend_xid);  
                else  
                        nulls[15] = true;  
  
                if (TransactionIdIsValid(local_beentry->backend_xmin))  
                        values[16] = TransactionIdGetDatum(local_beentry->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;  

例子1:

1、开启一个read committed事务

postgres=# begin;  
BEGIN  
postgres=# select 1;  
 ?column?   
----------  
        1  
(1 row)  
postgres=# select pg_backend_pid();  
 pg_backend_pid   
----------------  
           3497  
(1 row)  

2、查询它的事务状态

postgres=# select * from pg_stat_activity where pid=3497;  
-[ RECORD 1 ]----+------------------------------  
datid            | 16461  
datname          | postgres  
pid              | 3497  
usesysid         | 10  
usename          | postgres  
application_name | psql  
client_addr      |   
client_hostname  |   
client_port      | -1  
backend_start    | 2018-02-07 13:09:44.506794+08  
xact_start       | 2018-02-07 13:12:48.322815+08  
query_start      | 2018-02-07 13:13:03.454437+08  
state_change     | 2018-02-07 13:13:03.454926+08  
wait_event_type  | Client  
wait_event       | ClientRead  
state            | idle in transaction  
backend_xid      |   
backend_xmin     |   
query            | select pg_backend_pid();  
backend_type     | client backend  

可以看到这个会话的backend_xid和backend_xmin都没有值,因为它没有对数据库有任何写操作所以不需要申请事务号,因此backend_xid为空。

并且它当前没有SQL在执行,并且它是read committed的事务隔离级别,因此目前没有事务快照信息,backend_xmin为空。

如果后面有QUERY正在执行中,那么backend_xmin会有一个值,即这条QUERY启动时的事务快照ID。

例子2:

1、开启一个repeatable read事务

postgres=# begin isolation level repeatable read ;  
BEGIN  
postgres=# select 1;  
 ?column?   
----------  
        1  
(1 row)  

2、查询它的事务状态

postgres=# select * from pg_stat_activity where pid=3497;  
-[ RECORD 1 ]----+------------------------------  
datid            | 16461  
datname          | postgres  
pid              | 3497  
usesysid         | 10  
usename          | postgres  
application_name | psql  
client_addr      |   
client_hostname  |   
client_port      | -1  
backend_start    | 2018-02-07 13:09:44.506794+08  
xact_start       | 2018-02-07 13:16:30.995233+08  
query_start      | 2018-02-07 13:16:40.65339+08  
state_change     | 2018-02-07 13:16:40.653504+08  
wait_event_type  | Client  
wait_event       | ClientRead  
state            | idle in transaction  
backend_xid      |   
backend_xmin     | 152207375  
query            | select 1;  
backend_type     | client backend  

可以看到这个会话的backend_xid没有值,因为它没有对数据库有任何写操作所以不需要申请事务号,因此backend_xid为空。

它是repeatable read的事务隔离级别,因此在它执行了第一条SQL后,就会获得一个事务快照,并且跟随它到事务结束,因此backend_xmin不为空,并且对于rr以上隔离级别的事务,在整个事务过程中backend_xmin是一个不变的值。

例子3:

1、前面提到的任意一个事务,执行一个INSERT。

postgres=# insert into a values (2);  
INSERT 0 1  

2、查询它的事务状态

postgres=# select * from pg_stat_activity where pid=3497;  
-[ RECORD 1 ]----+------------------------------  
datid            | 16461  
datname          | postgres  
pid              | 3497  
usesysid         | 10  
usename          | postgres  
application_name | psql  
client_addr      |   
client_hostname  |   
client_port      | -1  
backend_start    | 2018-02-07 13:09:44.506794+08  
xact_start       | 2018-02-07 13:16:30.995233+08  
query_start      | 2018-02-07 13:18:07.129475+08  
state_change     | 2018-02-07 13:18:07.13004+08  
wait_event_type  | Client  
wait_event       | ClientRead  
state            | idle in transaction  
backend_xid      | 152207375  
backend_xmin     | 152207375  
query            | insert into a values (2);  
backend_type     | client backend  

可以看到这个会话的backend_xid和backend_xmin都有值了,因为写入操作要申请事务号,因此backend_xid不为空。

它是repeatable read的事务隔离级别,因此在它执行了第一条SQL后,就会获得一个事务快照,并且跟随它到事务结束,因此backend_xmin也不为空。

小结

如何判断idle in transaction的事务中有没有东西要提交?

pg_stat_activity.backend_xid不为空的,即说明这个事务有东西要提交。

相关实践学习
使用PolarDB和ECS搭建门户网站
本场景主要介绍基于PolarDB和ECS实现搭建门户网站。
阿里云数据库产品家族及特性
阿里云智能数据库产品团队一直致力于不断健全产品体系,提升产品性能,打磨产品功能,从而帮助客户实现更加极致的弹性能力、具备更强的扩展能力、并利用云设施进一步降低企业成本。以云原生+分布式为核心技术抓手,打造以自研的在线事务型(OLTP)数据库Polar DB和在线分析型(OLAP)数据库Analytic DB为代表的新一代企业级云原生数据库产品体系, 结合NoSQL数据库、数据库生态工具、云原生智能化数据库管控平台,为阿里巴巴经济体以及各个行业的企业客户和开发者提供从公共云到混合云再到私有云的完整解决方案,提供基于云基础设施进行数据从处理、到存储、再到计算与分析的一体化解决方案。本节课带你了解阿里云数据库产品家族及特性。
目录
相关文章
|
SQL 缓存 运维
PostgreSQL 事务号回卷分析
## XID 定义 xid 是个啥东西?xid 就是 PostgreSQL 里面的事务号,每个事物都会分配一个 xid。PostgreSQL 数据中每个元组头部都会保存着 插入 或者 删除 这条元组的事务号,即 xid,然后内核通过这个 xid 进行元组的可见性判断。简单理解,比如有两个事务,xid1=200,xid2=201,那么 xid1 中只能看到 t_xmin 200 的元组。 ```c
|
7月前
|
存储 SQL Oracle
02-PostgreSQL 存储过程的进阶介绍(含游标、错误处理、自定义函数、事务)
02-PostgreSQL 存储过程的进阶介绍(含游标、错误处理、自定义函数、事务)
|
Oracle 关系型数据库 数据库
PostgreSQL技术大讲堂 - 第20讲:事务概述与隔离级别
PostgreSQL从小白到专家,技术大讲堂 - 第20讲:事务概述与隔离级别
269 2
|
关系型数据库 PostgreSQL
PostgreSQL事务提交日志与CLOG操作初步认识
PostgreSQL事务提交日志与CLOG操作初步认识
265 0
|
SQL 存储 Oracle
PostgreSQL 事务隔离级别的实现和多版本并发控制|学习笔记
快速学习 PostgreSQL 事务隔离级别的实现和多版本并发控制
PostgreSQL 事务隔离级别的实现和多版本并发控制|学习笔记
|
SQL 关系型数据库 数据库
PostgreSQL TRANSACTION(事务)
TRANSACTION(事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。 数据库事务通常包含了一个序列的对数据库的读/写操作。包含有以下两个目的: 为数据库操作序列提供了一个从失败中恢复到正常状态的方法,同时提供了数据库即使在异常状态下仍能保持一致性的方法。 当多个应用程序在并发访问数据库时,可以在这些应用程序之间提供一个隔离方法,以防止彼此的操作互相干扰。 当事务被提交给了数据库管理系统(DBMS),则 DBMS 需要确保该事务中的所有操作都成功完成且其结果被永久保存在数据库中,如果事务中有的操作没有成功完成,则事务中的所有操作都需要回滚,回到事务执行前的
209 0
|
存储 SQL 关系型数据库
【学习资料】第16期快速入门PostgreSQL应用开发与管理 - 6 事务和锁
大家好,这里是快速入门PostgreSQL应用开发与管理 - 6 事务和锁
|
SQL Oracle 关系型数据库
Oracle/Mysql迁移到Postgresql事务回滚行为差异(开发避坑系列)
Mysql或Oracle迁移到Postgresql系产品后,经常会发生事务回滚导致的问题,具体问题一般都是类似于: **为什么我没rollback,我的事务就自己回滚了?** 下面我举一个简单的例子,说明下PG和其他两款DB在事务回滚行为上的差异 ## Oracle事务内报错后的行为 (完整代码贴在文章最后) ```java Class.fo
1050 0
|
SQL 关系型数据库 PostgreSQL
AnalyticDB for PostgreSQL 6.0新特性解析 - OLTP 高并发事务能力优化
本文介绍 ADB PG6.0版本里,面向 OLTP 的高并发执行优化
4267 0

相关产品

  • 云原生数据库 PolarDB
  • 云数据库 RDS PostgreSQL 版