首页 > 数据库 >postgresql事务与oracle中的事务差异

postgresql事务与oracle中的事务差异

时间:2024-11-10 20:48:26浏览次数:1  
标签:事务 postgresql -- begin test oracle trans id

事务

事务ID及回卷

  参见postgresql中的事务回卷原理及预防措施

子事务(事务处理:概念与技术 4.7)

 

 子事务具有ACI特性,但是不具有D特性。只会在主事务提交时,才会提交,无法单独提交。pg不支持子事务。

xact

保存点

保存点是不支持子事务/嵌套事务时的折中实现,但它是ANSI SQL标准的一部分。因为管理更加简单(参见事务处理:概念与技术 4.5节)。 

保存点比子事务具有更灵活的可恢复性,可以恢复到任意位置。但是保存点不可以单独提交。

zjh@postgres=# create table table1 (a int);
CREATE TABLE

zjh@postgres=# BEGIN;
BEGIN
zjh@postgres=*#     INSERT INTO table1 VALUES (3);
INSERT 0 1
zjh@postgres=*#     SAVEPOINT my_savepoint;
SAVEPOINT
zjh@postgres=*#     INSERT INTO table1 VALUES (4);
INSERT 0 1
zjh@postgres=*#     RELEASE SAVEPOINT my_savepoint;
RELEASE
zjh@postgres=*# select * from table1;
 a 
---
 3
 4
(2 rows)

zjh@postgres=*# rollback;
ROLLBACK
zjh@postgres=# select * from table1;
 a 
---
(0 rows)

zjh@postgres=# BEGIN;
BEGIN
zjh@postgres=*#     INSERT INTO table1 VALUES (4);
INSERT 0 1
zjh@postgres=*# BEGIN;
WARNING:  there is already a transaction in progress
BEGIN

 pg中的事务行为

create table test_trans(id int, v int);
insert into test_trans values(1,1);
insert into test_trans values(2,2);
insert into test_trans values(3,3);
insert into test_trans values(4,4);

-- 测试事务里面走plsql块,plsql块里面正常回滚
begin;
do $$

begin
delete from test_trans where id = 1;
rollback;

END$$;

-- 报“invalidtransaction termination”    如果CALL在事务块中执行,则被调用的存储过程无法执行事务控制语句(也就是commit/rollback)等TCL语句。只有CALL在自己事务中执行时,才允许事务控制语句。而我们使用python程序模块psycopg连接的时候,通常是以begin开始运行的,这就代表了CALL在事务块中运行,是没办法在存储过程中执行commit的。
select * from test_trans;
commit;

-- 测试事务里面走plsql块,plsql块里面正常提交
begin;
do $$

begin
delete from test_trans where id = 1;
rollback;

END$$;
-- ERROR:  invalid transaction termination
select * from test_trans;
commit;

-- 测试事务里面走plsql块,plsql块里面无事务控制提交
begin;
do $$

begin
delete from test_trans where id = 1;

END$$;
select * from test_trans;
rollback;

-- 测试事务里面走plsql块,plsql块里面无事务控制回滚
begin;
do $$

begin
delete from test_trans where id = 1;

END$$;
select * from test_trans;
commit;
insert into test_trans values(1,1);

-- 测试事务里面走plsql块,plsql块exception里面回滚
begin;
do $$
declare i int;
begin
delete from test_trans where id = 1;
i:=1/0;  -- i=1/0; 也行
exception when others then
   rollback;
END$$;
-- 同上面,报无效的事务终止
select * from test_trans;
commit;

-- 测试事务里面走plsql块,plsql块exception里面提交
begin;
do $$
declare i int;
begin
delete from test_trans where id = 1;
i:=1/0;
exception when others then
   commit;
END$$;
-- 同上面,报无效的事务终止
select * from test_trans;
rollback;

-- 测试存储过程的上述主块和异常控制行为
create or replace procedure sp_test_trans()
language plpgsql    
as $$
begin
    delete from test_trans where id = 1;
    commit;
end $$;

lightdb@postgres=# begin;
BEGIN
lightdb@postgres=*# call sp_test_trans ;
ERROR:  invalid transaction termination    -- 存储过程和事务都一样,不允许嵌套在事务中
CONTEXT:  PL/pgSQL function sp_test_trans() line 4 at COMMIT


-- 测试函数的上述主块和异常控制行为
create or replace function fn_test_trans() returns void
language plpgsql    
as $$
begin
    delete from test_trans where id = 1;
    commit;
