1.问题出现

因业务需要,数据库中有一张表每时每刻都有数据插入,数据量比较庞大,都是些物联网数据。最近一段时间,发现在工作日周一至周五晚上10点多,和周六周日早上6点多发生数据插入失败的情况,经日志记录,在insert那张表时Oracle数据库报错:ORA-01013: 用户请求取消当前的操作。

2.问题排查

1)排除ORM框架问题

一开始是怀疑自己的ORM框架存在问题,由于我用的是C#语言,采用了SqlSugar作为ORM框架。后替换为Oracle原生框架也存在insert失败或一直等待的情况,所以排除了ORM框架问题。

2)排除SQL语句执行方式问题

不管用事务方式批量插入数据还是直接SQL语句单条插入,均存在ORA-01013问题。

3)排除操作系统问题

在问题发生时刻,在另一台计算机上执行同样的SQL语句一样报错。

3.问题定位

经测试,问题发生时,仅对那张大数据表的插入产生了报错,而别的表的插入查询均未出现问题。初步判定为那张表被锁。在数据库服务器上翻阅trace日志,发现问题产生时刻存在如下trc文件记录:

*** 2023-09-23 06:36:58.786

*** SESSION ID:(6333.24337) 2023-09-23 06:36:58.786

*** CLIENT ID:() 2023-09-23 06:36:58.786

*** SERVICE NAME:(SYS$USERS) 2023-09-23 06:36:58.786

*** MODULE NAME:(DBMS_SCHEDULER) 2023-09-23 06:36:58.786

*** ACTION NAME:(ORA$AT_OS_OPT_SY_19107) 2023-09-23 06:36:58.786

ORA-04021: timeout occurred while waiting to lock object

*** 2023-09-23 06:36:58.786

DBMS_STATS: GATHER_STATS_JOB: GATHER_TABLE_STATS('"XXX"','"XXXX"','""', ...)

DBMS_STATS: ORA-04021: timeout occurred while waiting to lock object

*** 2023-09-23 06:52:13.068

DBMS_STATS: GATHER_STATS_JOB: GATHER_TABLE_STATS('"XXX"','"XXXXX"','"XXXX"', ...)

DBMS_STATS: ORA-04021: timeout occurred while waiting to lock object

*** 2023-09-23 07:07:30.528

DBMS_STATS: GATHER_STATS_JOB: GATHER_TABLE_STATS('"XXX"','"XXXXX"','"XXXX"', ...)

DBMS_STATS: ORA-04021: timeout occurred while waiting to lock object

再登录数据库SYS账号,查询发生问题时刻执行的SQL语句,找到了:

SELECT SUM(x) FROM (SELECT CASE WHEN B != LAG(B) OVER (ORDER BY "XXX") THEN 1 ELSE 0 END x FROM (SELECT "XXX", DBMS_ROWID.ROWID_BLOCK_NUMBER(ROWID) b FROM "XX"."XXXX" WHERE ROWNUM < 1000))

正是需要插入的那张表,执行者为SYS,所以排除业务数据库XXX的定时任务等操作。

由于时间发生比较特殊,为工作日晚10点多和周末早6点多,顺着这个思路继续探索。

查询SYS的计划任务:

select window_name,repeat_interval,duration,enabled from dba_scheduler_windows;

结果:

发现了工作日和周末的执行时间。那执行的是什么,经过度娘的帮助,发现是Oracle的自动任务可能会产生ORA-04021: timeout occurred while waiting to lock object 问题。

查询自动维护任务:

select client_name,status from dba_autotask_client;

有三个任务:auto optimizer stats collection、auto space advisor、sql tuning advisor。其中第三个好像是SQL优化建议的,尝试把第三个任务关闭:

--关闭sql tuning advisor

BEGIN

DBMS_AUTO_TASK_ADMIN.disable(

client_name => 'sql tuning advisor',

operation => NULL,

window_name => NULL);

END;

至此,问题解决!!!

参考阅读

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: