首页 > 其他分享 >Kingbase ES 游标跨事务及其案例一则

Kingbase ES 游标跨事务及其案例一则

时间:2023-09-18 14:34:47浏览次数:33  
标签:07 192.1 56 游标 Kingbase sys 153.142 49637 ES

前言

本文介绍游标在PLSQL和SQL层跨事务使用案例,及其案例一则。

本文验证版本:

db0=# select version();
db0-# /
            version

----------------------------------------

 KingbaseES V008R006C007B0024 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 4.8.5 20150623 (Red Hat 4.8.5-28), 64-bit
(1 row)

一,PLSQL块中的游标跨事务

原生plpgsql跨事务例子,不支持跨事务

drop table t2;

create table t2(id int,name varchar(20));
insert into t2 values (1,'aaa'), (2,'bbb'), (3,'ccc');
create or replace procedure testcur02
as
$$
declare
    cur1 refcursor;
    vid numeric;
    vname varchar(20);
begin
    open cur1 for select * from t2;
    commit;
    fetch cur1 into vid,vname;   --因为cur1在commit后被自动释放,所以将报错不存在
    raise notice 'vid:%,vname:%',vid,vname;
    close cur1;
end;
$$ language plpgsql;

call testcur02();


--运行结果
db0=# call testcur02();
db0-#
db0-# /
error:  cursor "<unnamed portal 8>" does not exist
context:  pl/pgsql function testcur02() line 9 at fetch

kes-plsql默认支持存储过程中跨事务

drop table t2;

create table t2(id int,name varchar(20));
insert into t2 values (1,'aaa'), (2,'bbb'), (3,'ccc');
create or replace procedure testcur01
is
declare
    cur1 refcursor;
    vid numeric;
    vname varchar(20);
begin
    open cur1 for select * from t2;
    commit;
    fetch cur1 into vid,vname;   --cur1在commit后不会被自动释放
    raise notice 'vid:%,vname:%',vid,vname;
    close cur1;
end;

call testcur01();

--运行结果
db0=# call testcur01();
db0-# /
notice:  vid:1,vname:aaa
call
db0=#

二,SQL层的游标和事务

SQL层也有游标语句,也可声明游标,为了验证跨事务问题,以fetch all in语句为例。

create or replace procedure testcur04( pcur1 out refcursor)
is
begin
    open pcur1 for select * from t2;
end;


db0=# begin;   ---开启事务
db0-# /
BEGIN
db0=# call testcur04('vcur');   ----获取游标结果集
db0-# /

 pcur1
-------

 vcur
(1 row)

db0=# fetch all in vcur;    ---一次性提取游标结果集
db0-# /
 id | name
----+------
  1 | aaa
  2 | bbb
  3 | ccc
(3 rows)

db0=#

在早前的V7版本,可以通过开启 enable_out_refcursor_holdable 参数为on,
实现在SQL层跨事务执行上述游标结果集(要求存储过程的参数模式为out 或inout),目前实测来看V008R006C007B0024已不支持该参数。

三,游标跨事务案例一则

这是一个V7版本上产生的问题,

问题描述客户应用层代码使用fetch al in获取游标结果集,但是报错游标不存在。完整的截取客户代码如下;

