结论

PG的是事务和ORACLE的事务是不一样的

在ORACLE事务中,有失败是可以继续执行的,且事务提交后,只有失败的不可见(成功的可见)

在PG事务中,有失败,立即中止,且前面成功的,也会回滚

报错:current transaction is aborted, commands ignored until end of transaction block


原因

oracle具有子事务功能,orale的子事务是指一个大事务可以包含多个小事务,而每个小事务可以单独提交或者回滚,同时也支持跟随父事务进行提交或回滚。其实现原理为嵌套事务结合保存点来实现的。

在Oracle数据库中执行第一条数据操纵语言(DML)语句(如INSERT、UPDATE、DELETE)时,Oracle会自动隐式地开启一个新的事务。这意味着,事务的开启是自动进行的,用户无需进行额外的操作。


PG

MogDB=# \c testdb
Non-SSL connection (SSL connection is recommended when requiring high-security)
You are now connected to database "testdb" as user "sysomm".
testdb=# create table t_test_trans(var varchar(2),fixed char(2));
CREATE TABLE
testdb=# begin;
BEGIN
testdb=# insert into t_test_trans values('1','1');
INSERT 0 1
testdb=# insert into t_test_trans values('2','2');
INSERT 0 1
testdb=# insert into t_test_trans values('测试3','测试3');
ERROR:  value too long for type character varying(2)
CONTEXT:  referenced column: var
testdb=# insert into t_test_trans values('4','4');
ERROR:  current transaction is aborted, commands ignored until end of transaction block, firstChar[Q]
testdb=# commit;
ROLLBACK
testdb=# select * from t_test_trans;
 var | fixed 
-----+-------
(0 rows)

ORACLE

create table t_test_trans(var varchar(2),fixed char(2));

SQL> insert into t_test_trans values('1','1');

1 row created.

SQL> insert into t_test_trans values('2','2');

1 row created.

SQL> insert into t_test_trans values('测试3','测试3');
insert into t_test_trans values('测试3','测试3')
                                *
ERROR at line 1:
ORA-12899: value too large for column "SYS"."T_TEST_TRANS"."VAR" (actual: 10, maximum: 2)


SQL> insert into t_test_trans values('4','4');

1 row created.

SQL> commit;

Commit complete.

SQL> select * from t_test_trans;

VAR  FIXE
---- ----
1    1
2    2
4    4


--oracle
create table t_test(id int PRIMARY KEY, name varchar(20));

insert into t_test values (1,'111');
insert into t_test values (2,'222');
insert into t_test values (3,'333');
commit;

se1:
delete t_test where id = '3'; 

se2:
delete t_test where id = '3';  --会话挂起

se1:
insert into t_test values(3,'133');
commit;

se2:
insert into t_test values(3,'233');

SQL> select * from t_test;

	ID NAME
---------- ----------------------------------------
	 1 111
	 2 222
	 3 233

--mogdb
create table t_test(id int PRIMARY KEY, name varchar(20));

insert into t_test values (1,'111');
insert into t_test values (2,'222');
insert into t_test values (3,'333');

se1:
start transaction;
delete t_test where id = '3'; 

se2:
start transaction;
delete t_test where id = '3';  --会话挂起

se1:
insert into t_test values(3,'133');
commit;

se2:
insert into t_test values(3,'233');
auxdb=# insert into t_test values(3,'233');
ERROR:  duplicate key value violates unique constraint "t_test_pkey"
DETAIL:  Key (id)=(3) already exists.


在MogDB老版本中,可使用类似MySQL的insert ON DUPLICATE KEY UPDATE之类的语法来解决该问题。
两者的区别是 Oracle 会在挂起的会话2恢复后,再次执行一遍。

在opengauss 挂起的会话2,手动再次执行一次,得出的结果和 oracle 结果一致。