Oracle 提交空事务是否昂贵?

Oracle 提交空事务是否昂贵?,oracle,oracle11g,transactions,Oracle,Oracle11g,Transactions,在某个Oracle 11.2环境中,我观察到不必要的提交,例如 -- some updates/inserts etc. commit; select * from mytable where somecond = 23; commit; 甚至: update mytable set foo = '42'; commit; commit; 因此,在这两个示例中,第二次提交都是不必要的,因为事务是“空的”——没有要提交的内容 问题是:这些不必要的承诺有多昂贵 Oracle DB是否足够“智能”

在某个Oracle 11.2环境中,我观察到不必要的提交,例如

-- some updates/inserts etc.
commit;
select * from mytable where somecond = 23;
commit;
甚至:

update mytable set foo = '42';
commit;
commit;
因此,在这两个示例中,第二次提交都是不必要的,因为事务是“空的”——没有要提交的内容

问题是:这些不必要的承诺有多昂贵

Oracle DB是否足够“智能”来检测此类空事务并用(无)替换那些不必要的提交


背景:这些冗余提交有时似乎来自某些框架的层,程序员不知道“隐藏”逻辑,或者有时它们只是疏忽。根据它们的昂贵程度(就数据库性能而言),以高优先级修复代码是有意义的。

是的,即使没有要提交的内容,也会有开销。当您发出提交时,会有很多事情被序列化,因此可伸缩性会受到影响

HUSQVIK@db> BEGIN
  2     FOR i IN 1..100000 LOOP
  3             NULL;
  4     END LOOP;
  5  END;
  6  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:00.00
HUSQVIK@db> BEGIN
  2     FOR i IN 1..100000 LOOP
  3             COMMIT;
  4     END LOOP;
  5  END;
  6  /

PL/SQL procedure successfully completed.

Elapsed: 00:00:02.37

空提交并不昂贵,可以忽略。空提交只需要少量CPU,不会阻塞其他进程或阻止可伸缩性

正常提交速度较慢,因为它会导致数据写入磁盘以确保持久性。数据库更改需要重做(以防数据库在更改之前崩溃) 数据可以完全写入数据文件,允许恢复向前滚动)、撤消(以便其他事务可以看到更改前的数据), 将新的系统更改号记录到控制文件等。只有将这些内容写入磁盘,提交才会完成

空提交不会执行任何这些操作。它们使用CPU时间,但可能只足以检查是否需要进行更改。CPU时间 与写入数据文件、重做日志或控制文件相比,它的成本较低。它应该具有良好的伸缩性

下面的示例表明,真正的问题是在每次微小更改后执行提交。仅运行时间不足以比较这三种方法。 如果查看GV$ACTIVE_SESSION_历史记录中的等待,或磁盘I/O(来自Windows资源监视器、Solaris truss等),您将看到下面的示例#1 只使用CPU。示例3使用CPU、重做日志、数据文件和控制文件

--#1: Empty commits.
--15 seconds for 1 million commits.
--Only CPU waits, almost no I/O is generated.
begin
    for i in 1..1000000 loop
        commit;
    end loop;
end;
/


--#2: Just inserts.
--34 seconds for 1 million inserts.
--CPU waits, plus some "other" waits.
create table test1(a number);
begin
    for i in 1..1000000 loop
        insert into test1 values(1);
    end loop;
    commit;
end;
/


--#3: Inserts and commits.
--107 seconds for 1 million inserts and commits.
--Lots of CPU waits, lots of "other" waits.
begin
    for i in 1..1000000 loop
        insert into test1 values(1);
        commit;
    end loop;
end;
/

如果你把网络往返看作是慢的,那就要看了。我想知道你是否正从正确的方向接近一个性能问题。“JeffreyKemp,你是什么意思?”