[20130607]PL/SQL存储过程的commit提交问题.txt

[20130607]PL/SQL存储过程的commit提交问题.txt

昨天在看别人写的存储过程的时候,发现程序代码里面不好的写法,就是把commit写在循环体内,这样写按照以前应该会产生很大的redo日
志,主要是redo waste也会增加,但是我在11G下测试,情况好像不一样.

1.建立测试环境:

SQL> @ver
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.3.0 - 64bit Production
create table t (a number,b varchar2(10));
$ cat viewredo.sql
SELECT b.NAME, a.statistic#, a.VALUE
  FROM v$mystat a, v$statname b
 WHERE b.NAME IN ('redo size', 'redo wastage') AND a.statistic# = b.statistic#;
2.测试1:(commit在循环体内)
set timing on
@viewredo.sql
begin
for i in 1..10000 loop
insert into t values (i,'test');
commit;
end loop;
end;
/
@viewredo
@viewredo.sql
NAME                 STATISTIC#      VALUE
-------------------- ---------- ----------
user commits                  6          0
redo size                   178        728
redo wastage                183          0
@viewredo.sql
NAME                  STATISTIC#      VALUE
-------------------- ---------- ----------
user commits                  6      10000
redo size                   178    4863032
redo wastage                183          0
--Elapsed: 00:00:01.32,redo size=4863032-728=4862304.
3.测试2:(commit在循环体外)
set timing on
@viewredo.sql
begin
for i in 1..10000 loop
insert into t values (i,'test');
end loop;
commit;
end;
/
@viewredo.sql
NAME                 STATISTIC#      VALUE
-------------------- ---------- ----------
user commits                  6          0
redo size                   178        728
redo wastage                183          0
NAME                 STATISTIC#      VALUE
-------------------- ---------- ----------
user commits                  6          1
redo size                   178    2536896
redo wastage                183          0
--Elapsed: 00:00:00.56,redo size=2536896-728=2536168.

--对比发现时间上并没有什么差别,当然redo size前面几乎比后面的大1倍,不知道为什么这个版本redo wastage都是0.
--我记忆里面以前在8i下做过测试,测试1应该需要许多时间.不可能这么快完成.

4.测试3

--突然想起来10g下提交可以改成如下:

set timing on
@viewredo.sql
begin 
for i in 1..10000 loop 
insert into t values (i,'test'); 
commit write wait; 
end loop; 
end; 
/
@viewredo.sql
NAME                 STATISTIC#      VALUE
-------------------- ---------- ----------
user commits                  6          0
redo size                   178        728
redo wastage                183          0
NAME                 STATISTIC#      VALUE
-------------------- ---------- ----------
user commits                  6      10000
redo size                   178    5527876
redo wastage                183          0

--Elapsed: 00:01:01.14.redo size=5527876-728=5527148.

5.google找到如下链接:
http://www.oracle-base.com/articles/10g/commit-10gr2.php
--我修改一点,加入commit的比较.

CREATE TABLE commit_test (
  id           NUMBER(10),
  description  VARCHAR2(50),
  CONSTRAINT commit_test_pk PRIMARY KEY (id)
);
SET SERVEROUTPUT ON
DECLARE
  PROCEDURE do_loop (p_type  IN  VARCHAR2) AS
    l_start  NUMBER;
    l_loops  NUMBER := 1000;
  BEGIN
    EXECUTE IMMEDIATE 'TRUNCATE TABLE commit_test';
                                                                                                            
    l_start := DBMS_UTILITY.get_time;
    FOR i IN 1 .. l_loops LOOP
      INSERT INTO commit_test (id, description)
      VALUES (i, 'Description for ' || i);
      
      CASE p_type
        WHEN 'WAIT'             THEN COMMIT WRITE WAIT;
        WHEN 'NOWAIT'           THEN COMMIT WRITE NOWAIT;
        WHEN 'BATCH'            THEN COMMIT WRITE BATCH;
        WHEN 'IMMEDIATE'        THEN COMMIT WRITE IMMEDIATE;
        WHEN 'BATCH,WAIT'       THEN COMMIT WRITE BATCH WAIT;
        WHEN 'BATCH,NOWAIT'     THEN COMMIT WRITE BATCH NOWAIT;
        WHEN 'IMMEDIATE,WAIT'   THEN COMMIT WRITE IMMEDIATE WAIT;
        WHEN 'IMMEDIATE,NOWAIT' THEN COMMIT WRITE IMMEDIATE NOWAIT;
        else  COMMIT;
      END CASE;
    END LOOP;
    DBMS_OUTPUT.put_line(RPAD('COMMIT WRITE ' || p_type, 30) || ': ' || (DBMS_UTILITY.get_time - l_start));
  END;
BEGIN
  do_loop('other');
  do_loop('WAIT');
  do_loop('NOWAIT');
  do_loop('BATCH');
  do_loop('IMMEDIATE');
  do_loop('BATCH,WAIT');
  do_loop('BATCH,NOWAIT');
  do_loop('IMMEDIATE,WAIT');
  do_loop('IMMEDIATE,NOWAIT');