end $$;
-- 因为select会开启隐式事务,所以在事务中了,所以函数本质上和存储过程一样(不存在存储过程中允许事务一说),是 call调用所致的差别
lightdb@postgres=# select * from fn_test_trans();
ERROR:  invalid transaction termination
CONTEXT:  PL/pgSQL function fn_test_trans() line 4 at COMMIT

-- 纯粹的pl/sql块嵌套,子块里面有事务
do $$
declare i int;
begin
    delete from test_trans where id = 2;
    begin
        from test_trans where id = 1;
        i:=1/0;  -- i=1/0; 也行
    exception when others then
       rollback;   -- 不只是回滚子块,回滚了整个块
    END;
    commit;
END $$;

-- 存储过程调用函数,里面带事务
create or replace procedure sp_test_call_func()
language plpgsql    
as $$
begin
    delete from test_trans where id = 1;
    commit;
    perform fn_test_trans();
end $$;

-- 因为已经在事务中,所以perform调用失败

上述语句oracle中的行为

dbeaver默认自动提交,所以去掉了自动提交。

 

create table test_trans(id int, v int);
insert into test_trans values(1,1);
insert into test_trans values(2,2);
insert into test_trans values(3,3);
insert into test_trans values(4,4);

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

begin
delete from test_trans where id = 1;
rollback;
END;
-- 已经被回滚了,有咩有commit无所谓
COMMIT;

declare i int;
begin
delete from test_trans where id = 1;
i:=1/0;  
exception when others then
   rollback;  -- 已经被回滚了
END;
/  -- dbeaver去掉 /
SELECT * FROM test_trans;

declare i int;
begin
delete from test_trans where id = 1;
i:=1/0;  
exception when others then
   commit;   -- 还在同一个事务,1被删了
END;
/  -- dbeaver去掉 /

SELECT * FROM test_trans;

INSERT into test_trans values(1,1);
SELECT * FROM test_trans;
create or replace procedure sp_test_trans
is
begin
    delete from test_trans where id = 1;
    commit;
end;
/  -- dbeaver去掉 /

-- 测试存储过程提交
DELETE FROM test_trans WHERE id = 4;

CALL sp_test_trans();
-- delete from id = 4也提交了。

SELECT * FROM test_trans;
TRUNCATE TABLE test_trans;
insert into test_trans values(1,1);
insert into test_trans values(2,2);
insert into test_trans values(3,3);
insert into test_trans values(4,4);
COMMIT;

declare i int;
begin
    delete from test_trans where id = 1;

    begin
      delete from test_trans where id = 2;
      i:=1/0;  -- i=1/0; 也行
    
    exception when others then
       commit;   -- 还在同一个事务,2被删了
    END;
exception when others then
   ROLLBACK;   -- 还在同一个事务,1被删了
END;
/  -- dbeaver去掉 /
SELECT * FROM test_trans;

