PL/SQL精明的调用栈分析

原文:http://www.oracle.com/technetwork/issue-archive/2014/14-jan/o14plsql-2045346.html

The three DBMS_UTILITY functions

(DBMS_UTILITY.FORMAT_CALL_STACK, DBMS_UTILITY.FORMAT_ERROR_STACK, and DBMS_UTILITY.FORMAT_ERROR_ BACKTRACE) have been crucial aids in diagnosing and resolving problems in PL/SQL code. The UTL_CALL_STACK package recognizes the importance of this data and takes a big step forward in giving PL/SQL developers access to more in-depth and useful information

12C以前的3个工具函数(DBMS_UTILITY.FORMAT_CALL_STACK,DBMS_UTILITY.FORMAT_ERROR_STACK,DBMS_UTILITY.FORMAT_ERROR_ BACKTRACE)

已经给PL/SQL程序分析和问题解决提供了关键的帮助。

12C开始引入的UTL_CALL_STACK包意识到改类数据的重要性并进一步增强以使PL/SQL开发者可以获得更多深层次的有用的信息。

–调用栈 Call Stacks :DBMS_UTILITY.FORMAT_CALL_STACK

回答了 “How did I get here?” ,我是怎么一步一步到达这里的?例如:

SQL> CREATE OR REPLACE PROCEDURE proc1
  2  IS
  3  BEGIN
  4     DBMS_OUTPUT.put_line (DBMS_UTILITY.format_call_stack);
  5  END;
  6  /

SQL> CREATE OR REPLACE PACKAGE pkg1
  2  IS
  3     PROCEDURE proc2;
  4  END pkg1;
  5  /

SQL> CREATE OR REPLACE PACKAGE BODY pkg1
  2  IS
  3     PROCEDURE proc2
  4     IS
  5     BEGIN
  6        proc1;
  7     END;
  8  END pkg1;
  9  /

SQL> CREATE OR REPLACE PROCEDURE proc3
  2  IS
  3  BEGIN
  4     FOR indx IN 1 .. 1000
  5     LOOP
  6        NULL;
  7     END LOOP;
  8
  9     pkg1.proc2;
 10  END;
 11  /

SQL> BEGIN
  2     proc3;
  3  END;
  4  /

——————— PL/SQL Call Stack ———————

object handle line number object name

000007FF7EA83240 4 procedure HR.PROC1

000007FF7E9CC3B0 6 package body HR.PKG1

000007FF7EA0A3B0 9 procedure HR.PROC3

000007FF7EA07C00 2 anonymous block

–弊端:

If you call a subprogram in a package, the formatted call stack will show only the package name, not the subprogram name and certainly not the names of nested subprograms defined within that packaged subprogram.

如果我们调用包中的子程序,那么此函数只能显示报名,压根不会显示子程序的名称更别提嵌套子程序的名称了。

If you simply want the name of the most recently executed subprogram, you will have to parse the string. This is not hard to do, but it’s more code that you have to write and maintain.

如果我们仅仅想看下最近执行的子程序名称,还得去解析冗长的字符串。虽然这并不是难事,但无疑加重了开发者的负担。

The object handle value is, for all practical purposes, “noise.” PL/SQL developers—outside of Oracle, at least—never use it.

object handle值是个鸡肋,无实际用途。

–错误栈 Error Stacks :DBMS_UTILITY.FORMAT_ERROR_STACK Similar to SQLERRM

The DBMS_UTILITY.FORMAT_ERROR_STACK function differs from SQLERRM in two ways:

It can return an error message as long as 1,899 characters, thereby avoiding (or at least making extremely unlikely) truncation issues when the error stack gets long. (SQLERRM truncates at only 510 characters.)

You cannot pass an error code number to this function, and it cannot be used to return the message for an error code.

–错误回溯 Error Backtraces :DBMS_UTILITY.FORMAT_ERROR_BACKTRACE

returns a formatted string that displays a stack of programs and line numbers tracing back to the line on which the error was originally raised.

12c: UTL_CALL_STACK package

Name Description

BACKTRACE_DEPTH Returns the number of backtrace items in the backtrace

BACKTRACE_LINE Returns the line number of the unit at the specified backtrace depth

BACKTRACE_UNIT Returns the name of the unit at the specified backtrace depth

CONCATENATE_SUBPROGRAM Returns a concatenated form of a unit-qualified name

DYNAMIC_DEPTH Returns the number of subprograms in the call stack, including SQL, Java, and other non-PL/SQL contexts invoked along the way—for example, if A calls B calls C calls B, this stack, written as a line with dynamic depths underneath it, will look like this:

A B C B

4 3 2 1

ERROR_DEPTH Returns the number of errors in the call stack

ERROR_MSG Returns the error message of the error at the specified error depth

ERROR_NUMBER Returns the error number of the error at the specified error depth

