数据库时oracle12c,rac环境,两个节点,服务器内存有32g,cpu多核心的,服务器及配置上应该没有问题,没有死锁,open_cursor设置为1000,配置如下:
我需要每分钟执行一次这个存储过程,但是现在每次执行都需要好长时间,处理的数据量也不是很大。
系统在oracle10g/11g下面都很正常,就是12c的rac环境下这样,实在是不知道什么原因。
哪位高人指点下,不胜感激。
7 个解决方案
#1
内存32g有点少哦,一般都在128g以上~
#2
发下你存储过程,看下代码如何?
#3
PROCEDURE autoprocuploadconsumerec
AS
out_msg VARCHAR2 (1000);
out_result NUMBER;
vplanstoptime VARCHAR2 (128);
vcount NUMBER;
visbalance NUMBER;
n_opcount NUMBER;
n_oddfare NUMBER;
n_subopcount NUMBER;
n_suboddfare NUMBER;
CURSOR c1
IS
SELECT *
FROM ( SELECT *
FROM t_xfjla
ORDER BY a.id)
WHERE ROWNUM < 800;
BEGIN
out_msg := '';
dbms_output.put_line( 'START PROCESS _CONSUME'|| to_char(SYSTIMESTAMP,'yy-mm-dd hh24:mi:ss:ff3') );
FOR c1_rec IN c1
LOOP
SELECT NVL (COUNT (*), 0)
INTO vcount
FROM base_customers a
WHERE a.customerid = c1_rec.customerid
AND a.dpid = c1_rec.dpid;
--如果为正式账户,则锁住base_customers表中的行
IF vcount > 0
THEN
SELECT a.opcount,
a.oddfare,
a.subopcount,
a.suboddfare
INTO n_opcount,
n_oddfare,
n_subopcount,
n_suboddfare
FROM base_customers a
WHERE a.customerid = c1_rec.customerid
AND a.dpid = c1_rec.dpid
FOR UPDATE OF
a.opcount, a.oddfare, a.subopcount, a.suboddfare skip locked ;
END IF;
SELECT NVL (COUNT (*), 0)
INTO vcount
FROM rec_writeoff a
WHERE a.customerid = c1_rec.customerid
AND a.dpid = c1_rec.dpid;
pkg_rec_cust_acc.processconsumerec (c1_rec.customerid,
out_msg,
out_result);
--记录处理成功,删除上传记录
DELETE rec_upload_consume
WHERE id = c1_rec.id;
dbms_output.put_line( 'END PROCESS REC_UPLOAD_CONSUME'|| to_char(SYSTIMESTAMP,'yy-mm-dd hh24:mi:ss:ff3') );
COMMIT;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK;
out_msg := out_result || '_' || out_msg || '_' || SQLERRM;
out_result := -1;
dbms_output.put_line( 'proceupdateoldflag' || OUT_MSG || to_char(SYSTIMESTAMP,'yy-mm-dd hh24:mi:ss:ff3') );
END;
我用的exec dbms_scheduler做的job自动1分钟执行一次,目前每次总超过1分钟,plsql中执行速度很快
AS
out_msg VARCHAR2 (1000);
out_result NUMBER;
vplanstoptime VARCHAR2 (128);
vcount NUMBER;
visbalance NUMBER;
n_opcount NUMBER;
n_oddfare NUMBER;
n_subopcount NUMBER;
n_suboddfare NUMBER;
CURSOR c1
IS
SELECT *
FROM ( SELECT *
FROM t_xfjla
ORDER BY a.id)
WHERE ROWNUM < 800;
BEGIN
out_msg := '';
dbms_output.put_line( 'START PROCESS _CONSUME'|| to_char(SYSTIMESTAMP,'yy-mm-dd hh24:mi:ss:ff3') );
FOR c1_rec IN c1
LOOP
SELECT NVL (COUNT (*), 0)
INTO vcount
FROM base_customers a
WHERE a.customerid = c1_rec.customerid
AND a.dpid = c1_rec.dpid;
--如果为正式账户,则锁住base_customers表中的行
IF vcount > 0
THEN
SELECT a.opcount,
a.oddfare,
a.subopcount,
a.suboddfare
INTO n_opcount,
n_oddfare,
n_subopcount,
n_suboddfare
FROM base_customers a
WHERE a.customerid = c1_rec.customerid
AND a.dpid = c1_rec.dpid
FOR UPDATE OF
a.opcount, a.oddfare, a.subopcount, a.suboddfare skip locked ;
END IF;
SELECT NVL (COUNT (*), 0)
INTO vcount
FROM rec_writeoff a
WHERE a.customerid = c1_rec.customerid
AND a.dpid = c1_rec.dpid;
pkg_rec_cust_acc.processconsumerec (c1_rec.customerid,
out_msg,
out_result);
--记录处理成功,删除上传记录
DELETE rec_upload_consume
WHERE id = c1_rec.id;
dbms_output.put_line( 'END PROCESS REC_UPLOAD_CONSUME'|| to_char(SYSTIMESTAMP,'yy-mm-dd hh24:mi:ss:ff3') );
COMMIT;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK;
out_msg := out_result || '_' || out_msg || '_' || SQLERRM;
out_result := -1;
dbms_output.put_line( 'proceupdateoldflag' || OUT_MSG || to_char(SYSTIMESTAMP,'yy-mm-dd hh24:mi:ss:ff3') );
END;
我用的exec dbms_scheduler做的job自动1分钟执行一次,目前每次总超过1分钟,plsql中执行速度很快
#4
内存好像是96g,足够用了
#5
job执行的时候,看看有没有锁,看看v$session_wait有什么等待事件
#6
一分钟执行一次为什么还要一条条记录执行,直接一批执行不就好啦?而且你这种没加监控时间,你自己都不知道你这个sql执行那一步比较慢
#7
id 有索引没有,加个索引看看! base_customers 查询慢步 ,和 pkg_rec_cust_acc.processconsumerec 又是什么过程, FOR UPDATE OF 不用可以不,加个日志运行记录临时表分段记录记录时间为毫秒,看看运行到哪个代码段慢了,就分析一下!
#1
内存32g有点少哦,一般都在128g以上~
#2
发下你存储过程,看下代码如何?
#3
PROCEDURE autoprocuploadconsumerec
AS
out_msg VARCHAR2 (1000);
out_result NUMBER;
vplanstoptime VARCHAR2 (128);
vcount NUMBER;
visbalance NUMBER;
n_opcount NUMBER;
n_oddfare NUMBER;
n_subopcount NUMBER;
n_suboddfare NUMBER;
CURSOR c1
IS
SELECT *
FROM ( SELECT *
FROM t_xfjla
ORDER BY a.id)
WHERE ROWNUM < 800;
BEGIN
out_msg := '';
dbms_output.put_line( 'START PROCESS _CONSUME'|| to_char(SYSTIMESTAMP,'yy-mm-dd hh24:mi:ss:ff3') );
FOR c1_rec IN c1
LOOP
SELECT NVL (COUNT (*), 0)
INTO vcount
FROM base_customers a
WHERE a.customerid = c1_rec.customerid
AND a.dpid = c1_rec.dpid;
--如果为正式账户,则锁住base_customers表中的行
IF vcount > 0
THEN
SELECT a.opcount,
a.oddfare,
a.subopcount,
a.suboddfare
INTO n_opcount,
n_oddfare,
n_subopcount,
n_suboddfare
FROM base_customers a
WHERE a.customerid = c1_rec.customerid
AND a.dpid = c1_rec.dpid
FOR UPDATE OF
a.opcount, a.oddfare, a.subopcount, a.suboddfare skip locked ;
END IF;
SELECT NVL (COUNT (*), 0)
INTO vcount
FROM rec_writeoff a
WHERE a.customerid = c1_rec.customerid
AND a.dpid = c1_rec.dpid;
pkg_rec_cust_acc.processconsumerec (c1_rec.customerid,
out_msg,
out_result);
--记录处理成功,删除上传记录
DELETE rec_upload_consume
WHERE id = c1_rec.id;
dbms_output.put_line( 'END PROCESS REC_UPLOAD_CONSUME'|| to_char(SYSTIMESTAMP,'yy-mm-dd hh24:mi:ss:ff3') );
COMMIT;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK;
out_msg := out_result || '_' || out_msg || '_' || SQLERRM;
out_result := -1;
dbms_output.put_line( 'proceupdateoldflag' || OUT_MSG || to_char(SYSTIMESTAMP,'yy-mm-dd hh24:mi:ss:ff3') );
END;
我用的exec dbms_scheduler做的job自动1分钟执行一次,目前每次总超过1分钟,plsql中执行速度很快
AS
out_msg VARCHAR2 (1000);
out_result NUMBER;
vplanstoptime VARCHAR2 (128);
vcount NUMBER;
visbalance NUMBER;
n_opcount NUMBER;
n_oddfare NUMBER;
n_subopcount NUMBER;
n_suboddfare NUMBER;
CURSOR c1
IS
SELECT *
FROM ( SELECT *
FROM t_xfjla
ORDER BY a.id)
WHERE ROWNUM < 800;
BEGIN
out_msg := '';
dbms_output.put_line( 'START PROCESS _CONSUME'|| to_char(SYSTIMESTAMP,'yy-mm-dd hh24:mi:ss:ff3') );
FOR c1_rec IN c1
LOOP
SELECT NVL (COUNT (*), 0)
INTO vcount
FROM base_customers a
WHERE a.customerid = c1_rec.customerid
AND a.dpid = c1_rec.dpid;
--如果为正式账户,则锁住base_customers表中的行
IF vcount > 0
THEN
SELECT a.opcount,
a.oddfare,
a.subopcount,
a.suboddfare
INTO n_opcount,
n_oddfare,
n_subopcount,
n_suboddfare
FROM base_customers a
WHERE a.customerid = c1_rec.customerid
AND a.dpid = c1_rec.dpid
FOR UPDATE OF
a.opcount, a.oddfare, a.subopcount, a.suboddfare skip locked ;
END IF;
SELECT NVL (COUNT (*), 0)
INTO vcount
FROM rec_writeoff a
WHERE a.customerid = c1_rec.customerid
AND a.dpid = c1_rec.dpid;
pkg_rec_cust_acc.processconsumerec (c1_rec.customerid,
out_msg,
out_result);
--记录处理成功,删除上传记录
DELETE rec_upload_consume
WHERE id = c1_rec.id;
dbms_output.put_line( 'END PROCESS REC_UPLOAD_CONSUME'|| to_char(SYSTIMESTAMP,'yy-mm-dd hh24:mi:ss:ff3') );
COMMIT;
END LOOP;
EXCEPTION
WHEN OTHERS
THEN
ROLLBACK;
out_msg := out_result || '_' || out_msg || '_' || SQLERRM;
out_result := -1;
dbms_output.put_line( 'proceupdateoldflag' || OUT_MSG || to_char(SYSTIMESTAMP,'yy-mm-dd hh24:mi:ss:ff3') );
END;
我用的exec dbms_scheduler做的job自动1分钟执行一次,目前每次总超过1分钟,plsql中执行速度很快
#4
内存好像是96g,足够用了
#5
job执行的时候,看看有没有锁,看看v$session_wait有什么等待事件
#6
一分钟执行一次为什么还要一条条记录执行,直接一批执行不就好啦?而且你这种没加监控时间,你自己都不知道你这个sql执行那一步比较慢
#7
id 有索引没有,加个索引看看! base_customers 查询慢步 ,和 pkg_rec_cust_acc.processconsumerec 又是什么过程, FOR UPDATE OF 不用可以不,加个日志运行记录临时表分段记录记录时间为毫秒,看看运行到哪个代码段慢了,就分析一下!