背景

sys_stat_activity视图中用两个字段表示:

backend_xid表示事务开始需要申请的事务id

backend_xmin表示一个事务快照,表示当前数据库中最小的正在运行的事务号,这个快照有可能是很久之前申请过的快照号,如果事务不结束,那么这个快照号一直保留,这符合MVCC特性,但是代价是表膨胀,vacuum不能及时回收。

我们可以通过这两个字段判断数据库中是否有长事务:

select * from sys_stat_activity where state<>'idle' and pg_backend_pid() != pid and (backend_xid is not null or backend_xmin is not null ) and extract(epoch from (now() - xact_start))  > 3; <时间阈值,单位秒> ;

下面我们看一下不同隔离级别下xmin的变化情况,借此理解MVCC。

实验

repeatable read隔离级别的事务,事务的第一条SQL会获取快照(xmin),快照持续到事务结束释放。

[](javascript:void(0)

session A:
获取当前会话PID,并开启一个repeatable read隔离级别的事务
test=# select sys_backend_pid();
sys_backend_pid
----------------
25481
(1 row)
test=# begin transaction isolation level repeatable read;
BEGIN session B:
查询会话A的xmin,xid
test=# select pid,backend_xid,backend_xmin from sys_stat_activity where pid=25481;
pid | backend_xid | backend_xmin
-------+-------------+--------------
25481 | |
(1 row) session A:
执行第一条SQL
test=# select 1;
?column?
----------
1
(1 row) session B:
115494为session A事务开启时数据库集群中未分配的最小事务号,或者未结束的最小事务号
test=# select pid,backend_xid,backend_xmin from sys_stat_activity where pid=25481;
pid | backend_xid | backend_xmin
-------+-------------+--------------
25481 | | 115494
(1 row)
在session B消耗2个事务(使用两种方法,各消耗1个事务ID)
test=# select txid_current();
txid_current
--------------
115494
(1 row)
test=# insert into tbl1 values (1);
INSERT 0 1 session A:
执行第二条SQL
test=# select 2;
?column?
----------
2
(1 row) session B:
对于repeatable read隔离级别的事务来说,xmin不会变化。
test=# select pid,backend_xid,backend_xmin from sys_stat_activity where pid=25481;
pid | backend_xid | backend_xmin
-------+-------------+--------------
25481 | | 115494
(1 row) session A:
执行一条会申请XID的SQL,例如插入数据。
test=# insert into tbl1 values (1);
INSERT 0 1 session B:
xid有值了,为session A对应事务申请下来的事务号,是已消耗掉的,XID不会变化。
test=# select pid,backend_xid,backend_xmin from sys_stat_activity where pid=25481;
pid | backend_xid | backend_xmin
-------+-------------+--------------
25481 | 115495| 115494
(1 row)

[](javascript:void(0)

read committed隔离级别的事务,事务的每一条SQL都会获取快照,SQL执行结束就会释放快照。

[](javascript:void(0)

session A:
获取当前会话PID,并开启一个read committed隔离级别的事务
test=# select sys_backend_pid();
sys_backend_pid
----------------
57479
(1 row)
test=# begin transaction isolation level read committed;
BEGIN session B:
查询会话A的xmin,xid
test=# select pid,backend_xid,backend_xmin from sys_stat_activity where pid=57479;
pid | backend_xid | backend_xmin
-------+-------------+--------------
57479 | |
(1 row) session A:
执行第一条SQL
test=# select 1;
?column?
----------
1
(1 row) session B:
并没有观察到xmin,因为select 1;开始时获取,SQL执行结束,xmin马上就释放了
test=# select pid,backend_xid,backend_xmin from sys_stat_activity where pid=57479;
pid | backend_xid | backend_xmin
-------+-------------+--------------
57479 | |
(1 row) session A:
执行第一条long SQL
test=# select sys_sleep(20); session B:
sys_sleep执行结束前查看,可以观察到xmin,SQL执行结束再查看xmin就会消失。
test=# select pid,backend_xid,backend_xmin from sys_stat_activity where pid=57479;
pid | backend_xid | backend_xmin
-------+-------------+--------------
57479 | | 78339
(1 row) session B:
在session B消耗2个事务(使用两种方法,各消耗1个事务ID)
test=# select txid_current();
txid_current
--------------
78339
(1 row)
test=# insert into tbl1 values (1);
INSERT 0 1 session A:
执行第2条long SQL
test=# select sys_sleep(20); session B:
sys_sleep执行结束前查看,可以观察到xmin,SQL执行结束再查看xmin就会消失。
xmin与第一条SQL看到的78339不一样,因为read committed隔离级别的事务,每条SQL开始时都会新申请快照。注意这里和repeatable read隔离级别不一样,它对应的xmin不会变化。
test=# select pid,backend_xid,backend_xmin from sys_stat_activity where pid=57479;
pid | backend_xid | backend_xmin
-------+-------------+--------------
57479 | | 78341
(1 row) session A:
执行一条会申请XID的SQL,例如插入数据。
test=# insert into tbl1 values (1);
INSERT 0 1 session B:
xid有值了,为session A对应事务申请下来的事务号,是已消耗掉的,XID不会变化,直到事务结束(session A commit后,backend_xid:78341变为空)。而backend_xmin为空表示已经没有未结束的最老的快照版本。这是好的现象,这不会引起表膨胀后vacuum进程回收失败。
test=# select pid,backend_xid,backend_xmin from sys_stat_activity where pid=57479;
pid | backend_xid | backend_xmin
-------+-------------+--------------
57479 | 78341 |
(1 row)

[](javascript:void(0)

总结

以上实验帮助大家理解不同隔离级别下,根据pid查出backend_xid,backend_xmin对应的区别变化,更好理解这两个字段的涵义。当这两个字段任何一个有值时都表示有未结束的事务,这也对应起来开头提到的查询长事务的语句中的where条件:backend_xid is not null or backend_xmin is not null。

当然我们最常用的隔离级别是read committed,这是我们KES数据库的默认隔离级别,也是oracle的默认隔离级别。只有一些特殊的业务场景需要用到repeatable read隔离级别。

KingbaseESV8R6不同隔离级下xmin的区别的更多相关文章

  1. python 里面的单下划线与双下划线的区别

    python 里面的单下划线与双下划线的区别 Python 用下划线作为变量前缀和后缀指定特殊变量. _xxx 不能用'from moduleimport *'导入 __xxx__ 系统定义名字 __ ...

  2. 测试Python类成员的单下划线,双下划线,两头下划线的区别

    首先原谅一个菜鸟叫他“两头下划线”.记得在windows编程中,很多宏定义使用下划线+大写,给人逼格很高的错觉.对于Python下划线的认识,大概是从__dict__这个属性开始的,看__dict__ ...

  3. php windows与linux下的路径区别

    php windows与linux下的路径区别windows用的是"\",linux用的是"/"这一点要特别清楚,, ps:在PHP windows也可以用/表 ...

  4. 114、drawable和mipmap 目录下图片的区别

    android 在 API level 17 加入了 mipmap 技术,对 bitmap 图片的渲染支持 mipmap 技术,来提高渲染的速度和质量.mipmap 是一种很早就有的技术了,翻译过来就 ...

  5. C++和C在linux下 和在windows下有什么区别?

    一.函数库的区别 linux下的C函数库和windows下的函数库系统调用的机制不一样,Glibc包含了主要的C库.这个库提供了基本例程,用于分配内存.搜索目录.打开关闭文件.读写文件.字串处理.模式 ...

  6. Python 私有变量中两个下划线 _ _item 与 一个下划线的区别 _item

    python中没有常量的说法, 但是可以通过元组实现一个常量 在python的私有变量中, 存在两个下划线 _ _item 与一个下划线 _item 的区别 前面带两个下划线的私有变量: 只能在本类中 ...

  7. 【HTML&CSS】 第二章:标准模式下的页面与怪异模式下的页面区别

    盒模型 前面提到,盒模型(box mode)是浏览器 Quirks Mode 和 Standards Mode 的主要区别. 描述 对于“盒模型”一词并没有明确的文档定义,它是开发人员描述 CSS 中 ...

  8. linux下 open fopen区别

    open是linux下的底层系统调用函数,fopen与freopen c/c++下的标准I/O库函数,带输入/输出缓冲.linxu下的fopen是open的封装函数,fopen最终还是要调用底层的系统 ...

  9. linux中bin和xbin下可执行程序的区别

    /bin下的都是Linux最基础的,所有用户都可以使用的外部命令 /sbin下的都是只有超级用户root才能使用的.管理Linux系统的外部命令 /usr/bin以及/usr/local/bin下的都 ...

随机推荐

  1. 重学ES系列之模版字符串

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. 利用MySQL中的乐观锁和悲观锁实现分布式锁

    背景 对于一些并发量不是很高的场景,使用MySQL的乐观锁实现会比较精简且巧妙. 下面就一个小例子,针对不加锁.乐观锁以及悲观锁这三种方式来实现. 主要是一个用户表,它有一个年龄的字段,然后并发地对其 ...

  3. Day04 HTML标记

    路径 ./ 同级目录 ./ 进入该目录名下 ../ 上一级目录 HTML标记 图片 <!-- 图片标记 src 图片的路径 width 设置图片宽度 height 设置图片高度 title 鼠标 ...

  4. P2599 [ZJOI2009]取石子游戏 做题感想

    题目链接 前言 发现自己三岁时的题目都不会做. 我发现我真的是菜得真实. 正文 神仙构造,分讨题. 不敢说有构造,但是分讨我只服这道题. 看上去像是一个类似 \(Nim\) 游戏的变种,经过不断猜测结 ...

  5. Eclipse拷贝动态的web工程

    1.选中需要拷贝的工程,CTRL+C,然后CTRL+V 2.在web动态工程中,还需要选中新拷贝工程,右键选中properties,然后搜索web,--->Web Project Setttin ...

  6. JDBC:处理事务

    1.如何实现事务 如果现在希望对 A 表和 B 表同时删除某一个 id 号的记录,使这两个sql操作组成一个事务.(成功则同时成功,否则都失败) 注意:如果 B 表 建立了引用 A 表的id外键,并指 ...

  7. 简单状压dp的思考 - 最大独立集问题和最大团问题 - 贰

    接着上文 题目链接:最大独立集问题 上次说到,一种用状压DP解决任意无向图最大团问题(MCP)的方程是: 注:此处popcountmax代表按照二进制位下1的个数作为关键字比较,即选择二进制位下1的个 ...

  8. 如何编写测试团队通用的Jmeter脚本

    平时学习.工作过程中,编写的一些jmeter脚本,相信大多数都遇到过这个问题.那就是:如果换一台电脑运行,文件路径不一样,会导致运行失败. 前不久,自己就真真切切遇到过一回,A同学写了个脚本用于压测, ...

  9. MySQL基本操作笔记

    一.数值类型 1.常量(1)字符串常量 ASCII字符串常量占一个字节 例如:'Hello Word' Unicode字符串常量占两个字节 例如:N'Hello Word' mysql> sel ...

  10. UE4.25 Slate源码解读

    概述 Slate系统是UE的一套UI解决方案,UMG系统也是依赖Slate系统实现的. 问题: Slate系统是如何组织的? 控件树的父子关系是如何绑定的? Slate系统是如何渲染的? slate渲 ...