一、问题描述

用户在实际中可能会碰到类似以下 dead rows 无法 vacuum的问题,一个可能的原因是由于游标未结束的原因。

test=# vacuum(verbose) t1;
INFO: vacuuming "public.t1"
INFO: "t1": found 0 removable, 985 nonremovable row versions in 66 out of 67 pages
DETAIL: 788 dead row versions cannot be removed yet, oldest xmin: 4996
There were 0 unused item identifiers.
Skipped 1 page due to buffer pins, 0 frozen pages.
0 pages are entirely empty.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
INFO: vacuuming "pg_toast.pg_toast_29558"
INFO: index "pg_toast_29558_index" now contains 0 row versions in 1 pages
DETAIL: 0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
INFO: "pg_toast_29558": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 4996
There were 0 unused item identifiers.
Skipped 0 pages due to buffer pins, 0 frozen pages.
0 pages are entirely empty.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.

二、举例说明

1、事务不提交的情况

创建测试数据:

create table t1(id integer,name text);
create table t2(id integer);
insert insert t1 select generate_series(1,1000),repeat('a',500);

创建测试过程:

create or replace procedure proc01_nocommit as
cursor c01 is select id from t1;
v_id integer;
begin
open c01;
fetch c01 into v_id;
while (c01%FOUND) loop
insert into t2 values(v_id);
perform pg_sleep(1);
fetch c01 into v_id;
end loop;
end;
/

session 1:

call proc01_nocommit();

session 2:

test=# select * from pg_locks where relation='t1'::regclass;
locktype | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction | pid | mode | granted | fastpath
----------+----------+----------+------+-------+------------+---------------+---------+-------+----------+--------------------+--------+-----------------+---------+----------
relation | 29504 | 29558 | | | | | | | | 4/2737 | 360612 | AccessShareLock | t | t
(1 row) test=# delete from t1 where mod(id,5)<>1;
DELETE 200

  

无法 vacuum

test=# vacuum(verbose) t1;
INFO: vacuuming "public.t1"
INFO: "t1": found 0 removable, 985 nonremovable row versions in 66 out of 67 pages
DETAIL: 788 dead row versions cannot be removed yet, oldest xmin: 4996
There were 0 unused item identifiers.
Skipped 1 page due to buffer pins, 0 frozen pages.
0 pages are entirely empty.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
INFO: vacuuming "pg_toast.pg_toast_29558"
INFO: index "pg_toast_29558_index" now contains 0 row versions in 1 pages
DETAIL: 0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
INFO: "pg_toast_29558": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 4996
There were 0 unused item identifiers.
Skipped 0 pages due to buffer pins, 0 frozen pages.
0 pages are entirely empty.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
VACUUM

  

结论:可以看到对象有 AccessShareLock 锁(实际验证,不管只要 cursor 定义了,不管是否open ,都会有 AccessShareLock 锁)。

2、事务提交的情景

修改过程块如下:

create or replace procedure proc01_commit as
cursor c01 is select id from t1;
v_id integer;
begin
open c01;
fetch c01 into v_id;
while (c01%FOUND) loop
insert into t2 values(v_id);
perform pg_sleep(1);
fetch c01 into v_id;
commit;
end loop;
end;
/

可以看到在游标内部加了commit;

PS:KingbaseES 支持游标跨事务的场景。在 commit时,会将剩余未完成游标的结果取回到临时文件,这样可以保证MVCC 机制。

Session 1:

call proc01_commit()

Session 2:

test=# select * from pg_locks where relation='t1'::regclass;
locktype | database | relation | page | tuple | virtualxid | transactionid | classid | objid | objsubid | virtualtransaction | pid | mode | granted | fastpath
----------+----------+----------+------+-------+------------+---------------+---------+-------+----------+--------------------+--------+-----------------+---------+----------
(0 row) test=# delete from t1 where mod(id,5)<>0;
DELETE 800

  

结论:没有锁,可以vacuum。

test=# vacuum (verbose) t1;
INFO: vacuuming "public.t1"
INFO: "t1": removed 800 row versions in 67 pages
INFO: "t1": found 800 removable, 200 nonremovable row versions in 67 out of 67 pages
DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 4857
There were 0 unused item identifiers.
Skipped 0 pages due to buffer pins, 0 frozen pages.
0 pages are entirely empty.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
INFO: vacuuming "pg_toast.pg_toast_29549"
INFO: index "pg_toast_29549_index" now contains 0 row versions in 1 pages
DETAIL: 0 index row versions were removed.
0 index pages have been deleted, 0 are currently reusable.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
INFO: "pg_toast_29549": found 0 removable, 0 nonremovable row versions in 0 out of 0 pages
DETAIL: 0 dead row versions cannot be removed yet, oldest xmin: 4857
There were 0 unused item identifiers.
Skipped 0 pages due to buffer pins, 0 frozen pages.
0 pages are entirely empty.
CPU: user: 0.00 s, system: 0.00 s, elapsed: 0.00 s.
VACUUM

