点击蓝字

关注我们

本文将分别在openGauss/MogDB和PostgreSQL数据库中测试存储过程commit与exception的使用。

实验一

1.PostgreSQL

先创建测试表:

create table t1(id int);

下面创建存储过程proc1:

create or replace procedure proc1() as
$$
declare
beginraise notice '--begin to drop table t2,time=%',clock_timestamp();drop table if exists t2;raise notice '--drop table t2,time=%',clock_timestamp();raise notice '--begin to alter table t1 rename to t2,time=%',clock_timestamp();  alter table t1 rename to t2;raise notice '--alter table t1 rename to t2,time=%',clock_timestamp();   raise notice '--do something...,time=%',clock_timestamp();   perform pg_sleep(30);raise notice '--begin to commit,time=%',clock_timestamp();commit;raise notice '-- commit over,time=%',clock_timestamp();raise notice 'job is over,time=%',clock_timestamp();
end;
$$ language plpgsql;

完整的执行结果如下:

postgres=# call proc1();
NOTICE:  --begin to drop table t2,time=2021-12-22 17:11:52.746994+08
NOTICE:  table "t2" does not exist, skipping
NOTICE:  --drop table t2,time=2021-12-22 17:11:52.747054+08
NOTICE:  --begin to alter table t1 rename to t2,time=2021-12-22 17:11:52.747057+08
NOTICE:  --alter table t1 rename to t2,time=2021-12-22 17:11:52.74728+08
NOTICE:  --do something...,time=2021-12-22 17:11:52.74729+08
NOTICE:  --begin to commit,time=2021-12-22 17:12:22.778001+08
NOTICE:  -- commit over,time=2021-12-22 17:12:22.778074+08
NOTICE:  job is over,time=2021-12-22 17:12:22.778081+08
CALL
Time: 30031.268 ms (00:30.031)

上面的程序代码块里,我们使用commit语句是为了确保t1表的改名操作可以立即对其它客户端可见,同时为了便于测试观察,我们在commit语句之前加了一个30秒的延时。

下面观察如果在这个延迟的时间内,如果有新的客户端访问t1表,是什么现象,测试结果如下图:

可以看到新的客户端访问t1表会发生锁等待(截图中的左下和右下部分)。

2.openGauss/MogDB

先创建测试表:

create table t1(id int);

下面创建存储过程proc1:

create or replace procedure proc1() as
beginraise notice '--begin to drop table t2,time=%',clock_timestamp();drop table if exists t2;raise notice '--drop table t2,time=%',clock_timestamp();raise notice '--begin to alter table t1 rename to t2,time=%',clock_timestamp();  alter table t1 rename to t2;raise notice '--alter table t1 rename to t2,time=%',clock_timestamp();   raise notice '--do something...,time=%',clock_timestamp();   perform pg_sleep(30);raise notice '--begin to commit,time=%',clock_timestamp();commit;raise notice '-- commit over,time=%',clock_timestamp();raise notice 'job is over,time=%',clock_timestamp();
end;
/

完整的执行结果如下:

postgres=# call proc1();
NOTICE:  --begin to drop table t2,time=2021-12-22 17:37:40.72122+08
NOTICE:  table "t2" does not exist, skipping
CONTEXT:  SQL statement "drop table if exists t2"
PL/pgSQL function proc1() line 4 at SQL statement
NOTICE:  --drop table t2,time=2021-12-22 17:37:40.721364+08
NOTICE:  --begin to alter table t1 rename to t2,time=2021-12-22 17:37:40.721404+08
NOTICE:  --alter table t1 rename to t2,time=2021-12-22 17:37:40.721835+08
NOTICE:  --do something...,time=2021-12-22 17:37:40.721917+08
NOTICE:  --begin to commit,time=2021-12-22 17:38:10.723386+08
NOTICE:  -- commit over,time=2021-12-22 17:38:11.072483+08
NOTICE:  job is over,time=2021-12-22 17:38:11.072545+08

程序代码块里使用commit语句是为了确保t1表的改名操作可以立即对其它客户端可见,为了便于测试观察,我们在commit语句之前加了一个30秒的延时。

下面观察如果在这个延迟的时间内,如果有新的客户端访问t1表,是什么现象,测试结果如下图:

可以看到新的客户端访问t1表会发生锁等待(截图中的左下和右下部分)。

实验二

对上面的proc1增加exception处理,修改后的代码如下:

1.PostgreSQL

先创建测试表:

create table t1(id int);

下面创建存储过程proc2:

create or replace procedure proc2() as
$$
declare
beginraise notice '--begin to drop table t2,time=%',clock_timestamp();drop table if exists t2;raise notice '--drop table t2,time=%',clock_timestamp();raise notice '--begin to alter table t1 rename to t2,time=%',clock_timestamp();  alter table t1 rename to t2;raise notice '--alter table t1 rename to t2,time=%',clock_timestamp();   raise notice '--do something...,time=%',clock_timestamp();   perform pg_sleep(30);raise notice '--begin to commit,time=%',clock_timestamp();commit;raise notice '-- commit over,time=%',clock_timestamp();raise notice 'job is over,time=%',clock_timestamp();exception when others thenraise notice 'sqlstate=%,sqlerrm=%', sqlstate,sqlerrm;
end;
$$ language plpgsql;

完整的执行结果如下:

postgres=# call proc2();
NOTICE:  --begin to drop table t2,time=2021-12-22 17:48:56.030816+08
NOTICE:  --drop table t2,time=2021-12-22 17:48:56.031055+08
NOTICE:  --begin to alter table t1 rename to t2,time=2021-12-22 17:48:56.031082+08
NOTICE:  --alter table t1 rename to t2,time=2021-12-22 17:48:56.031242+08
NOTICE:  --do something...,time=2021-12-22 17:48:56.031269+08
NOTICE:  --begin to commit,time=2021-12-22 17:49:26.09492+08
NOTICE:  sqlstate=2D000,sqlerrm=cannot commit while a subtransaction is active
CALL
Time: 30064.663 ms (00:30.065)

可以看出,如果我们的语句块里有exception子句,那当我们调用commit语句则会提示错误:

cannot commit while a subtransaction is active

其实在官方文档有如下相关的描述:

A transaction cannot be ended inside a block with exception handlers.

参考链接如下:https://www.postgresql.org/docs/current/plpgsql-transactions.html

因此在PG里面,我们不能再有exception子句的存储过程使用commit或者rollback语句。

2.openGauss/MogDB

先创建测试表:

create table t1(id int);

再创建存储过程proc2:

create or replace procedure proc2() as
beginraise notice '--begin to drop table t2,time=%',clock_timestamp();drop table if exists t2;raise notice '--drop table t2,time=%',clock_timestamp();raise notice '--begin to alter table t1 rename to t2,time=%',clock_timestamp();  alter table t1 rename to t2;raise notice '--alter table t1 rename to t2,time=%',clock_timestamp();   raise notice '--do something...,time=%',clock_timestamp();   perform pg_sleep(30);raise notice '--begin to commit,time=%',clock_timestamp();commit;raise notice '-- commit over,time=%',clock_timestamp();raise notice 'job is over,time=%',clock_timestamp();exception when others thenraise notice 'sqlstate=%,sqlerrm=%', sqlstate,sqlerrm;
end;
/

完整的执行结果如下:

postgres=# call proc2();
NOTICE:  --begin to drop table t2,time=2021-12-22 17:57:58.572717+08
NOTICE:  --drop table t2,time=2021-12-22 17:57:58.573627+08
NOTICE:  --begin to alter table t1 rename to t2,time=2021-12-22 17:57:58.57374+08
NOTICE:  --alter table t1 rename to t2,time=2021-12-22 17:57:58.57425+08
NOTICE:  --do something...,time=2021-12-22 17:57:58.574311+08
NOTICE:  --begin to commit,time=2021-12-22 17:58:28.575849+08
NOTICE:  -- commit over,time=2021-12-22 17:58:28.774332+08
NOTICE:  job is over,time=2021-12-22 17:58:28.774389+08

可以看出,openGauss/MogDB里可以完整执行。

总结

通过两个实验,我们对比测试存储过程中commit与exception的使用。实验一结果一致,实验二结果不一致。

1.通过实验一我们了解可以使用commit语句立刻提交来确保程序块所作的变化对其它客户端可见,并且这是不可撤销的(rollback)。

2.在PostgreSQL里面,我们不能在有exception子句的存储过程使用commit或者rollback语句,openGauss/MogDB里则可以兼容这两种操作。


墨天轮原文链接:https://www.modb.pro/db/220168?sjhy复制链接至浏览器或点击文末阅读原文查看)

关于作者

彭冲,云和恩墨PG技术顾问,网名“多米爸比”,PG社区认证专家,中国首期PostgreSQL ACE Partner,多年从事基于PostgreSQL数据库的软件研发,擅长于PL/PGSQL业务迁移及优化,Oracle到PostgreSQL的迁移升级,异构数据库整合;作为墨天轮PostgreSQL实践专栏作者,热衷于PostgreSQL实践技术分享,在自己的岗位积极推广PostgreSQL,致力为PG社区多做奉献。

END

推荐阅读:2021数据技术嘉年华视频回放及PPT下载

2021数据技术嘉年华50余个PPT下载、视频回放已上传墨天轮平台,可在“数据和云”公众号回复关键词“2021DTC”获得!

你知道吗?我们的视频号里已经发布了很多精彩的内容,快去看看吧!↓↓↓

点击下图查看更多 ↓

云和恩墨大讲堂 | 一个分享交流的地方

长按,识别二维码,加入万人交流社群