事务行为差异总结

  如果驱动或客户端不设置,oracle默认在DML后自动开启事务,且不自动提交。在select后自动提交。这是由内核控制的。

  在pg中,如果不在一个事务中,默认是会自动开启一个事务、自动提交的。自动开启没问题,但是自动提交需要改成非自动(这是第一个变化点)。

   pg多语句在一个事务需要显示开始,oracle则不用显示开启。所以第二个点是如果一批语句,第一个DML开启的地方才是真正的事务,之前的select全部自动提交,不管在不在存储过程、不管有没有异常。

  第三个点是pg没有见到commit/ROLLBACK,都不结束事务(需要确认pg里面commit是客户端、驱动干的还是内核干的)。第四个点是oracle如果发生了异常,比如1/0,只是报错,不改变事务的状态。

  oracle语句块嵌套、函数调用函数、函数调用过程、过程调用过程:子块和事务没有关系,一路平行到底,也就是代码怎么写和事务没关系,除了明确的savepoint、COMMIT、ROLLBACK。

   最后,plpgsql块本身就是个savepoint(跟这里的描述是一致的,https://dev.to/aws-heroes/exceptions-and-commit-in-postgresql-plpgsql-vs-oracle-plsql-1nk8),有异常的时候整个rollback,所以要跟Oracle一致,那就是每个语句前都需要加个savepoint。exception发生的时候,回滚到出错前那一个savepoint(这种做法是比较差的)。

正确的做法是,语句级回滚。当做语句的状态正常出错即可。用户爱回滚回滚、爱提交提交。

 

  -- savepoint的差异,没有差异。V$TRANSACTION查看进行中的事务(pg暂无对应,实现也简单的,主要是返回事务id和最新执行的语句)。https://www.modb.pro/db/51691 查看Oracle事务行为,还有一个Transaction Guard,12c新增,用户给终端更好的体验。

参考:

  https://www.postgresql.org/docs/11/plpgsql-transactions.html

 https://franckpachot.medium.com/postgresql-subtransactions-savepoints-and-exception-blocks-67e0fbd412af

子事务的问题:https://about.gitlab.com/blog/2021/09/29/why-we-spent-the-last-month-eliminating-postgresql-subtransactions/

oracle自治事务

http://www.nyoug.org/Presentations/2002/fire_forget.pdf,lightdb的自治事务行为和oracle一致,百度/必应搜索引擎搜索"lightdb 自治事务"即可。

标签:事务,postgresql,--,begin,test,oracle,trans,id
From: https://www.cnblogs.com/lightdb/p/14870386.html

相关文章

  • PostgreSQL 安装 POSTGRES_FDW
    PostgreSQL安装POSTGRES_FDW插件postgres_fdw模块提供外部数据包装器postgres_fdw它可以用于访问存储在外部PostgreSQL服务器中的数据。使用postgres_fdw访问外部数据需要做以下几点准备:1、使用CREATEextension安装postgres_fdw扩展2、使用createserver......
  • 【数据库系列】postgresql链接详解
    ......
  • MySQL中的事务与锁
    目录事务InnoDB和ACID模型 原⼦性的实现持久性的实现 ​隔离性的实现锁隔离级别 ​多版本控制(MVCC)事务1.什么是事务?事务是把⼀组SQL语句打包成为⼀个整体,在这组SQL的执⾏过程中,要么全部成功,要么全部失败,这组SQL语句可以是⼀条也可以是多条示例:转账的......
  • 07 Oracle数据库恢复基础解析:从检查点到归档,一步步构建数据安全防线
    文章目录Oracle数据库恢复基础解析:从检查点到归档,一步步构建数据安全防线一、检查点(Checkpoint)1.1检查点定义1.2检查点重要性1.3检查点工作原理1.4手动触发检查点二、日志(RedoLog)2.1日志定义2.2日志重要性2.3查看当前使用的Redo日志成员三、归档机制(Archiving)3......
  • 08 Oracle数据库故障应对与恢复策略:全面掌握RMAN恢复方法
    文章目录Oracle数据库故障应对与恢复策略:全面掌握RMAN恢复方法一、故障场景及恢复策略1.1实例失败1.2介质故障1.3数据丢失二、RMAN恢复方法详解2.1全库恢复2.2增量恢复2.3时间点恢复三、实践与总结Oracle数据库故障应对与恢复策略:全面掌握RMAN恢复方法Ora......
  • Oracle 中的 Incarnation 到底是个什么?概念理解篇
    转自:https://www.cnblogs.com/askscuti/p/10935945.html目录1.恋爱的持续2.痛苦的分手3.对上天的祈求4.重生的机会(恋爱篇)5.重生的机会(数据库篇)6.幸福美满的生活 1.恋爱的持续一直到上大学,我们不在同一个地方-称之为异地恋,那时候没有微信,没有触屏手机,移动的动......
  • Oracle 中的 Incarnation 到底是个什么?实验操作篇
    转自:https://www.cnblogs.com/askscuti/p/10939593.html目录1.官方图示例2.场景模拟3.实验步骤3.1备份数据库(略)3.2 查询当前数据库化身版本3.3按场景模拟操作3.4恢复出B表并打开数据库3.5查询当前数据库化身版本3.6恢复出A-6(修改当前......
  • Oracle 与 GreatSQL 差异:更改唯一索引列
    Oracle与GreatSQL差异:更改唯一索引列问题来源在从Oracle迁移到GreatSQL的应用系统中,一条普通的update语句在GreatSQL中却报错,需要进行SQL语句的改写。把实际问题简化为下面简单情况进行说明。在Oracle下,可以正常执行的update语句。--建表CREATETABLEte......
  • Seata — 分布式事务
    1.分布式事务简介分布式事务是指在分布式系统中,事务涉及到多个数据库和服务,需要跨多个系统节点协调完成事务的提交和回滚,保证系统的一致性。由于涉及多个节点,分布式事务比单一数据库中的事务实现更为复杂。归其原因就是参与事务的多个子业务在不同的微服务,跨越了不同的数据......
  • Oracle 第28章:Oracle机器学习
    Oracle机器学习第28章:数据科学与机器学习基础及利用Oracle进行预测性分析在当今数据驱动的时代,数据科学和机器学习成为了企业决策的重要组成部分。Oracle作为一家领先的数据库技术提供商,不仅提供强大的数据库管理功能,还整合了先进的数据分析工具,使得用户能够轻松地在其环境......