END;
/
COMMIT WRITE other            : 18
COMMIT WRITE WAIT             : 680
COMMIT WRITE NOWAIT           : 18
COMMIT WRITE BATCH            : 780
COMMIT WRITE IMMEDIATE        : 752
COMMIT WRITE BATCH,WAIT       : 901
COMMIT WRITE BATCH,NOWAIT     : 19
COMMIT WRITE IMMEDIATE,WAIT   : 991
COMMIT WRITE IMMEDIATE,NOWAIT : 16
PL/SQL procedure successfully completed.

--很明显commit与COMMIT WRITE WAIT一致.
 

时间: 2024-10-27 22:53:19

[20130607]PL/SQL存储过程的commit提交问题.txt的相关文章

pl sql存储过程-为后台执行加载数据 可以加载到临时表 却不能加载到表区间(调用存储过程)

问题描述 为后台执行加载数据 可以加载到临时表 却不能加载到表区间(调用存储过程) CREATE OR REPLACE PROCEDURE PRC_DET_01026_DAY( IN_DAY IN NUMBER --统计日期yyyymmdd ON_RtnCode OUT NUMBER --返回值,正确为0,错误为ORACLE的错误代码 ON_RtnMsg OUT VARCHAR2 --返回信息,正确为'NO ERROR'否则为ORACLE的出错信息 ) AS -----程序固定变量,不要修改--

PL/SQL --> 存储过程

--===================== -- PL/SQL --> 存储过程 --=====================        存储过程子程序的一种类型,能够完成一些任务,作为schema对象存储于数据库.是一个有名字的PL/SQL代码块,支持接收或不接受参数 ,同时也支持参数输出.一个存储过程通常包含定于部分,执行部分,Exception部分,可以被其他子程序调用,也可以被重用.   一.过程定义      CREATE [OR REPLACE]PROCEDURE proc

PL/SQL --> 动态SQL

--==================== -- PL/SQL --> 动态SQL --====================         使用动态SQL是在编写PL/SQL过程时经常使用的方法之一.很多情况下,比如根据业务的需要,如果输入不同查询条件,则生成不同的执行 SQL查询语句,对于这种情况需要使用动态SQL来完成.再比如,对于分页的情况,对于不同的表,必定存在不同的字段,因此使用静态SQL则只 能针对某几个特定的表来形成分页.而使用动态的SQL,则可以对不同的表,不同的字段进行

PL/SQL --> DML 触发器

--======================= -- PL/SQL --> DML 触发器 --=======================         何谓触发器?简言之,是一段命名的PL/SQL代码块,只不过该代码块在特定的条件下被触发并且执行.对于这样的代码我们称之为触发器 .触发器根据触发类型的不同又分为不同级别的触发器,下面将给出触发器的分类,定义,以及使用的示例.   一.触发器的相关概念     1.触发器的分类         通常根据触发条件以及触发级别的不同分为DM

PL/SQL --> INSTEAD OF 触发器

--============================== -- PL/SQL --> INSTEAD OF 触发器 --==============================       INSTEAD OF 触发器常用于管理编写不可更新的视图,INSTEAD-OF触发器必须是行级的.     可以用INSTEAD OF触发器来解释INSERT.UPDATE和DELETE语句,并用备用的程序代码替换那些指令.   一.不可更新视图     基于下列情形创建的视图,不可直接对其进行D

PL/SQL --> 函数

--================== -- PL/SQL --> 函数 --==================       函数通常用于返回特定的数据.其实质是一个有名字的PL/SQL块,作为一个schema对象存储于数据库,可以被反复执行.函数通常被作为 一个表达式来调用或存储过程的一个参数,具有返回值.   一.建立函数的语法     CREATE [ OR REPLACE ] FUNCTION function_name         (argument1 [mode1] data

PL/SQL -->隐式游标(SQL%FOUND)

--=============================== -- PL/SQL -->隐式游标(SQL%FOUND) --===============================       在PL/SQL中,游标的使用分为两种,一种是显示游标,一种是隐式游标,显示游标的使用需要事先使用declare来进行声明,其过程包括 声明游标,打开游标,从游标提取数据,关闭游标.该方式多用于处理select语句返回的多行数据的情形.而隐式游标则由则由系统自动定义 ,当DML被使用时,Orac

PL/SQL --> 动态SQL的常见错误

--============================ -- PL/SQL --> 动态SQL的常见错误 --============================       动态SQL在使用时,有很多需要注意的地方,如动态SQL语句结尾处不能使用分号(;),而动态PL/SQL结尾处需要使用分号(;),但不能使用正 斜杠结尾(/),以及shcema对象不能直接作为变量绑定.本文介绍了动态SQL的常见问题.   一.演示动态SQL的使用     下面的示例中,首先使用动态SQL基于sco

怪异问题!sql在pl/sql中执行结果与java jdbc执行结果不一致

问题描述 做一查询系统(struts2+myeclipse+tomcat+oracle9),一般先在pl/sql中测试sql语句,无问题后在action中使用oracle thin模式连接数据库,执行sql语句,然后将查询结果存入HashMap后输出至jsp页面.出现如下怪异问题:1.在pl/sql中测试sql语句时结果正常.结果中有6个字段,其中两个字段为count()函数统计出的数值.2.将在pl/sql中测试过的sql语句写入struts2的action中,通过jdbc thin模式执行,