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数据库联机重定义讲解及错误处理的更多相关文章

  1. Oracle数据库中字段定义为Char类型,Hibernate用该字段进行动态绑定参数查询,获取不到结果的问题

    一.问题背景 产生环境:oracle数据库,hibernate操作 定义了一个表 create table STORE_INFORMATION ( id CHAR(32) not null, name ...

  2. Oracle数据库教程-数据定义语言(表操作)

    创建表 建表语法: CREATE TABLE 表名 ( 列1 数据类型 [primary key], 列2 数据类型 default 默认值 [not null], …, constraint 约束名 ...

  3. Oracle数据库中序列用法讲解

    序列(SEQUENCE)是序列号生成器,可以为表中的行自动生成序列号,产生一组等间隔的数值(类型为数字).其主要的用途是生成表的主键值,可以在插入语句中引用,也可以通过查询检查当前值,或使序列增至下一 ...

  4. Oracle数据库排序后分页查询数据错误问题解决

    一.问题描述:根据更新时间倒序排序然后分页查询数据,但是点击分页操作的时候,会出现数据重复看似没有操作的情况 二.问题错误原因分析 分页查询的SQL语句: select * FROM (select ...

  5. 修改oracle数据库字段类型,处理ORA-01439错误

    修改表PTLOG的列TYPE的char(1)为varchar(2)类型? 在PTLOG 表新增一列 TYPE_2:ALTER TABLE PTLOG ADD TYPE_2 VARCHAR2(2) de ...

  6. Oracle在线重定义(online redefinition)--将普通表改为分区表

    使用Oracle的在线重定义技术,可以将Oracle的普通表改为分区表.操作如下: STEP1:测试表是否可以在线重定义,这里以unixdev数据库的LIJIAMAN.BSTEST为例 EXEC DB ...

  7. 基于 dbms_redefinition 在线重定义表

    Oracle 支持在线重定义表,也就是说我们可以在修改表结构(DDL)的同时进行相关的DQL.DML操作,使得前端的DML根本感觉不到表结构实际上已经发生了变化,对于用户而言是完全透明的.当然在线重定 ...

  8. Oracle数据库备份、灾备的23个常见问题

    为了最大限度保障数据的安全性,同时能在不可预计灾难的情况下保证数据的快速恢复,需要根据数据的类型和重要程度制定相应的备份和恢复方案.在这个过程中,DBA的职责就是要保证数据库(其它数据由其它岗位负责) ...

  9. oracle数据库常用SQL语句(11.29更新)

    笔者日常工作中常用到的sql语句,现总结如下,留作日后查看. 1.按照两列中的最大值取 ,只取两列其中的一列 SELECT * FROM t_doc T ORDER BY GREATEST(T.Loa ...

随机推荐

  1. Django配置相关及其它

    配置 模板 TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [ os.pat ...

  2. C++编译器将自动为类产生四个缺省的函数

    构造函数.析构函数与赋值函数是每个类最基本的函数.它们太普通以致让人容易麻痹大意, 其实这些貌似简单的函数就象没有顶盖的下水道那样危险. 每个类只有一个析构函数和一个赋值函数,但可以有多个构造函数(包 ...

  3. postman 做接口测试之学习笔记

    Postman 之前是作为Chrome 的一个插件,现在要下载应用才能使用. 以下是postman 的界面: 各个功能区的使用如下: 快捷区: 快捷区提供常用的操作入口,包括运行收藏夹的一组测试数据, ...

  4. Docker:从引擎和运行框架理解Docker(3)

    Docker是GO语言编写的. 1.Docker发挥的作用: 1.快速.一致.标准化的交付应用.从开发.测试.到部署交付到成产环境都可以使用docker命令处理image到不同的环境 2.部署和扩展: ...

  5. postgres密码修改

    . 修改PostgreSQL数据库默认用户postgres的密码 PostgreSQL数据库创建一个postgres用户作为数据库的管理员,密码随机,所以需要修改密码,方式如下: 步骤一:登录Post ...

  6. Python使用中错误(持续更新.....)

    1.在使用requests发送请求,响应数据转成json提示,没有可解码的json 解决办法: 这是由于,发送请求的数据,存在错误,响应出错比如404 400,所以找不到可以解码的json 示例如下: ...

  7. linux----------今天又遇到一个奇葩的问题,就是linux文件的权限已经是777了但是还是没有写入权限,按照下面的命令就解决了

    查看SELinux状态: 1./usr/sbin/sestatus -v  ##如果SELinux status参数为enabled即为开启状态 SELinux status:             ...

  8. CentOS 7 使用SVN+Apache搭建版本控制服务器

    svn简介 Subversion是一个免费/开源的版本控制系统, Subversion 可以跨越时间地对文件和目录, 以及它们的修改进行管理. 这就允许你恢复 数据的旧版本, 或检查数据的修改历史. ...

  9. CentOS 7 nginx+tomcat9 session处理方案之session复制

    我们的目标是所有服务器上都要保持用户的Session,那么将每个应用服务器中的Session信息复制到其它服务器节点上是不是就可以呢? 这就是Session的第二中处理办法:会话复制 192.168. ...

  10. SQL Server 2008 报表服务入门【转】

    转http://www.cnblogs.com/YZDONET/archive/2012/08/17/2644711.html 概述 上周,Tim与我们分享了SQL Server 2008 报表服务的 ...