PostgreSQL Oracle兼容性之 - 函数 自治事务 的实现
发布日期:2021-08-26 15:47:33 浏览次数:2 分类:技术文章

本文共 4866 字,大约阅读时间需要 16 分钟。

使用Oracle的用户,在函数中如果使用了自治事务的话,如果要转到PostgreSQL会遇到很棘手的问题。

因为PostgreSQL的函数是作为一个事务来处理的,要么全部提交,要么全部回滚,
除了exception,每个exception是一个子事务。
因此使用exception可以达到自治事务的目的。
例子1,
使用并行block和嵌套block,来控制子事务层级。
输入参数为block1, block2.1, block2.2, block3.1 。
这些参数代表执行在哪个block出错,出错时对应层级的block的exception会捕获错误,同时处理,然后跳到下一个block继续执行。
如果是外层的block出错,内层还没有被执行的block就没机会执行了。
根据业务需求,调整block层级或嵌套层级,达到目的。
这种用法可以完美的支撑业务的需求。
(除了一种情况不能满足,就是被提交的子事务立刻可以被其他事务可见。这种需求建本文下面的方法,用dblink来满足这种需求即可。)

create or replace function ft(err_level text) returns void as $$declarebegin -- block level 1  raise notice 'block level 1';  if (err_level='block1') then    raise exception '%', err_level;  end if;  begin -- block level 2.1    raise notice 'block level 2.1';  -- 请用业务处理SQL代替    if (err_level='block2.1') then      raise exception '%', err_level;    end if;    begin -- block level 3.1      raise notice 'block level 3.1';      if (err_level='block3.1') then        raise exception '%', err_level;      end if;      exception when others then  -- you can write catchup any ERROR CODE or ERROR STATE.        raise notice 'end block level 3.1';    end; -- end block level 3.1    exception when others then  -- you can write catchup any ERROR CODE or ERROR STATE. 回滚block 2.1的业务处理SQL      raise notice 'end block level 2.1';  end; -- end block level 2.1  begin -- block level 2.2    raise notice 'block level 2.2';    if (err_level='block2.2') then      raise exception '%', err_level;    end if;    exception when others then  -- you can write catchup any ERROR CODE or ERROR STATE.      raise notice 'end block level 2.2';  end; -- end block level 2.2  exception when others then  -- you can write catchup any ERROR CODE or ERROR STATE.    raise notice 'end block level 1';end; -- end block level 1$$ language plpgsql;

测试:

在block 1出错,出错代码后面的代码都不会被执行。

postgres=# select ft('block1');NOTICE:  block level 1NOTICE:  end block level 1 ft ---- (1 row)

在block2.1出错,block 2.1内部出错代码后面的代码都不会被执行。但是同级代码如2.2会被执行。

postgres=# select ft('block2.1');NOTICE:  block level 1NOTICE:  block level 2.1NOTICE:  end block level 2.1NOTICE:  block level 2.2 ft ---- (1 row)

在block2.2出错。

postgres=# select ft('block2.2');NOTICE:  block level 1NOTICE:  block level 2.1NOTICE:  block level 3.1NOTICE:  block level 2.2NOTICE:  end block level 2.2 ft ---- (1 row)

在block3.1出错。

postgres=# select ft('block3.1');NOTICE:  block level 1NOTICE:  block level 2.1NOTICE:  block level 3.1NOTICE:  end block level 3.1NOTICE:  block level 2.2 ft ---- (1 row)

更直观的例子:

drop table tt;create table tt(id int primary key, info text);insert into tt values(5,'test');create or replace function ft() returns void as $$declarebegin -- block level 1  begin -- block level 2.1    insert into tt values (1,'test'),(2,'test'),(3,'test');    exception when others then       raise notice 'rollback block level 2.1';  end; -- end block level 2.1  begin -- block level 2.2    insert into tt values (4,'test'),(5,'test'),(6,'test'); -- 主键冲突, 插入失败, 但是不影响后面的block继续执行.    exception when others then       raise notice 'rollback block level 2.2';  end; -- end block level 2.2  begin -- block level 2.3    insert into tt values (7,'test'),(8,'test'),(9,'test');    exception when others then       raise notice 'rollback block level 2.3';  end; -- end block level 2.3  exception when others then  -- you can write catchup any ERROR CODE or ERROR STATE.    raise notice 'rollback block level 1';end; -- end block level 1$$ language plpgsql;postgres=# select ft();NOTICE:  rollback block level 2.2 ft ---- (1 row)postgres=# select * from tt; id | info ----+------  5 | test  1 | test  2 | test  3 | test  7 | test  8 | test  9 | test(7 rows)