游标长时间open导致表无法vacuum问题的更多相关文章

  1. 防止shell脚本长时间执行导致ssh超时

    在一些对安全性要求较高的场景下.ssh的超时时间是管理员预先设置好的,在闲置一段时间后ssh连接会自己主动断开. 这样的情况下假设通过ssh运行脚本,而脚本运行时间又比較长的话.会导致sshclien ...

  2. JVM 调优 —— GC 长时间停顿问题及解决方法

    零. 简介 垃圾收集器长时间停顿,表现在 Web 页面上可能是页面响应码 500 之类的服务器错误问题,如果是个支付过程可能会导致支付失败,将造成公司的直接经济损失,程序员要尽量避免或者说减少此类情况 ...

  3. SQL一次查出相关类容避免长时间占用表(下)

    /* server: db: EDI */ -- 以下案例多次查询同一张表,仅有Name条件不同 --可以使用一次查出相关类容避免长时间占用表 USE EDI GO DECLARE @FileType ...

  4. SQL一次查出相关类容避免长时间占用表(上)

    /* server: db: EDI */ -- 以下案例多次查询同一张表,仅有组合条件Name+Direction不同 --可以使用一次查出相关类容避免长时间占用表 USE EDI GO DECLA ...

  5. kali长时间未使用导致数字签名过期无法更新源解决办法

    kali长时间未使用,数字签名会过期,从而导致无法更新源. apt-get update:从源(Source)服务器那里下载最新的软件包列: apt-get upgrade:对已经安装的软件包本身进行 ...

  6. 查看Oracle中存储过程长时间被卡住的原因

    1:查V$DB_OBJECT_CACHE SELECT * FROM V$DB_OBJECT_CACHE WHERE name='CUX_OE_ORDER_RPT_PKG' AND LOCKS!='0 ...

  7. ASP.NET 工作流:支持长时间运行操作的 Web 应用程序

    ASP.NET 工作流 支持长时间运行操作的 Web 应用程序 Michael Kennedy   代码下载位置:MSDN 代码库 在线浏览代码 本文将介绍以下内容: 独立于进程的工作流 同步和异步活 ...

  8. ios之申请后台延时执行和做一个假后台的方法(系统进入长时间后台后,再进入前台部分功能不能实现)

    转自:http://sis hu ok.com/forum/blogCategory/showByCategory.html?categories_id=138&user_id=10385   ...

  9. 为什么drop table的时候要在checking permissions花很长时间?

    昨天,我drop一个表的时候在checking permissions花了20s+,这个时间花在哪里了呢?经常查找发现我的配置文件innodb_file_per_table=1的,innodb需要遍历 ...

随机推荐

  1. 数字图像处理-基于matlab-直方图均匀化,傅立叶变换,图像平滑,图像锐化

    直方图均匀化 任务:用MATLAB或VC或Delphi等实现图像直方图均匀化的算法. clc;clear;close all; % 清除工作台 % path(path,'..\pics'); % 设置 ...

  2. Vue.js与ElementUI搭建无限级联层级表格组件

    前言 今天,回老家了.第一件事就是回家把大屏安排上,写作的感觉太爽了,终于可以专心地写文章了.我们今天要做的项目是怎么样搭建一个无限级联层级表格组件,好了,多了不多说,赶快行动起来吧!项目一览 到底是 ...

  3. 【python基础】第03回 软件安装

    上节内容回顾 1.计算机五大组成部分详解 1.控制器 控制计算机各个硬件的工作 2.运算器 数学运算.逻辑运算(核心) """CPU = 控制器 + 运算器"& ...

  4. map集合中对应key的value为null处理办法

    问题: Map集合中对应key的value为null,但是现在需要将这个value转为Integer类型,这个value如果不是null,那么get到的是long类型或者是Bigdecimal类型 处 ...

  5. 强化学习-学习笔记7 | Sarsa算法原理与推导

    Sarsa算法 是 TD算法的一种,之前没有严谨推导过 TD 算法,这一篇就来从数学的角度推导一下 Sarsa 算法.注意,这部分属于 TD算法的延申. 7. Sarsa算法 7.1 推导 TD ta ...

  6. CSS进阶内容—盒子和阴影详解

    CSS进阶内容 在学习了CSS基本知识之后,我们需要进一步了解CSS,因此写下了这篇文章 当然如果没有学习之前的知识,可以到我的主页中查看之前的文章:秋落雨微凉 - 博客园 CSS三大特性 首先我们先 ...

  7. 掌握CSS中的z-index

    前言 z-index是一个用于控制文档中图层顺序的属性.具有较高z-index值的元素将会出现在具有较低值的元素之上.就像页面上的x轴和y轴决定一个元素在水平和垂直方向上的位置一样,z-index控制 ...

  8. 30行自己写并发工具类(Semaphore, CyclicBarrier, CountDownLatch)是什么体验?

    30行自己写并发工具类(Semaphore, CyclicBarrier, CountDownLatch)是什么体验? 前言 在本篇文章当中首先给大家介绍三个工具Semaphore, CyclicBa ...

  9. selenium环境配置和八大元素定位

    一.环境配置 1.selenium下载安装 安装一:pip install selenium(多数会超时安装失败) 安装二:pip install -i https://pypi.tuna.tsing ...

  10. JUC源码学习笔记3——AQS等待队列和CyclicBarrier,BlockingQueue

    一丶Condition 1.概述 任何一个java对象都拥有一组定义在Object中的监视器方法--wait(),wait(long timeout),notify(),和notifyAll()方法, ...