相关

《Postgresql源码(60)事务系统总结》

《43.8. Transaction Management》

20220928新增

  • 从之前的分析可知(《Postgresql中plpgsql事务管理实例(commit/rollback)》),Postgresql中函数是不允许使用事务控制语句的(commit/rollback),只有Procedure和匿名块可以使用。

  • Procedure和匿名块都是使用SPI接口来实现事务功能的,且为了区分函数、过程、匿名块在函数引入了nonatomic

    • nonatomic=false:表示原子执行、函数、内部整体为一个事务。
    • nonatomic=false:表示非原子执行、过程匿名块、内部事务可以提交。
  • plpgsql内的commit/rollback实现比较简单,和普通事务没有太大区别。

    • 单个函数内commit/rollback与一个事务内执行commit/rollback一致,区别是plpgsql内在执行commit/rollback后会马上新启动一个事务。
    • 多个函数嵌套调用commit/rollback时,无论哪里执行了commit,都会把commit之前的语句(无论是内层还是外层)提交掉。
      • 在commit前嵌套调用执行过得所有语句都在一个事务中,commit会把这个事务提交掉所有语句无论在哪一层执行的都会持久化。

原文

实例1:PROCEDURE内部可以使用提交、回滚语句

drop table test1;
create table test1 (a int);
CREATE or replace PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGININSERT INTO test1 (a) VALUES (2);COMMIT;INSERT INTO test1 (a) VALUES (3);ROLLBACK;
END;
$$;CALL transaction_test1();
select * from test1;a
---2

commit语句都做了什么?

执行上层的事务状态流转函数:

  1. 执行CommitTransactionCommand
  2. 执行StartTransactionCommand
static int
exec_stmt_commit(PLpgSQL_execstate *estate, PLpgSQL_stmt_commit *stmt)
{if (stmt->chain)SPI_commit_and_chain();else{SPI_commit();SPI_start_transaction();}...return PLPGSQL_RC_OK;
}

rollback语句都做了什么?

执行上层的事务状态流转函数:

  1. 执行AbortCurrentTransaction
  2. 执行StartTransactionCommand
static int
exec_stmt_rollback(PLpgSQL_execstate *estate, PLpgSQL_stmt_rollback *stmt)
{if (stmt->chain)SPI_rollback_and_chain();else{SPI_rollback();SPI_start_transaction();}...return PLPGSQL_RC_OK;
}

实例2:PROCEDURE内报错自动回滚已执行的语句

drop table test1;
create table test1 (a int);
CREATE or replace PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGININSERT INTO test1 (a) VALUES (2);INSERT INTO test1 (a) VALUES (3);RAISE division_by_zero;
END;
$$;CALL transaction_test1();
ERROR:  division_by_zero
CONTEXT:  PL/pgSQL function transaction_test1() line 5 at RAISEselect * from test1;a
---
(0 rows)

事务是如何回滚的?

// 触发ereport ERROR
RAISE division_by_zero;  // jump 到:
PostgresMainif (sigsetjmp(local_sigjmp_buf, 1) != 0)AbortCurrentTransaction()

走AbortCurrentTransaction触发回滚动作

实例3:PROCEDURE内报错不会滚已经提交的语句

drop table test1;
create table test1 (a int);
CREATE or replace PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGININSERT INTO test1 (a) VALUES (2);COMMIT;INSERT INTO test1 (a) VALUES (3);RAISE division_by_zero;
END;
$$;CALL transaction_test1();
select * from test1;a
---2
(1 row)

参考实例1的分析结果,commit执行完了会新起一个事务,后面的保存不影响前面已经提交的事务了。

实例4:PROCEDURE包含EXCEPTION的语句块不支持COMMIT

drop table test1;
create table test1 (a int);
CREATE or replace PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGININSERT INTO test1 (a) VALUES (2);COMMIT;INSERT INTO test1 (a) VALUES (3);RAISE division_by_zero;
EXCEPTIONWHEN division_by_zero THENRAISE NOTICE 'caught division_by_zero';
END;
$$;CALL transaction_test1();
ERROR:  cannot commit while a subtransaction is active
CONTEXT:  PL/pgSQL function transaction_test1() line 4 at COMMITselect * from test1;a
---
(0 rows)

如果走EXCEPTION语句块的话,会把整个block包在一个子事务里面,子事务里面不支持执行commit。

exec_stmt_block...if (block->exceptions)// 启了一个子事务BeginInternalSubTransactionPG_TRY()exec_stmtsPG_CATCH()// 如果有异常,把整个子事务结束掉RollbackAndReleaseCurrentSubTransaction

实例5:function是原子的不支持部分提交

drop table test1;
create table test1 (a int);
CREATE or replace function transaction_test1()
returns void
LANGUAGE plpgsql
AS $$
BEGININSERT INTO test1 (a) VALUES (2);COMMIT;INSERT INTO test1 (a) VALUES (3);ROLLBACK;
END;
$$;select transaction_test1();
ERROR:  invalid transaction termination
CONTEXT:  PL/pgSQL function transaction_test1() line 4 at COMMIT

原因:

执行函数前,初始化SPI系统

如果传入的fcinfo->context是一个call context就配置nonatomic

plpgsql_call_handlernonatomic = fcinfo->context && IsA(fcinfo->context, CallContext) && !castNode(CallContext, fcinfo->context)->atomic;SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0))_SPI_current->atomic = (options & SPI_OPT_NONATOMIC ? false : true);