例子2:

使用dblink,同样需要将需要批量提交的部分写成子函数先。
例如 :

create extension dblink;CREATE SERVER fdtest FOREIGN DATA WRAPPER dblink_fdw OPTIONS (hostaddr '127.0.0.1', dbname '函数所在的库名');CREATE USER MAPPING FOR 需要调用函数的用户名 SERVER fdtest OPTIONS (user '需要调用函数的用户名', password '用户密码');GRANT USAGE ON FOREIGN SERVER fdtest TO 需要调用函数的用户名;

函数体

declare  dblink_block_res1 record;  dblink_block_res2 record;...  dblink_block_resn record;...  其他变量定义;begin-- 建立连接if ( dblink_connect('myconn', 'fdtest') <> 'OK' ) then  raise notice '连接失败';  return;end if;-- block 1,需要流转的变量通过参数传入下面的函数  select dblink('myconn', 'select func1($1,$2,...)') into dblink_block_res1;  -- $1,$2,...使用常数替代, 或动态SQL-- 中间结果判断  if not found then  -- dblink调用异常    -- 异常处理  else    -- dblink对应子事务已提交  end if;-- block 2,需要流转的变量通过参数传入下面的函数  select dblink('myconn', 'select func2($1,$2,...)') into dblink_block_res2;  -- $1,$2,...使用常数替代, 或动态SQL-- 中间结果判断  if not found then  -- 远程调用异常    -- 异常处理  else    -- dblink对应子事务已提交  end if;......-- block n,需要流转的变量通过参数传入下面的函数  select dblink('myconn', 'select funcn($1,$2,...)') into dblink_block_resn;  -- $1,$2,...使用常数替代, 或动态SQL-- 中间结果判断  if not found then  -- 远程调用异常    -- 异常处理  else    -- dblink对应子事务已提交  end if;......exception when others then...end;

其他参考地址:

转载地址:https://blog.csdn.net/weixin_33890499/article/details/90689835 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:基于vuejs2+webpack2+vuxui2多页面架手脚,支持二级目录
下一篇:Cocos2d-x 3.0坐标系详解

发表评论

最新留言

逛到本站,mark一下
[***.202.152.39]2024年04月12日 23时43分01秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章

超全深度学习细粒度图像分析:项目、综述、教程一网打尽 2019-04-28
旷视研究院出席全球计算机多媒体顶会ICME 2019 2019-04-28
ICCV 2019 | 旷视研究院提出MetaPruning:基于元学习和AutoML的模型压缩新方法 2019-04-28
旷视研究院「技术圆桌派 for PhDs」 2019-04-28
ICCV 2019 | 旷视研究院提出新型抠图方法AdaMatting,实现当前最佳 2019-04-28
活动 | 旷视「智见AI」SpringCamp圆满结营 (附回放链接) 2019-04-28
CVPR 2019 | 旷视研究院提出GIF2Video:首个深度学习GIF质量提升方法 2019-04-28
CVPR 2019 | 旷视研究院提出ML-GCN:基于图卷积网络的多标签图像识别模型 2019-04-28
CVPR 2019 | 旷视研究院Oral论文提出GeoNet:基于测地距离的点云分析深度网络 2019-04-28
CVPR 2019 | 旷视研究院提出实时语义分割技术DFANet:高清虚化无需双摄 2019-04-28
CVPR 2019 | 旷视研究院提出新型损失函数:改善边界框模糊问题 2019-04-28
CVPR 2019 | 旷视研究院提出Geo-CNN:建模3D点云的局部几何结构 2019-04-28
旷视研究院ShuffleNet V2斩获VALSE年度杰出学生论文奖 2019-04-28
旷视研究院喜提全球文字检测与识别顶赛ICDAR 2019-ArT两项世界第一 2019-04-28
VALSE 2019 | 旷视研究院奏响学术“华尔兹”,助力谱写中国CV新乐章 2019-04-28
R Talk | 旷视研究院张祥雨:高效轻量级深度模型的研究与实践 2019-04-28
活动 | 「R-Intern 猿力崛起」专场活动回顾 2019-04-28
CVPR 2019 | 旷视研究院提出用于全景分割的端到端闭环网络OANet 2019-04-28
CVPR 2019 | 旷视研究院提出极轻量级年龄估计模型C3AE 2019-04-28
CVPR 2019 | 旷视研究院提出TACNet,刷新时空动作检测技术新高度 2019-04-28