Oracle查找引起归档日志暴增的SQL语句

2023年 10月 26日 82.6k 0

一、新建表,模拟数据变更

1、新建三个表

CREATE TABLE t1 (
id NUMBER,
name VARCHAR2(200),
info VARCHAR2(200),
row_create_time TIMESTAMP,
row_lastupdate_time TIMESTAMP
);

CREATE TABLE t2 (
id NUMBER,
name VARCHAR2(200),
info VARCHAR2(200),
row_create_time TIMESTAMP,
row_lastupdate_time TIMESTAMP
);

CREATE TABLE t3 (
id NUMBER,
name VARCHAR2(200),
info VARCHAR2(200),
row_create_time TIMESTAMP,
row_lastupdate_time TIMESTAMP
);

2、初始化数据

-- 使用循环插入数据,每10000条数据提交一次
DECLARE
commit_count NUMBER := 0;
BEGIN
FOR i IN 1..50000 LOOP
INSERT INTO t1 (id, name, info, row_create_time, row_lastupdate_time)
VALUES (i, 't1_' || i, 'info ' || i, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

INSERT INTO t2 (id, name, info, row_create_time, row_lastupdate_time)
VALUES (i, 't2_' || i, 'info ' || i, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

INSERT INTO t3 (id, name, info, row_create_time, row_lastupdate_time)
VALUES (i, 't3_' || i, 'info ' || i, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP);

commit_count := commit_count + 1;

IF commit_count = 10000 THEN
COMMIT;
commit_count := 0;
END IF;
END LOOP;
COMMIT;
END;

3、编写存储过程执行update 或者 delete

CREATE OR REPLACE PROCEDURE update_or_delete_data (
p_action VARCHAR2,
p_table_name VARCHAR2,
p_total_rows NUMBER,
p_commit_interval NUMBER
) AS
v_counter NUMBER := 0;
v_start_time TIMESTAMP := CURRENT_TIMESTAMP;

BEGIN
IF p_action = 'update' THEN
-- 执行更新操作
WHILE v_counter < p_total_rows LOOP
EXECUTE IMMEDIATE 'UPDATE ' || p_table_name || '
SET name = ''Updated Name '' || DBMS_RANDOM.VALUE,
info = ''Updated Info '' || DBMS_RANDOM.VALUE,
row_lastupdate_time = CURRENT_TIMESTAMP
WHERE id = :id' USING v_counter + 1;

v_counter := v_counter + 1;

IF MOD(v_counter, p_commit_interval) = 0 THEN
COMMIT;
END IF;
END LOOP;

ELSIF p_action = 'delete' THEN
-- 执行删除操作
WHILE v_counter < p_total_rows LOOP
EXECUTE IMMEDIATE 'DELETE FROM ' || p_table_name || '
WHERE id = :id' USING v_counter + 1;

v_counter := v_counter + 1;

IF MOD(v_counter, p_commit_interval) = 0 THEN
COMMIT;
END IF;
END LOOP;
ELSE
DBMS_OUTPUT.PUT_LINE('Invalid action. Use "update" or "delete" as the first parameter.');
END IF;

COMMIT;

-- 计算总耗时并输出信息
DBMS_OUTPUT.PUT_LINE('Total Elapsed Time: ' || (CURRENT_TIMESTAMP - v_start_time));
DBMS_OUTPUT.PUT_LINE('Table: ' || p_table_name || ', Action: ' || p_action || ', Total Rows Changed: ' || p_total_rows);
END;
/

4、执行存储过程,模拟数据变更

-- 调用存储过程来执行更新操作,更新表t1中的10000行,每1000行提交一次
call update_or_delete_data('update', 't1', 10000, 1000);

-- 调用存储过程来执行删除操作,删除表t2中的20000行,每2000行提交一次
call update_or_delete_data('delete', 't2', 20000, 2000);

二、查询归档日志暴增的三种方法

  • 根据SQL查询
  • 根据AWR定位
  • 根据dbms_logmnr挖掘归档日志

--第一种方法,根据SQL查询

1、查询最近三个小时的DML变更

with aa as
(SELECT IID,
USERNAME,
to_char(BEGIN_TIME,'mm/dd hh24:mi') begin_time,
SQL_ID,
decode(COMMAND_TYPE,3,'SELECT',2,'INSERT',6,'UPDATE',7,'DELETE',189,'MERGE INTO','OTH') "SQL_TYPE",
executions "EXEC_NUM",
rows_processed "Change_NUM"
FROM (SELECT s.INSTANCE_NUMBER IID,
PARSING_SCHEMA_NAME USERNAME,COMMAND_TYPE,
cast(BEGIN_INTERVAL_TIME as date) BEGIN_TIME,
s.SQL_ID,
executions_DELTA executions,
rows_processed_DELTA rows_processed,
(IOWAIT_DELTA) /
1000000 io_time,
100*ratio_to_report(rows_processed_DELTA) over(partition by s.INSTANCE_NUMBER, BEGIN_INTERVAL_TIME) RATIO,
sum(rows_processed_DELTA) over(partition by s.INSTANCE_NUMBER, BEGIN_INTERVAL_TIME) totetime,
elapsed_time_DELTA / 1000000 ETIME,
CPU_TIME_DELTA / 1000000 CPU_TIME,
(CLWAIT_DELTA+APWAIT_DELTA+CCWAIT_DELTA+PLSEXEC_TIME_DELTA+JAVEXEC_TIME_DELTA)/1000000 OTIME,
row_number() over(partition by s.INSTANCE_NUMBER,BEGIN_INTERVAL_TIME order by rows_processed_DELTA desc) TOP_D
FROM dba_hist_sqlstat s, dba_hist_snapshot sn,dba_hist_sqltext s2
where s.snap_id = sn.snap_id
and s.INSTANCE_NUMBER = sn.INSTANCE_NUMBER
and rows_processed_DELTA is not null
and s.sql_id = s2.sql_id and COMMAND_TYPE in (2,6,7,189)
and sn.BEGIN_INTERVAL_TIME > sysdate - nvl(180,1)/1440 and PARSING_SCHEMA_NAME'SYS')
WHERE TOP_D = TO_DATE('2023-10-23 21:00:00', 'YYYY-MM-DD HH24:MI:SS')
and sn.BEGIN_INTERVAL_TIME < TO_DATE('2023-10-23 22:30:00', 'YYYY-MM-DD HH24:MI:SS')
and PARSING_SCHEMA_NAME'SYS')
WHERE TOP_D sysdate - nvl(180,1)/1440 and PARSING_SCHEMA_NAME'SYS')
WHERE TOP_D = to_date('2023-10-23 21:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND dhs.begin_interval_time dbms_logmnr.new,其他不需要添加

SELECT 'execute dbms_logmnr.add_logfile(logfilename=>''' || name || ''', options=>dbms_logmnr.new);' as ddl
FROM v$archived_log
WHERE completion_time >= TO_DATE('2023-10-22 20:00:00', 'YYYY-MM-DD HH24:MI:SS')
AND completion_time '/data/oracle/archivelog/1_167_1106703090.dbf', options=>dbms_logmnr.new);

--使用本地的在线数据字典分析归档日志
execute dbms_logmnr.start_logmnr(options=>dbms_logmnr.dict_from_online_catalog);

--增加日志
execute dbms_logmnr.add_logfile(logfilename=>'/data/oracle/archivelog/1_168_1106703090.dbf');
execute dbms_logmnr.add_logfile(logfilename=>'/data/oracle/archivelog/1_169_1106703090.dbf');
execute dbms_logmnr.add_logfile(logfilename=>'/data/oracle/archivelog/1_170_1106703090.dbf');
execute dbms_logmnr.add_logfile(logfilename=>'/data/oracle/archivelog/1_171_1106703090.dbf');
execute dbms_logmnr.add_logfile(logfilename=>'/data/oracle/archivelog/1_172_1106703090.dbf');
execute dbms_logmnr.add_logfile(logfilename=>'/data/oracle/archivelog/1_173_1106703090.dbf');
execute dbms_logmnr.add_logfile(logfilename=>'/data/oracle/archivelog/1_174_1106703090.dbf');

--创建临时表记录变更信息
create table test.logmnr_contents_1023 as select * from v$logmnr_contents;

-- 最后释放pga
execute dbms_logmnr.end_logmnr;

--查询临时表找出哪个表变更的比较频繁

select to_char(TIMESTAMP,'YYYY-MM-DD HH24') TIME_1,
seg_owner,
table_name,
operation,
count(*)
from test.logmnr_contents_1023
where seg_owner not in ('SYS')
group by to_char(TIMESTAMP,'YYYY-MM-DD HH24'),seg_owner,table_name,operation
order by seg_owner,table_name,to_char(TIMESTAMP,'YYYY-MM-DD HH24'),operation;

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论