LEXICAL_DEPTH Returns the lexical nesting level of the subprogram at the specified dynamic depth

OWNER Returns the owner name of the unit of the subprogram at the specified dynamic depth

UNIT_LINE Returns the line number of the unit of the subprogram at the specified dynamic depth

SUBPROGRAM Returns the unit-qualified name of the subprogram at the specified dynamic depth

SQL> CREATE OR REPLACE PROCEDURE format_call_stack_12c
  2  IS
  3  BEGIN
  4     DBMS_OUTPUT.put_line (
  5        ‘LexDepth Depth LineNo Name‘);
  6     DBMS_OUTPUT.put_line (
  7        ‘-------- ----- ------ ----‘);
  8
  9     FOR the_depth IN REVERSE 1 ..
 10                          utl_call_stack.dynamic_depth ()
 11     LOOP
 12        DBMS_OUTPUT.put_line (
 13              RPAD (
 14                 utl_call_stack.lexical_depth (
 15                    the_depth),
 16                 9)
 17           || RPAD (the_depth, 5)
 18           || RPAD (
 19                 TO_CHAR (
 20                    utl_call_stack.unit_line (
 21                       the_depth),
 22                    ‘99‘),
 23                 8)
 24           || utl_call_stack.concatenate_subprogram (
 25                 utl_call_stack.subprogram (
 26                    the_depth)));
 27     END LOOP;
 28  END;
 29  /

 SQL> CREATE OR REPLACE PACKAGE pkg
  2  IS
  3     PROCEDURE do_stuff;
  4  END;
  5  /

SQL> CREATE OR REPLACE PACKAGE BODY pkg
  2  IS
  3     PROCEDURE do_stuff
  4     IS
  5        PROCEDURE np1
  6        IS
  7           PROCEDURE np2
  8           IS
  9              PROCEDURE np3
 10              IS
 11              BEGIN
 12                 format_call_stack_12c;
 13              END;
 14           BEGIN
 15              np3;
 16           END;
 17        BEGIN
 18           np2;
 19        END;
 20     BEGIN
 21        np1;
 22     END;
 23  END;
 24  /

SQL> BEGIN
  2     pkg.do_stuff;
  3  END;
  4  /

LexDepth Depth LineNo Name

——————— ——————— ———————— ——————————————————————————

0 6 2 __anonymous_block

1 5 21 PKG.DO_STUFF

2 4 18 PKG.DO_STUFF.NP1

3 3 15 PKG.DO_STUFF.NP1.NP2

4 2 12 PKG.DO_STUFF.NP1.NP2.NP3

0 1 12 FORMAT_CALL_STACK_12C

SQL> CREATE OR REPLACE FUNCTION backtrace_to
  2     RETURN VARCHAR2
  3  IS
  4  BEGIN
  5     RETURN
  6        utl_call_stack.backtrace_unit (
  7           utl_call_stack.error_depth)
  8        || ‘ line ‘
  9        ||
 10        utl_call_stack.backtrace_line (
 11           utl_call_stack.error_depth);
 12  END;
 13  /

SQL> CREATE OR REPLACE PACKAGE pkg1
  2  IS
  3     PROCEDURE proc1;
  4     PROCEDURE proc2;
  5  END;
  6  /

SQL> CREATE OR REPLACE PACKAGE BODY pkg1
  2  IS
  3     PROCEDURE proc1
  4     IS
  5        PROCEDURE nested_in_proc1
  6        IS
  7        BEGIN
  8           RAISE VALUE_ERROR;
  9        END;
 10     BEGIN
 11        nested_in_proc1;
 12     END;
 13
 14     PROCEDURE proc2
 15     IS
 16     BEGIN
 17        proc1;
 18     EXCEPTION
 19        WHEN OTHERS THEN RAISE NO_DATA_FOUND;
 20     END;
 21  END pkg1;
 22  /

SQL> CREATE OR REPLACE PROCEDURE proc3
  2  IS
  3  BEGIN
  4     pkg1.proc2;
  5  END;
  6  /

SQL> BEGIN
  2     proc3;
  3  EXCEPTION
  4     WHEN OTHERS
  5     THEN
  6        DBMS_OUTPUT.put_line (backtrace_to);
  7  END;
  8  /

HR.PKG1 line 19

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-29 07:39:45

PL/SQL精明的调用栈分析的相关文章

Android群英传笔记——第八章:Activity与Activity调用栈分析

Android群英传笔记--第八章:Activity与Activity调用栈分析 开篇,我们陈述一下Activity,Activity是整个应用用户交互的核心组件,了解Activity的工作模式,生命周期和管理方式,是了解Android的基础,本节主讲 Activity的生命周期与工作模式 Activity调用栈管理 一.Activity Activity作为四大组建出现平率最高的组件,我们在哪里都能看到他,就让我们一起先来了解一下他的生命周期 1.起源 Activity是用户交互的第一接口,他

