• 记一次Oracle数据故障排除过程


    前天在Oracle生产环境中,自己的存储过程运行时间超过1小时,怀疑是其他job运行时间过长推迟了自己job运行时间,遂重新跑job,发现同测试环境的确不同,运行了25分钟。

    之后准备在测试环境中制造同数量级的数据进行分析,写了大概如下的存储过程,

    create or replace PROCEDURE PERFORMANCE_TEST AS 
    
    v_date date;
    v_start_date date;
    v_end_date date;
    v_start_date_str varchar2(10) := '2017-01-31';
    v_end_date_str varchar2(10) := '2017-07-31';
    v_date_str varchar2(10);
    
    BEGIN
      v_start_date := to_date(v_start_date_str, 'yyyy-mm-dd');
      v_end_date := to_date(v_end_date_str, 'yyyy-mm-dd');
      v_date := v_start_date;
      while v_date < v_end_date loop
        v_date_str := to_char(v_date, 'yyyy-mm-dd');
        insert into datacore.df_customer_static_report
        (
          data_date,
          cty_code,
          party_id,
          party_name,
          ho_domicile_cty,
          rm_code,
          rm_name,
          business_division
        )(
          select 
            v_date_str,
            cty_code,
            party_id,
            party_name,
            ho_domicile_cty,
            rm_code,
            rm_name,
            business_division
          from datacore.df_customer_static_report
          where data_date = v_end_date_str
        );
        commit;
      end loop;
      
    END PERFORMANCE_TEST;

    犯了个致命错误,丢了v_date := v_date + 1; 存储过程陷入无限循环!在过了1个多小时后,意识到不对劲,遂查询了数据量,发现2017-01-31的数据量竟然达到了千万级。。。赶紧停止运行找原因,才发现无限循环插入数据。

    剩下就是怎么删掉这些数据,毕竟千万级的数据占据存储空间太大了。简单的删除肯定不起作用,遂尝试分批删除,先试着删除1w条,结果运行很长时间后还是没有结束。这个时候,感觉之前那个无限循环应该还没有结束,在后台还在运行。因为其他事情捣乱,没来得及修正这个问题。第二天来,再次查询,发现数据量达到了快5千万条,欲哭无泪啊!赶紧删数据,分批次,1百万条的删,(这次加上累加条件了)

    create or replace PROCEDURE DELETE_TEMP AS 
    
    v_number number := 1;
    v_number_end number := 50;
    
    BEGIN
    
      while v_number <= v_number_end loop
        delete from datacore.df_customer_static_report nologging
        where data_date = '2017-01-31'
        and rownum < 1000000;
        commit;
        v_number := v_number + 1;
        dbms_output.put_line(v_number || ' end');
      end loop;
      
    END DELETE_TEMP;

    本想用TRUNCATE把所有数据都删掉,但是我这里只需要删掉表中‘2017-01-31’的数据,而且只是把千万条降低到万条。查了delete语句的优化,发现加上nologging会更快些(数据不做恢复)。

    运行了大概1个小时后,感觉差不多了,遂手动终止了delete的运行。再次查询,‘2017-01-31’的数据降到9千多条。窃喜~

    不过又想起昨天想到的“是否无限循环还在后台运行”?过了10几分钟后查询,发现数据又多了,欲哭无泪。。

    怎么让这个讨厌的无限循环终止呢?因为使用的账号没有dba权限,所以想通过更改表的结构,让包含无限循环的存储过程异常终止。但估计不可行,因为数据库表一直被占用了。抱着试一试的想法,执行以下sql,

    alter table datacore.df_customer_static_report
    drop column rds_spread_code

    报错“资源正忙, 但指定以 NOWAIT 方式获取资源, 或者超时失效;resource busy and acquire with NOWAIT specified”。

    搜索后,果真有解决方案 - here,但还是需要dba权限(厚脸皮要吧)。

    1. 用dba权限的用户查看数据库都有哪些锁

    SELECT T2.USERNAME,T2.SID,T2.SERIAL#,T2.LOGON_TIME
    FROM V$LOCKED_OBJECT T1,V$SESSION T2
    WHERE T1.SESSION_ID=T2.SID ORDER BY T2.LOGON_TIME;

    2. 根据sid查看具体的sql语句,如果sql不重要,可以kill

    SELECT SQL_TEXT FROM V$SESSION A,V$SQLTEXT_WITH_NEWLINES B
    WHERE DECODE(A.SQL_HASH_VALUE, 0, PREV_HASH_VALUE, SQL_HASH_VALUE)=B.HASH_VALUE
    AND A.SID=&SID ORDER BY PIECE;

    3. kill该事务

    ALTER SYSTEM KILL SESSION '590,20839';

    4. 再次查看数据库锁,发现锁消失。再次查询表数据,不再增加。

    教训:以后写存储过程中的循环,千万注意条件的累加!

    --------------------------------------------------------------------------------------------------------------------------------

    -- index(索引)
    select * from all_indexes;
    select * from user_indexes;

    select * from all_ind_columns;
    select * from user_ind_columns;

    select t.*,i.index_type
    from user_ind_columns t,user_indexes i
    where t.index_name = i.index_name
    and t.table_name = i.table_name and t.table_name = 'DM_RR_GQ_FIN_FEDS';

    select t.*,i.index_type
    from all_ind_columns t,all_indexes i
    where t.index_name = i.index_name
    and t.table_name = i.table_name
    and owner = 'FISP'
    and t.table_name = 'FIS_OUT_FLEXI';

    -- tables(表)
    select * from user_tab_columns;
    select * from all_tab_columns;

    select * from user_col_comments;
    select * from all_col_comments;

    select * from user_tables;
    select * from all_tables;

  • 相关阅读:
    nginx Server names
    ES6--变量的声明及解构赋值
    Android ListView and Tips.
    Eclipse自己定义keystore
    POJ 1129 Channel Allocation(DFS)
    机器学习笔记十三:Ensemble思想(上)
    设计模式——享元模式具体解释
    老猪带你玩转自定义控件三——sai大神带我实现ios 8 时间滚轮控件
    老猪带你玩转android自定义控件二——自定义索引栏listview
    android动手写控件系列——老猪叫你写相机
  • 原文地址:https://www.cnblogs.com/hello-yz/p/9923057.html
Copyright © 2020-2023  润新知