[2023-07-07 09:56:20.605 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: SELECT nspname, proname, proretset, prorettypedef, pronargs, proargtypes, protype, proargnames, proargmodes, proargtypmods FROM sys_catalog.sys_namespace JOIN sys_catalog.sys_proc on sys_proc.pronamespace = sys_namespace.oid AND (not proretset) AND nspname NOT LIKE 'SYS_%' ESCAPE '' AND nspname != 'INFORMATION_SCHEMA' LEFT JOIN sys_catalog.sys_package ON sys_proc.propkgoid = sys_package.oid AND sys_package.pkgnamespace = sys_namespace.oid WHERE 1 AND proname LIKE 'PROC_KBV7_OCI_0X1794F90' ESCAPE '' ORDER BY nspname, proname, proretset

---第一段黑体字

[2023-07-07 09:56:20.607 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: SET ENABLE_OUT_REFCURSOR_HOLDABLE TO on
[2023-07-07 09:56:20.608 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: call PROC_KBV7_OCI_0x1794f90('KDBCUR_178A2F0_0')
[2023-07-07 09:56:20.609 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: fetch all in KDBCUR_178A2F0_0
[2023-07-07 09:56:20.609 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: drop procedure if exists PROC_KBV7_OCI_0x1794f90(REFCURSOR)
[2023-07-07 09:56:20.611 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: close KDBCUR_178A2F0_0

[2023-07-07 09:56:20.613 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: parse _PLAN0X178D4B0: select object_name from user_objects where object_name = 'TRIGGER_PKG' and (object_type = 'PACKAGE' or object_type = 'PACKAGE BODY') and status<>'VALID'
[2023-07-07 09:56:20.616 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: EXECUTE _PLAN0x178d4b0()
[2023-07-07 09:56:20.616 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]DETAIL: prepare: select object_name from user_objects where object_name = 'TRIGGER_PKG' and (object_type = 'PACKAGE' or object_type = 'PACKAGE BODY') and status<>'VALID'
[2023-07-07 09:56:20.623 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: close _PLAN0X178D4B0
[2023-07-07 09:56:20.624 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: SELECT PRONAME, PROTYPE FROM SYS_PROC, SYS_PACKAGE WHERE SYS_PROC.PROPKGOID = SYS_PACKAGE.OID AND PKGNAME = UPPER('TRIGGER_PKG');
[2023-07-07 09:56:20.626 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: SELECT nspname, proname, proretset, prorettypedef, pronargs, proargtypes, protype, proargnames, proargmodes, proargtypmods FROM sys_catalog.sys_namespace JOIN sys_catalog.sys_proc on sys_proc.pronamespace = sys_namespace.oid AND (not proretset) AND nspname NOT LIKE 'SYS_%' ESCAPE '' AND nspname != 'INFORMATION_SCHEMA' LEFT JOIN sys_catalog.sys_package ON sys_proc.propkgoid = sys_package.oid AND sys_package.pkgnamespace = sys_namespace.oid WHERE 1 AND pkgname LIKE UPPER('TRIGGER_PKG') ESCAPE '' AND proname LIKE UPPER('SELECT_TRIGGER_ACTIONS') ESCAPE '' ORDER BY nspname, proname, proretset
[2023-07-07 09:56:20.628 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: CREATE OR REPLACE PROCEDURE PROC_KBV7_OCI_0x1786320(INTERNAL_PREFIX_0 INOUT REFCURSOR)
AS
begin TRIGGER_PKG.select_trigger_actions(INTERNAL_PREFIX_0); end;
[2023-07-07 09:56:20.631 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: SELECT nspname, proname, proretset, prorettypedef, pronargs, proargtypes, protype, proargnames, proargmodes, proargtypmods FROM sys_catalog.sys_namespace JOIN sys_catalog.sys_proc on sys_proc.pronamespace = sys_namespace.oid AND (not proretset) AND nspname NOT LIKE 'SYS_%' ESCAPE '' AND nspname != 'INFORMATION_SCHEMA' LEFT JOIN sys_catalog.sys_package ON sys_proc.propkgoid = sys_package.oid AND sys_package.pkgnamespace = sys_namespace.oid WHERE 1 AND proname LIKE 'PROC_KBV7_OCI_0X1786320' ESCAPE '' ORDER BY nspname, proname, proretset

---第二段黑体字

[2023-07-07 09:56:20.633 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: call PROC_KBV7_OCI_0x1786320('KDBCUR_1789020_1')
[2023-07-07 09:56:20.634 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: fetch all in KDBCUR_1789020_1
2023-07-07 09:56:20.634 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]ERROR: cursor "KDBCUR_1789020_1" does not exist
[2023-07-07 09:56:20.634 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]STATEMENT: fetch all in KDBCUR_1789020_1
[2023-07-07 09:56:20.635 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: drop procedure if exists PROC_KBV7_OCI_0x1786320(REFCURSOR)
[2023-07-07 09:56:20.636 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]LOG: statement: close KDBCUR_1789020_1
[2023-07-07 09:56:20.636 CST] [192.1.153.142][192.1.153.142(49637)][EMS][34][D5000][0]ERROR: cursor "KDBCUR_1789020_1" does not exist

从上面第一段黑体的日志可以看出,SET ENABLE_OUT_REFCURSOR_HOLDABLE TO on使游标可以跨事务执行,并且fetch all in KDBCUR_178A2F0_0执行游标提取成功,但是在第二段日志中同样的操作却出现了报错“ cursor "KDBCUR_1789020_1" does not exist”问题。

通过自己编写缩小的案例实测:

create or replace procedure proc_test01 (
    pcur inout refcursor  
)
as
begin
    open for select * from t1;
end ;

SET ENABLE_OUT_REFCURSOR_HOLDABLE TO on;

CALL PROC_TEST01('KDBCUR')

fetch all in KDBCUR

以上以上代码是能获取到结果集,但是必须要求proc_test01的参数为inout或者out模式,最终通过追查客户PROC_KBV7_OCI_0x1786320存储过程的定义,发现其未将参数模式定位为inout或者out模式,而是IN模式,故而问题找到原因。

标签:07,192.1,56,游标,Kingbase,sys,153.142,49637,ES
From: https://www.cnblogs.com/kingbase/p/17711782.html

相关文章

  • KingbaseESV8R6汉字首字母排序
    目的本文目的实现汉字首字母排序。排序规则和字符集的关系如下。selectsys_encoding_to_char(collencoding)asencoding,collname,collcollate,collctypefromsys_collation;按照UTF8字符集匹配中文排序规则如下。selectcollcollatefromsys_collationwheresys_encod......
  • KingbaseESV8R6普通用户无权限执行vacuum
    背景数据库日志有如下提示:WARNING:skipping"pivot_t1"---onlytableordatabaseownercanvacuumit从提示可以看出,有用户对表pivot_t1进行vacuum操作时,出现了权限问题。测试TEST=#\c-ud;Youarenowconnectedtodatabase"TEST"asuser"ud".TEST=>TEST=&g......
  • KingbaseESV8R6用户登录失败自动锁定后解锁遇到权限问题
    测试用户登录失败自动锁定创建用户tee并授权。TEST=#createusertee;CREATEROLETEST=#alteruserteewithcreatedb;ALTERROLETEST=#TEST=#alteruserteewithcreaterole;ALTERROLETEST=#TEST=#alterroleteewithreplication;ALTERROLETEST=#alterus......
  • KingbaseESV8R6识别IO使用率过高
    前言数据库正常运行离不开I/O的使用,在操作系统上,I/O又离不开存储的性能及使用方式,我们可以在存储层利用raid条带化技术使IOPS达到最佳性能。本篇文章有助于确认数据库I/O使用率过高的原因,以及解决方法。确定I/O使用率过高的原因1.需要数据库内置的sys_stat_statements扩展并......
  • KingbaseESV8R6延迟提交参数
    前言队列理论在我们生活中的应用随处可见,例如我们去食堂打饭需要排队,我们生活中随处可见排队的场景。在计算机领域中,性能诊断等地方使用队列理论的案例也很多。服务器硬件分为动态设备和静态设备。CPU和IO子系统属于动态设备,RAM属于静态设备,队列理论只对动态设备适用。Kingbase......
  • KingbaseESV8R6使用kbbench计算连接耗时
    前言本文讨论一下KingbaseESV8R6数据库中如何计算数据库连接耗时。有这样一个场景,不借助第三方工具,在数据库服务端计算1000个数据库连接的总耗时,并取得每个连接耗时的平均值。怎样实现呢?我们可以借助kbbench工具。这是Kingbase数据库自带的一款客户端工具。kbbench介绍kbbench......
  • KingbaseES数据库批量加载数据的最佳方法
    前言本文讨论在KingbaseES数据库服务器中批量加载数据的方法,以及空数据库中的初始数据加载和增量数据加载的最佳做法。批量加载方法以下数据加载方法按照从最耗时到最不耗时的顺序排列:1.运行单记录INSERT命令。2.在每次提交中分批成100到1000行。可以使用事务块在每次......
  • KingbaseESV8R6中查看索引常用sql
    前言KingbaseES具有丰富的索引功能,对于运行一段时间的数据库,经常需要查看索引的使用大小,使用状态等。尤其重复索引的存在,有时会因为索引过多而造成维护成本加大和减慢数据库的运行速度。下面是经常使用的查看索引的sql。1.查看表上索引个数,是否唯一,表与索引大小。SELECTCO......
  • KingbaseESV8R6全局临时表不能进行reindex操作
    背景我们经常遇到两种情况下会重建索引,reindex1、索引崩溃,由于软件或硬件问题导致索引内数据失效而不可用。2、索引膨胀,当索引膨胀会占用过多磁盘空间,reindex可以解决此问题。对于临时表和全局临时表而言,临时表可以进行reindex操作,而全局临时表不能进行此操作,原因是全局临时表......
  • 9.4classtest rewrite(仓库管理系统)
    第一部分,设计界面以及类的定义.importjava.util.Scanner;publicclassviovo{staticintnumber=5;//五个商品信息staticoppo[]s=newoppo[50];publicstaticvoidmain(String[]args){Scannerab=newScanner(System.in);......