ITPub博客

首页 > 数据库 > Oracle > [20201111]PL SQL function 和一致性.txt

[20201111]PL SQL function 和一致性.txt

原创 Oracle 作者:lfree 时间:2020-11-11 09:37:13 0 删除 编辑

[20201111]PL SQL function 和一致性.txt

--//每当从SQL查询中调用PL/SQL函数时,函数中的每个查询都与其开始的SCN一致,而不是与父查询的SCN一致。
--//通过一个例子说明:

1.环境:
SCOTT@book> @ ver1
PORT_STRING                    VERSION        BANNER
------------------------------ -------------- --------------------------------------------------------------------------------
x86_64/Linux 2.4.xx            11.2.0.4.0     Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production

create table test as select level a, level b from dual connect by level<=10;

create or replace function f1(a int) return int as
  res int;
begin
  select b into res
  from test t
  where t.a=f1.a;
  dbms_lock.sleep(1);
  return res;
end;
/

/* Formatted on 2020/11/11 9:21:28 (QP5 v5.269.14213.34769) */
CREATE OR REPLACE FUNCTION SCOTT.f1x (x INT)
   RETURN INT
   DETERMINISTIC
AS
   res   INT;
BEGIN
   SELECT b
     INTO res
     FROM test t
    WHERE t.a = x;

   DBMS_LOCK.sleep (1);
   RETURN res;
END;
/

SCOTT@book> set timing on
SCOTT@book> select t.*, f1(a) func from test t;
         A          B       FUNC
---------- ---------- ----------
         1          1          1
         2          2          2
         3          3          3
         4          4          4
         5          5          5
Elapsed: 00:00:05.01

--//查询时函数f1的查询结果与B字段对应。

2.测试:
$ cat abc.sql
begin
    for i in 1..10 loop
      update test set b=b+1;
      commit;
      dbms_lock.sleep(1);
    end loop;
end;
/

--// session 2:加入在修改test的同时,执行上面的查询呢?
SCOTT@book> @ abc.sql
PL/SQL procedure successfully completed.

--//马上切换到session 1,执行如下:
SCOTT@book> select t.*, f1(a) func from test t;
         A          B       FUNC
---------- ---------- ----------
         1          4          4
         2          5          6
         3          6          8
         4          7         10
         5          8         12
Elapsed: 00:00:05.00

--//你可以发现字段B与调用函数f1(a)的值不一致。越往后相差越大。
--//也就是当执行select t.*, f1(a) func from test t;时 oracle是访问那个时刻的SCN的信息,而函数调用时的scn信息不一致。
--//使用f1x函数也是一样。
--//这样就导致这样的情况出现,这种情况实际上也可以在正常的业务系统出现。

--//如何保证一致呢?执行如下:
CREATE OPERATOR f1_op
   BINDING (INT)
   RETURN INT
   USING F1;

--//这样可以保证调用函数f1_op时与查询时scn一致。

SCOTT@book> update test set b=a;
5 rows updated.
Elapsed: 00:00:00.01

SCOTT@book> commit ;
Commit complete.
Elapsed: 00:00:00.00

--//session 2:
SCOTT@book> @ abc.sql
PL/SQL procedure successfully completed.

--//session 1:
SCOTT@book> select t.*, f1(a) func,f1_op(a) op from test t;
         A          B       FUNC         OP
---------- ---------- ---------- ----------
         1          3          3          3
         2          4          6          4
         3          5          9          5
         4          6         12          6
         5          7         15          7
Elapsed: 00:00:10.02

--//问一下,有多少人知道CREATE OPERATOR这样的操作。我个人不主张开发使用自定义的函数的。

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/267265/viewspace-2733419/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
熟悉oracle相关技术,擅长sql优化,rman备份与恢复,熟悉linux shell编程。

注册时间:2008-01-03

  • 博文量
    4006
  • 访问量
    7969436