-----正文-----
本文就DM存储过程问题的排查方法进行简单介绍,主要针对打印错误代码信息和存储过程SQL耗时长的定位方法进行测试验证。
本章内容已在如下环境上测试:
操作系统:银河麒麟V10
数据库:DM8
相关关键字:DM8,存储过程
在DM数据库存储过程的调试执行过程中,会遇到异常错误无法准确定位的问题,这就造成无法及时准确地对错误进行修改。有没有方法来快速来定位错误的原因呢?答案是肯定的,本文通过实例进行测试,供大家参考使用。
1.1、 创建字段类型为数据类型的表
CREATE TABLE "TEST"."DMTEST01" ("ID" INT) ;
1.2、创建异常记录日志表
CREATE TABLE "TEST"."T_PROC_ERRMSG"
(
"SQLCODE" VARCHAR(50) ,
"SQLERRM" VARCHAR(200),
"EXECDATE" DATETIME(6)
);
1.3、 存储过程应用示例
create or replace
procedure test.pr_error_code_test
(
TEST in varchar2)
is
declare begin
insert into TEST.DMTEST01
(id
) values
(TEST
);
commit;
--异常错误记录处理
exception
when others then
insert into TEST.T_PROC_ERRMSG values
( sqlcode, sqlerrm, SYSDATE
);
print sqlcode;
print sqlerrm;
commit;
return;
end;
/
1.4、执行存储过程(将参数设置为字符串)
call "TEST"."PR_ERROR_CODE_TEST"('a');
1.5、查看异常记录信息
select * from "TEST"."T_PROC_ERRMSG";
通过以上方法可以定位到存储过程的错误信息。
存储过程的调试一直很令人头疼,因为里面的动态 SQL 和程序逻辑让人很难上手,所以我们建议他们将 EXECUTE IMMEDIATE 做一次分装,即把执行 SQL 的函数进行封装,函数里记录上我们需要的信息。
2.1、创建日志记录信息表
CREATE TABLE TEST.SQL_TRACE
(
LOG_NO INT IDENTITY(1, 1),
USER_NAME VARCHAR ,
BEGIN_TIME DATE ,
END_TIME DATE ,
SQL_STR VARCHAR ,
ROW_COUNT INT ,
SESSION_ID BIGINT ,
IP_ADDRESS VARCHAR ,
CALL_STACK VARCHAR ,
TIMES INT
);
2.2、创建存储过程方法
CREATE OR REPLACE
PROCEDURE EXECSQL
(
I_SQLSTRING IN VARCHAR2)
AS
V_ROWNUMID INTEGER;
V_TIME DATE;
V_SQLSTRING VARCHAR2(32767);
V_SQL VARCHAR2(8188);
V_CURTIME NUMBER(20, 2);
V_USETIME NUMBER(20, 2);
V_SID NUMBER(30);
V_SES V$SESSIONS%ROWTYPE;
V_CALL_STACK VARCHAR2(4000);
BEGIN
V_TIME :=SYSDATE;
V_CURTIME :=DBMS_UTILITY.GET_TIME;
V_SQLSTRING :=TRIM(I_SQLSTRING);
--去除SQL语句多余的空格
WHILE INSTR(V_SQLSTRING, ' ')>0
LOOP
V_SQLSTRING:=REPLACE(V_SQLSTRING, ' ', ' ');
END LOOP;
--执行SQL语句
EXECUTE IMMEDIATE V_SQLSTRING;
V_ROWNUMID :=SQL%ROWCOUNT;
V_USETIME :=(DBMS_UTILITY.GET_TIME-V_CURTIME)/100;
--运行时间超过0.5秒,记录语句日志
IF V_USETIME >=0.5 THEN
V_SQL :=TRIM(SUBSTRB(V_SQLSTRING, 1, 4000));
V_SID := SYS_CONTEXT('USERENV', 'SID');
V_CALL_STACK:=DBMS_UTILITY.FORMAT_CALL_STACK;
INSERT
INTO
SQL_TRACE
(
USER_NAME ,
BEGIN_TIME,
END_TIME ,
SQL_STR ,
ROW_COUNT ,
SESSION_ID,
IP_ADDRESS,
CALL_STACK,
TIMES
)
VALUES
(
SYS_CONTEXT('USERENV', 'CURRENT_SCHEMA'),
V_TIME ,
SYSDATE ,
V_SQL ,
V_ROWNUMID ,
V_SID ,
SYS_CONTEXT('USERENV', 'IP_ADDRESS') ,
V_CALL_STACK ,
V_USETIME
);
commit;
END IF;
END EXECSQL;
2.3、创建存储过程测试方法
CREATE OR REPLACE
PROCEDURE "TEST"."PR_ERROR_CODE_TEST" AUTHID DEFINER
is
declare
begin
call "TEST"."EXECSQL"('delete from "TEST"."DMTEST01" where id>10;');
exception
when others then
insert into TEST.T_PROC_ERRMSG values
( sqlcode, sqlerrm, SYSDATE
);
print sqlcode;
print sqlerrm;
commit;
end;
2.4、执行测试
call "TEST"."PR_ERROR_CODE_TEST"();
2.5、结果展示
执行后的记录结果:
表中记录了登录用户、开始时间、结束时间、影响行数、SESSID、IP 和存储过程的 TRACE BACK,里面记录了查询发生在哪个存储过程的哪一行:
EXECSQL:表示调用EXECSQL方法的第29行。
PR_ERROR_CODE_TEST:表示该存储过程中第7行SQL语句。
通过以上的方法我们就可以清楚的定位到具体执行的 SQL 和 SQL 执行耗时。
>>> THE END <<<
相关推荐
文章转载自达梦E学,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。