请备注:云和恩墨大讲堂

  点个“在看”

你的喜欢会被看到❤

MogDB存储过程事务控制与异常块相关推荐

  1. SpringMVC与Mybatis集合实现调用存储过程、事务控制

    在SSM框架中经常会用到调用数据库中的存储过程.以及事务控制,下面以保存某单据为例,介绍一下: 1.Oracle中存储过程代码如下(主要逻辑将单据编码自动加1,并将该单据编码返回): CREATE O ...

  2. controller的异常处理以及service层的事务控制___controller层 trycatch不影响service层抛出的异常

    controller的异常处理以及service层的事务控制 最近写代码涉及到一些事务,上午终于把代码给理顺了,之前不太清楚在哪里做异常处理,导致代码遍地try-catch,相当难看. 还是基于con ...

  3. 服务器无法继续该事务 3400000006 错误原因--JAVA调用SQLSERVER存储过程时过程发生异常内部事务未

    通过JAVA调用SQLSERVER存储过程时,存储过程内部发生了类型转换异常,在类型转换异常发生之前已经将事务打开了,并且在类型转换那一行没有采用像如下错误处理: if @@error<> ...

  4. 0046 @Transactional注解的几个参数--事务传播控制--事务隔离级别--异常与回滚

    0046 @Transactional注解的几个参数--事务传播控制--事务隔离级别--异常与回滚 参考文章: (1)0046 @Transactional注解的几个参数--事务传播控制--事务隔离级 ...

  5. @Transactional注解的几个参数--事务传播控制--事务隔离级别--异常与回滚

    @Transactianal注解有一些属性,见Spring-Framework-Reference Table17.3 Transactional-settings @Transactional(pr ...

  6. c# mysql代码中写事务_代码中添加事务控制 VS(数据库存储过程+事务) 保证数据的完整性与一致性...

    [c#]代码库代码中使用事务前提:务必保证一个功能(或用例)在同一个打开的数据连接上,放到同一个事务里面操作. 首先是在D层添加一个类为了保存当前操作的这一个连接放到一个事务中执行,并事务执行打开同一 ...

  7. Spring——DAO层、Spring JDBC、Spring事务控制

    目录 一.Spring对持久层技术支持 1.Spring支持的持久层技术 2.Spring JDBC 2.1. JDBCTemplate类 2.2.Spring JDBC CRUD操作 2.3.Spr ...

  8. java web 转账事务控制

    转账事务控制 1.数据准备 CREATE TABLE `account` (`aid` int(11) NOT NULL AUTO_INCREMENT,`uname` varchar(255) DEF ...

  9. 【spring】spring基于xml的声明式事务控制

    结构 domain package com.itheima.domain;import java.io.Serializable;public class Account implements Ser ...

最新文章

  1. Assembly--及相关内容
  2. Transformer的潜在竞争对手QRNN论文解读,训练更快的RNN
  3. python爬虫正则表达式实例-python爬虫学习三:python正则表达式
  4. 你用过这种奇葩的C#注释吗?如何看待
  5. 无法在流的结尾之外进行读取_IO流,字节流,字符流
  6. opendolphin_使用DolphinDB进行机器学习
  7. 电子商务基础课件(10.25更新)
  8. 【老王来了】之隔壁路由器坏了,他来了...
  9. android 保存文件_Android 数据库操作框架LitePal使用介绍(一)
  10. zabbix系统日志文件监控key
  11. A joke about regular expression
  12. 死磕算法!35篇算法设计实例+6本必读书打包送你
  13. 故障:在 Application Log 中出现 ID57860 的 Backup Exec 错误日志
  14. 51单片机读引脚和读端口测试总结
  15. bat篇---windows bat启动exe结尾的可执行程序
  16. java--String类常用方法大全
  17. 爬虫_app 2.7 packet capture抓包工具介绍
  18. matlab动图启动,MATLAB制作动图或视频
  19. PP视频(PPTV聚力)web接口分析
  20. 微博android升级7.000,华为 Android 7.0 升级计划曝光:G9 青春版 /Nova 也有份

热门文章

  1. cass地籍参数设置命令_想成为一名厉害的测绘员?南方Cass教程+插件+课件不可少!...
  2. 如何使用Behat在Drupal中使用行为驱动的开发
  3. 最末参与者优化 lpo_优化博客以提高读者参与度的6种方法
  4. 组件化开发_思维导图
  5. jquery和javascript屏蔽右键菜单及阻止事件冒泡
  6. Less的条件表达式Guards
  7. 关于python字符编码以下选项中描述错误的是_关于import引用,以下选项中描述错误的是...
  8. php判断手机浏览器,php 获取 手机浏览器的信息 | 学步园
  9. 电竞高性能主机可以改云服务器吗,无缘主机平台 NBA 2K League电竞联赛将改用高性能PC...
  10. php之微型博客创建,php之微型博客的创建