如果是call procedure语句

_SPI_current->atomic = false;

所以在执行exec_stmt_commit时,不会报错。

exec_stmt_commitSPI_commit_SPI_commitif (_SPI_current->atomic)ereport(ERROR,(errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),errmsg("invalid transaction termination")));

如果是function会直接报错退出。

Postgresql中procedure支持事务语法(实例分析)相关推荐

  1. Postgresql中plpgsql异常处理方法与实例(RAISE EXCEPTION)

    相关 <Postgresql中plpgsql异常处理方法与实例(RAISE EXCEPTION)> <Postgresql源码(80)plpgsql中异常处理编译与执行流程分析(sq ...

  2. nuxt 脚手架创建nuxt项目中不支持es6语法的解决方案

    nuxt 脚手架创建nuxt项目中不支持es6语法的解决方案 参考文章: (1)nuxt 脚手架创建nuxt项目中不支持es6语法的解决方案 (2)https://www.cnblogs.com/jk ...

  3. java 中数组与list_Java中List与数组相互转换实例分析

    这篇文章主要介绍了Java中List与数组相互转换的方法,实例分析了Java中List与数组相互转换中容易出现的问题与相关的解决方法,具有一定参考借鉴价值,需要的朋友可以参考下 本文实例分析了Java ...

  4. PostgreSQL中使用的SQL语法

    作者:瀚高PG实验室 (Highgo PG Lab)- Kalath 本文将介绍PostgreSQL中使用的几个SQL语法. 标识符和关键词 SQL标识符和关键词必须以一个字母(a-z,也可以是带变音 ...

  5. jsp action java_jsp中Action使用session方法实例分析

    本文实例分析了jsp中action使用session方法.分享给大家供大家参考.具体如下: 在struts2里,如果需要在action中使用session,可以通过下面两种方式得到 1.通过actio ...

  6. java中的递归算法_java递归算法实例分析

    递归算法设计的基本思想是: 对于一个复杂的问题,把原问题分解为若干个相对简单类同的子问题,继续下去直到子问题简单到能够直接求解,也就是说到了递推的出口,这样原问题就有递推得解. 在做递归算法的时候,一 ...

  7. python读取文本中的英文歌_Python 实例分析 - 获取MP3歌曲的Tag信息

    下面利用一个python的实例程序,来学习python.这个程序的目的就是分析出所有MP3文件的Tag信息并输出. 其中遇到一个问题,让我深切感受到python中依靠缩进来控制流程的缺点,不多说,看程 ...

  8. oracle存储过程循环单列,Oracle存储过程循环语法实例分析

    本文实例讲述了Oracle存储过程循环语法.分享给大家供大家参考,具体如下: 1.简单循环 语法 sql;"> loop statements; end loop; 例子: sql;& ...

  9. 聊聊ajax,聊聊Ajax()中data()基本知识以及实例分析

    最近忙得不可开交啊,一个星期没出来透透气了,总算有点时间,来来来总结点东西:Ajax()中data参数类型.聊到data()方法,玩过ajax的童鞋肯定不会陌生了,data() 方法向被选元素附加数据 ...

最新文章

  1. UA OPTI501 电磁波 Lorentz Oscillator Model 4 Hilbet变换与Kramers-Konig关系式
  2. 解决GitHub未配置SSH key提示错误信息
  3. linux彻底卸载multipath,深度分析LINUX环境下如何配置multipath
  4. linux shell之删除当前文件夹不包含文件1和文件2的其他所有文件
  5. 在WildFly 8.2中修补焊接3 – Java EE 8的第一个实验RI
  6. 美国团购网站Groupon的盈利模式
  7. 转:SQL:外连接on条件与where条件的区别
  8. 模板方法设计模式的原理及测试代码(手写JdbcTemplate)
  9. 用C#实现DES加密解密解决URL参数明文的问题
  10. 屏幕提词器Presentation Prompter for Mac
  11. Agreeing to the Xcode/iOS license requires admin privileges, please run “sudo xcodebuild -license”
  12. 用CSS制作细线表格
  13. LabVIEW程序测试
  14. 用 Java 写了一个抽奖功能,年会抽奖靠它了!
  15. matlab中matconvnet,MATLAB2017a编译MatConvNet过程中出现的各种问题
  16. linux GSM0710(2)
  17. IMF Fintech负责人:金融科技监管体制设计的五原则
  18. 【QT课程设计】五:部分内容修正、利用opencv读入视频并进行部分图像处理
  19. 亮度、饱和度、对比度、灰度 RGBHSV
  20. 偏微分方程:计算基本理论

热门文章

  1. 徐少春说,金蝶国际明年就成真正意义上的云计算公司
  2. 【洞见区块链】众专家探讨企业级区块链未来之路
  3. 代码随想录算法训练营day13 | 239. 滑动窗口最大值 | 347.前 K 个高频元素
  4. 多语言混合开发之易语言调用python算法
  5. Coreform Cubit (csimsoft Trelis)
  6. C#仿QQ皮肤-ComboBoxDataGridView
  7. 【人工智能】人工智能资料汇总(百度云盘)
  8. 蓝桥杯JAVA-番外篇之四舍五入(JAVA实现)
  9. linux小学生(一)之 linux简介
  10. 激光干涉仪测量机床精度之线性测量