当前位置:网站首页>Postgresql中procedure支持事务语法(实例&分析)
Postgresql中procedure支持事务语法(实例&分析)
2022-07-07 02:05:00 【mingjie73】
相关
https://www.postgresql.org/docs/current/plpgsql-transactions.html
实例1:PROCEDURE内部可以使用提交、回滚语句
drop table test1;
create table test1 (a int);
CREATE or replace PROCEDURE transaction_test1()
LANGUAGE plpgsql
AS $$
BEGIN
INSERT INTO test1 (a) VALUES (2);
COMMIT;
INSERT INTO test1 (a) VALUES (3);
ROLLBACK;
END;
$$;
CALL transaction_test1();
select * from test1;
a
---
2
commit语句都做了什么?
执行上层的事务状态流转函数:
- 执行CommitTransactionCommand
- 执行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语句都做了什么?
执行上层的事务状态流转函数:
- 执行AbortCurrentTransaction
- 执行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 $$
BEGIN
INSERT 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 RAISE
select * from test1;
a
---
(0 rows)
事务是如何回滚的?
// 触发ereport ERROR
RAISE division_by_zero;
// jump 到:
PostgresMain
if (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 $$
BEGIN
INSERT 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 $$
BEGIN
INSERT INTO test1 (a) VALUES (2);
COMMIT;
INSERT INTO test1 (a) VALUES (3);
RAISE division_by_zero;
EXCEPTION
WHEN division_by_zero THEN
RAISE 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 COMMIT
select * from test1;
a
---
(0 rows)
如果走EXCEPTION语句块的话,会把整个block包在一个子事务里面,子事务里面不支持执行commit。
exec_stmt_block
...
if (block->exceptions)
// 启了一个子事务
BeginInternalSubTransaction
PG_TRY()
exec_stmts
PG_CATCH()
// 如果有异常,把整个子事务结束掉
RollbackAndReleaseCurrentSubTransaction
实例5:function是原子的不支持部分提交
drop table test1;
create table test1 (a int);
CREATE or replace function transaction_test1()
returns void
LANGUAGE plpgsql
AS $$
BEGIN
INSERT 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_handler
nonatomic = 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_commit
SPI_commit
_SPI_commit
if (_SPI_current->atomic)
ereport(ERROR,
(errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
errmsg("invalid transaction termination")));
如果是function会直接报错退出。
边栏推荐
- Install mongodb database
- C interview encryption program: input plaintext by keyboard, convert it into ciphertext through encryption program and output it to the screen.
- ETCD数据库源码分析——从raftNode的start函数说起
- laravel 使用腾讯云 COS5全教程
- VIM mapping large K
- Basic DOS commands
- 你不知道的互联网公司招聘黑话大全
- [SOC FPGA] peripheral PIO button lights up
- LM small programmable controller software (based on CoDeSys) Note 23: conversion of relative coordinates of servo motor operation (stepping motor) to absolute coordinates
- Markdown displays pictures side by side
猜你喜欢

安装VMmare时候提示hyper-v / device defender 侧通道安全性

CloudCompare-点对选取

A program lets you understand what static inner classes, local inner classes, and anonymous inner classes are

港科大&MSRA新研究:关于图像到图像转换,Fine-tuning is all you need

Redis (I) -- getting to know redis for the first time

PostgreSQL database timescaledb function time_ bucket_ Gapfill() error resolution and license replacement

tkinter窗口选择pcd文件并显示点云(open3d)

JMeter function assistant - random value, random string, fixed value random extraction

win系统下安装redis以及windows扩展方法

基于ADAU1452的DSP及DAC音频失真分析
随机推荐
[SOC FPGA] custom IP PWM breathing lamp
Subghz, lorawan, Nb IOT, Internet of things
地质学类比较有名的外文期刊有哪些?
微信小程序隐藏video标签的进度条组件
2022 Android interview essential knowledge points, a comprehensive summary
Redisl garbled code and expiration time configuration
3428. Put apples
ST表预处理时的数组证明
Database notes 04
Go straight to the 2022ecdc fluorite cloud Developer Conference: work with thousands of industries to accelerate intelligent upgrading
Audio distortion analysis of DSP and DAC based on adau1452
Experience sharing of contribution of "management world"
Find duplicate email addresses
VMware安装后打开就蓝屏
What are the classic database questions in the interview?
JVM command - jmap: export memory image file & memory usage
POI导出Excel:设置字体、颜色、行高自适应、列宽自适应、锁住单元格、合并单元格...
Rk3399 platform development series explanation (interruption) 13.10, workqueue work queue
Symmetric binary tree [tree traversal]
Redis(二)—Redis通用命令