第四章 Activity和Activity调用栈分析 系统信息与安全机制 性能优化

1.Activity生命周期理解生命周期就是两张图:第一张图是回字型的生命周期图第二张图是金字塔型的生命周期图 注意点(1)从stopped状态重新回到前台状态的时候会先调用onRestart方法,然后再调用后续的onStart等方法:(2)启动另一个Activity然后finish,先调用旧Activity的onPause方法,然后调用新的Activity的onCreate->onStart->onResume方法,然后调用旧Activity的onStop->onDestory方法.如

Android群英传知识点回顾——第八章:Activity与Activity调用栈分析

8.1 Activity 8.1.1 起源 8.1.2 Activity形态 8.1.3 生命周期 8.2 Activity任务栈简介 8.3 ActivityManifest启动模式 8.3.1 standard 8.3.2 singleTop 8.3.3 singleTask 8.3.4 singleInstance 8.4 Intent Flag启动模式 8.5 清空任务栈 8.6 Activity任务栈使用 四大组件中出现频率最高的组件 Activity是与用户交互的第一接口,它提供了一

x86架构调用栈分析

以一个简单求阶乘的代码为例: 1 #include <stdio.h> 2 3 unsigned int fact(unsigned int n) 4 { 5 if (n == 0) 6 return 1; 7 return n * fact(n - 1); 8 } 9 10 int main(void) 11 { 12 int c = 0; 13 14 c = fact(5); 15 16 return c; 17 } 1 void mbacktrace(int fps[], int n)

PL/SQL数据库开发那点事

PL/SQL数据库开发那点事-->编程,存储程序 在SQL*plus 中编写PL/SQL程序,并在SQL*plus 中执行它, PL/SQL块的代码就存放在SQL*plus的缓冲区中.如果在SQL*plus 中执行了其他的SQL语句或PL/SQL块,缓冲区中就会存放新的代码,原来的PL/SQL块就会被从缓冲区中清除出去.这种没有名称只是临时存放在缓冲区中的PL/SQL块叫做匿名块.匿名块就是没有名字的PL/SQL块,它仅存放在缓冲区中,只能在当前SQL*plus环境中执行.如果希望PL/SQL块

每周一书《Oracle 12 c PL(SQL)程序设计终极指南》

本周为大家送出的书是<Oracle 12 c PL(SQL)程序设计终极指南>,此书由机械工业出版社出版, 孙风栋,王澜,郭晓惠 著. 内容简介: <Oracle 12c PL/SQL程序设计终极指南>志在打造PL/SQL领域最为系统.全面.实战.权威的著作,通过一系列非常突出的优势在大量的同类书中脱颖而出,成为该领域的标准读物. PL/SQL本身涉及的知识点浩瀚.庞杂,初学者根本无法依靠自身能力理清头绪,学习成本极高.本书对知识点进行了体系化的梳理,化繁杂为有序,突出重点,直指核

【转】Oralce PL/SQL 堆栈信息追踪

总结如下: DBMS_UTILITY.FORMAT_CALL_STACK - 这是在Oracle7中引入的,DBMS_UTILITY.FORMAT_CALL_STACK这个内置函数返回一个格式化的字符串,它显示了执行调用堆栈:直至此函数的调用点处的所有过程或者函数的调用顺序.换句话说,这个函数回答了这个问题:"我是怎么来到这里的?" DBMS_UTILITY.FORMAT_ERROR_STACK - 这是在Oracle7中引入的,DBMS_UTILITY.FORMAT_ERROR_ST

ORACLE PL/SQL 中序列(sequence)的简易使用方法介绍

如果我是C罗 原文 ORACLE PL/SQL 中序列(sequence)的简易使用方法介绍 sequence在ORACLE中应用十分广泛,就是序列号的意思,会自动增加指定变数,如逐次增加1或者2或者其他. 1.创建序列 Create Sequence 你首先要有CREATE SEQUENCE或者CREATE ANY SEQUENCE 权限 CREATE SEQUENCE CUX_DEMO_SEQUENCEMINVALUE 1MAXVALUE 99999999999START WITH 1000

2015/8/17笔记整理 第12章 PL/SQL编程简介1 块 过程 函数

Oracle数据库中包含一种过程化编程语言PL/SQL,PL/SQL是ORACLE对标准数据库语言的扩展. 一.PL/SQL的优点 PL/SQL 不是一个独立的产品,他是一个整合到ORACLE服务器和ORACLE工具中的技术,可以把PL/SQL看作ORACLE服务器内的一个引擎,sql语句执行者处理单个的sql语句,PL/SQL引擎处理PL/SQL程序块.当PL/SQL程序块在PL/SQL引擎处理时,ORACLE服务器中的SQL语句执行器处理pl/sql程序块中的SQL语句. PL/SQL语句—