Oracle数据库联机重定义讲解及错误处理
1.1. 关键字:联机重定义/SYNC_INTERIM_TABLE/GATHER_TABLE_STATS
1.2. 需求:数据表的清理机制需要优化
离线消息表采用delete的方式定期对过期的数据进行清理,在数据库检测日志中发现每次清理时间都特别长,且清理过程中数据库服务器IO和CPU使用率超高,希望对清理机制进行优化。
1.3. 分析:数据量大
1.涉及到的表有50张,从OFFMSG_0到OFFMSG_49,数据量比较大,最少的一张有一千多万数据,35G左右,最大的一张有几亿数据,超过300G
2.这些表使用比较频繁,超过8000万用户使用,在凌晨两三点也一直有数据进出,不能停机
3.现有的表清理机制是每天凌晨1点开始清理,delete掉日期在7天的数据
综合以上分析,可以将这些表进行分区,每天的数据写入到一个分区,清理时每天truncate掉对应的分区即可
4.实际测试,一张1700万数据的表(35G)进行联机重定义,需要20分钟
5.根据测试的结果估算,平均每张表需要执行超过30分钟,所有表执行完耗时超过25小时
6.运维可接受的一次执行脚本时间在4小时以内
7.要分区的表有正在执行的清理策略,当分区后,清理策略需要进行调整
综合以上情况分析,最终方案确定为:分成8个批次进行联机重定义,将每个联机重定义过的表应用新的清理策略,没有联机重定义的表还使用原有的清理策略
1.4. 操作
检查表空间
联机重定义过程中所需的表空间大小相当于当前已使用的表空间大小,也就是说要联机重定义的表所在的表空间至少要有一半的空余表空间、索引空间和undo空间。
这几个空间保证很关键,有几次我在执行的时候都是只关注了表空间,没有留意索引空间和undo空间,造成索引空间和undo空间被打爆了,联机重定义失败。
检查可否联机重定义
以DBA用户在数据库执行脚本
begin
DBMS_REDEFINITION.CAN_REDEF_TABLE('DBUSER',
'OFFLMG_0',
DBMS_REDEFINITION.CONS_USE_ROWID);
END;
/
出现’ PL/SQL procedure successfully completed.’,说明该表支持联机重定义。如果这个检查都没有通过的话,恭喜你,GG了。
在这里有一点要注意,我操作的这些表是没有主键的,所以使用了DBMS_REDEFINITION.CONS_USE_ROWID,当操作的表有主键时,应该使用DBMS_REDEFINITION.CONS_USE_PK。
Shell脚本
由于需要批量执行,我们将联机重定义脚本设计成shell脚本,在执行时通过参数指定要做哪些表。如下:
#!/bin/ksh
rm -f nohup.out
ORACLE_SID=DBSID;export ORACLE_SID
nohup sqlplus "/as sysdba" << EOF
set serveroutput on;
declare
V_SIGN NUMBER(10);
V_MAX_SIGN NUMBER(10);
V_CREATE_TABLE VARCHAR2(8000);
... ...
begin
V_SIGN := $1;
V_MAX_SIGN := $2;
WHILE V_SIGN <= V_MAX_SIGN LOOP
... ...
这样就可以通过./ShellName 5 8 这种方式指定每次要执行的表了。
创建中间表
在脚本中首先要创建中间表,如:
V_CREATE_TABLE :='CREATE TABLE OFFLMG_0_MY
( ID NUMBER(22,0) NOT NULL,
... ...
--STEP1:定义分区标示字段
PARTITIONFLAG NUMBER(8,0)
)
--STEP2:使用list分区方式
PARTITION BY LIST (PARTITIONFLAG)
(
--STEP3:定义第一个分区
PARTITION P_OFFLMG_0 VALUES (0) TABLESPACE IMLOG,
PARTITION P_OFFLMG_1 VALUES (1) TABLESPACE IMLOG,
... ...
--STEP4:定义默认分区
PARTITION P_OFFLMG_100 VALUES (default) TABLESPACE IMLOG
)
TABLESPACE IMLOG ';
EXECUTE IMMEDIATE V_CREATE_TABLE;
说明:
STEP1:中间表需要有一个分区标示字段,该字段的值作为分区的依据,该字段一般是NUMBER类型的
STEP3:将0值划分到分区P_OFFLMG_0分区,也可以用VALUES(0,1,2,3)的方式将若干个值划分到同一分区,也可以用VALUES LESS THAN(100)的方式将小于100的值划分到同一分区。
例:
PARTITION P_0 VALUES LESS THAN(100) ,
PARTITION P_1 VALUES LESS THAN(200) ,
这段脚本定义了P_0分区存放分区标示字段小于100的数据,P_1分区存放分区标示字段大于等于100小于200的数据。
STEP4:使用list分区时要注意,当你加上default分区后,以后需要添加分区时不能直接add,需要先drop掉default分区再add(会弄丢default分区的数据),或者从default分区split出新分区(不会弄丢default分区的数据,但是当default分区数据比较多时,split操作会特别慢)。
联机重定义
--STEP1:将中间表和要操作的表进行关联
DBMS_REDEFINITION.START_REDEF_TABLE('OFFLMG_0','OFFLMG_0_MY',
'ID ID,TO,......,PARTITIONFLAG PARTITIONFLAG',DBMS_REDEFINITION.CONS_USE_ROWID);
--STEP2:开始进行数据同步
DBMS_REDEFINITION.SYNC_INTERIM_TABLE('OFFLMG_0','OFFLMG_0_MY');
--STEP3:并行创建索引
V_CREATE_INDEX_A :='CREATE INDEX OFFLMG_0_MY_ID ON OFFLMG_0_MY (ID) LOCAL TABLESPACE IMIDX PARALLEL 16';
EXECUTE IMMEDIATE V_CREATE_INDEX_A;
--STEP4:将索引改为非并行的
V_ALTER_INDEX_A := 'ALTER INDEX OOFFLMG_0_MY_ID NOPARALLEL';
EXECUTE IMMEDIATE V_ALTER_INDEX_A;
--STEP5:进行数据整理、统计 DBMS_STATS.GATHER_TABLE_STATS(OWNNAME=>'DBUSER',TABNAME=>'OFFLMG_0_MY',ESTIMATE_PERCENT=> 0.1,DEGREE=>4,CASCADE=>TRUE);
--STEP6:联机重定义结束前再次同步数据
DBMS_REDEFINITION.SYNC_INTERIM_TABLE('OFFLMG_0','OFFLMG_0_MY');
--STEP7:联机重定义结束
DBMS_REDEFINITION.FINISH_REDEF_TABLE('OFFLMG_0','OFFLMG_0_MY');
DBMD_OUTPUT.PUT_LINE('Table OFFLMG_0 Redefined !!!');
说明:
STEP3:要操作的表比较大,创建索引时可以用并行创建的方式进行,大大减少索引创建时间,创建索引时要创建成本地索引。当索引创建完成后,要将索引改成非并行的。
STEP5:这个比较重要,新创建的表同步过来的数据没有生成统计信息,要手动整理一下,这样就可以正常使用了。
STEP6:联机重定义结束前一定要再次同步数据,因为整个操作是不停机执行的,在创建索引和整理数据的时候表中难免有新的数据进来,这个时候执行下同步就能保证新进来的数据也完整同步了。
错误处理
当表空间不足或其他原因造成联机重定义操作异常终止时,需要手动进行回退。脚本如下:
DBMS_REDEFINITION.ABORT_REDEF_TABLE ('OFFLMG_0','OFFLMG_0_MY');
说明:
这个时候只删除中间表是删除不掉的,因为联机重定义会创建实例化视图和实例化视图日志。需要先删除实例化视图日志,再删除实例化视图,最后才能删除中间表。
尾声
当联机重定义结束后, 需要确认数据完全一致,且数据表使用正常后才能删除掉中间表。
Oracle数据库联机重定义讲解及错误处理的更多相关文章
- Oracle数据库中字段定义为Char类型,Hibernate用该字段进行动态绑定参数查询,获取不到结果的问题
一.问题背景 产生环境:oracle数据库,hibernate操作 定义了一个表 create table STORE_INFORMATION ( id CHAR(32) not null, name ...
- Oracle数据库教程-数据定义语言(表操作)
创建表 建表语法: CREATE TABLE 表名 ( 列1 数据类型 [primary key], 列2 数据类型 default 默认值 [not null], …, constraint 约束名 ...
- Oracle数据库中序列用法讲解
序列(SEQUENCE)是序列号生成器,可以为表中的行自动生成序列号,产生一组等间隔的数值(类型为数字).其主要的用途是生成表的主键值,可以在插入语句中引用,也可以通过查询检查当前值,或使序列增至下一 ...
- Oracle数据库排序后分页查询数据错误问题解决
一.问题描述:根据更新时间倒序排序然后分页查询数据,但是点击分页操作的时候,会出现数据重复看似没有操作的情况 二.问题错误原因分析 分页查询的SQL语句: select * FROM (select ...
- 修改oracle数据库字段类型,处理ORA-01439错误
修改表PTLOG的列TYPE的char(1)为varchar(2)类型? 在PTLOG 表新增一列 TYPE_2:ALTER TABLE PTLOG ADD TYPE_2 VARCHAR2(2) de ...
- Oracle在线重定义(online redefinition)--将普通表改为分区表
使用Oracle的在线重定义技术,可以将Oracle的普通表改为分区表.操作如下: STEP1:测试表是否可以在线重定义,这里以unixdev数据库的LIJIAMAN.BSTEST为例 EXEC DB ...
- 基于 dbms_redefinition 在线重定义表
Oracle 支持在线重定义表,也就是说我们可以在修改表结构(DDL)的同时进行相关的DQL.DML操作,使得前端的DML根本感觉不到表结构实际上已经发生了变化,对于用户而言是完全透明的.当然在线重定 ...
- Oracle数据库备份、灾备的23个常见问题
为了最大限度保障数据的安全性,同时能在不可预计灾难的情况下保证数据的快速恢复,需要根据数据的类型和重要程度制定相应的备份和恢复方案.在这个过程中,DBA的职责就是要保证数据库(其它数据由其它岗位负责) ...
- oracle数据库常用SQL语句(11.29更新)
笔者日常工作中常用到的sql语句,现总结如下,留作日后查看. 1.按照两列中的最大值取 ,只取两列其中的一列 SELECT * FROM t_doc T ORDER BY GREATEST(T.Loa ...
随机推荐
- mybatis BindingException: Invalid bound statement (not found)
错误截图 解决措施 此异常的原因是由于mapper接口编译后在同一个目录下没有找到mapper映射文件而出现的. 通常我们在配置SqlSessionFactory时会有如配置 <!-- 配置Sq ...
- PyQt5简介及demo
PyQt5说明 pyqt5是一套Python绑定Digia QT5应用的框架.它可用于Python 2和3.本教程使用Python 3.Qt库是最强大的GUI库之一.pyqt5的官方网站http:// ...
- PHP Echarts Ajax Json柱形图示例
<?php $server = '127.0.0.1'; $user = 'root'; $password = ''; $database = 'yiibaidb'; $conn = new ...
- web项目的一些常用设置
给项目取别名: 03
- 单源最短路——Dijkstara算法
算法基本思想:每次找到离源点最近的一个顶点,然后以该顶点为中心进行扩展,最终得到源点到其余所有点的最短路径. 1.将所有的顶点分为两个部分:已知最短路程的顶点集合P和未知最短路径的顶点集合Q 2.设置 ...
- go中 -strconv包的使用
strconv 包中的函数和方法 // atob.go ------------------------------------------------------------ // ParseBoo ...
- laravel中empty(),is_null() 以及isEmpty()
PHP中 empty() empty() 函数用于检查一个变量是否为空. if(empty($result->order)){ //操作 } is_null() is_null() 函数用于检测 ...
- P4777 【模板】扩展中国剩余定理(EXCRT)/ poj2891 Strange Way to Express Integers
P4777 [模板]扩展中国剩余定理(EXCRT) excrt模板 我们知道,crt无法处理模数不两两互质的情况 然鹅excrt可以 设当前解到第 i 个方程 设$M=\prod_{j=1}^{i-1 ...
- Python文档记录
Beautiful Soup 4.2.0 文档 Python3网络爬虫开发实战 Python库-requests 文档 Selenium with Python中文翻译文档 http://www.te ...
- 从GitHub远程仓库中删除文件夹或文件
在上传项目到github时,忘记忽略了某个文件夹target,就直接push上去了, 最后意识到了此问题,决定删除掉远程仓库中的target文件夹 删除前: 删除后: 在github上只能删除仓库,却 ...