结论
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 结果一致。