fromuser=zhangzj
touser=zzzzzz
tables=yz_ongimt_jingtzt file=exp0208.dmp log=imp0208.log
buffer=100000 –大小控制导入速度的,设置过大会导致日志产生很快
imp parfile=imp_ws0208.par –进行数据导入
注意上面的fromuser和touser。如果将表导入到两个schema:zzzzzz,yyyyy 需要按照这种格式配置参数:
fromuser和touser一一对应,即使导出时只有一个schema. fromuser=zhangzj,zhangzj touser=zzzzzz,yyyyy 1 2
b) exp导出数据时,检查exp的日志,如果报错,一般是参数配置错误,参考官方文档调整参数。
c) imp导入数据过程,需要监控下数据库事务和日志产生速度。 d) 对导入的表收集统计信息。
3. 验证方案
对比exp、imp的日志,确认导出导入数据量是否一致。并在数据库上检查数据量。 比如上面的数据迁移,检查数据量跟日志显示是否一致。
select count(*) from zzzzzz.yz_ongimt_jingtzt;
跨schema或者数据库迁移数据时,除检查日志外,还需要检查源和目标的对象数据量、 是否有失效对象。
select object_type,count(*) from dba_objects where owner=‘源schema‘; select object_type,count(*) from dba_objects where owner=‘目标schema‘; select * from dba_objects where status<>‘VALID‘ and owner=‘ 目标schema‘;
五、 核心对象风险
由于核心表访问、变更频繁,不宜直接使用imp对核心表大量导入数据。
六、 回退方案
exp对应用无影响,不需要回退。
imp后可能数据有误,需要进行回退操作。
如果目标表本来就是空表,跟应用确认后,直接清空即可。
如果目标表原有数据,跟应用确认是否使用原有备份数据进行恢复。若需要,先exp备份当前数据,然后清空再导入前面的备份数据。
19-数据迁移工具之sqlldr
一、 目的
说明使用sqlldr进行数据迁移的前置条件、操作步骤,降低对对应用造成的影响及避免故障
二、 适用范围
l 所有线上库:数据迁移,数据初始化,以及应用几乎只读的表
三、 风险评估
使用sqlldr迁移数据时,普通方式加载数据本质是insert,对表的结构影响不大。使用需要rows控制事务大小。风险主要在使用direct方式加载上:
l 默认情况下会同时维护索引,如果设置参数SKIP_INDEX_MAINTENANCE=true,则不会维护索引。导致索引处于处于unusable状态。
l direct方式加载数据时,表上unique约束始终有效,unique约束的校验是在表加载数据完毕后rebuild索引时完成的,如果索引build时发现有违反unique约束的数据,会导致该索引处于unusable状态。
l direct方式加载数据时,索引结构相当于rebuild,对临时空间需求比较大。如果空间不足,会导致索引处于unusable状态。
l 如果数据空间不足导致加载报错,也会导致索引处于unusable状态。
l 如果启用savepoint机制,sqlldr进程被中断失败时,会使索引处于unusable状态。
l direct方式加载数据时会自动disable表上的触发器和约束(check、外键),在加载完成再次enable,由于enable时需要获得一个互斥的表锁,如果获得表锁失败,会导致无法成功enable。 l 表上的约束如果以enable novalidate方式启用时,direct方式加载数据时不会校验该约束,可能导致非法数据出现。
四、 操作流程
1. 准备工作
a) sqlldr不支持cluster表,及有global index的分区表。检查加载数据的目标表结构,尤其是触发器和约束,以及表上索引状态。如果有处于unusable的索引,需要评估是否rebuild生效,或者删除。
SELECT INDEX_NAME, STATUS FROM USER_INDEXES WHERE TABLE_NAME = ?tablename‘ and status<>?VALID‘;
SELECT INDEX_NAME, PARTITION_NAME, STATUS FROM USER_IND_PARTITIONS WHERE STATUS <> ?VALID‘;
b) 如果有enable novalidate方式启用的约束,需要提前评估是否再对该约束enable validate
一次。
select constraint_name, status, validated from user_constraints
where table_name = upper(?tablename‘);
enable validate约束:该操作会锁表,需要在业务低峰期处理
alter tablename enable validate constraint constraint_name;
c) 估算表数据需要的空间和加载过程索引需要的临时空间大小。索引需要的临时空间计算方法:
1.3*(number_of_rows)*( 10 + sum_of_column_sizes + number_of_columns ) 一般情况下是1.3倍,安全起见可以使用2倍系数【参考】
d) 根据加载的文本文件内容编写controlfile,sqlldr命令使用的各个参数。SKIP_INDEX_MAINTENANCE 这个参数默认值是false,不建议修改。 e) 检查表上是否有活动事务 select *
from v$locked_object a, dba_object b where a.object_id = b.object_id
and b.owner = ‘schema‘
and b.object_name = ‘tablename‘;
2. 执行过程
如果目标表是已存在数据,跟应用确认后,可以先进行exp导出备份,以防后面需 要回退。
这里给出一个示例,从算法提供的文本文件加载数据。
先根据需求编辑的control文件:‘-?后面是参数说明,实际使用时去掉 more ld_ws.ctl load data
infile ?totaldata_ae.txt‘
append into table X_table_name (
id sequence(200000000,1), –这里产生表id列的数据,自增长。2亿是起始值,1代表步长 GMT_CREATE ―sysdate‖, –对gmt_create使用sysdate填充,下同 GMT_MODIFIED ―sysdate‖,
PRODUCT_ID POSITION(1) CHAR TERMINATED BY ?\\^‘ ―TO_NUMBER(:PRODUCT_ID)‖, –这里开始读取正式数据,注意position(1),指定从文本各行的第一个字符开始。如果不指定product_id数据的起始位置,上面的gmt_create,gmt_modified列数据初始化会报错 group_ID TERMINATED BY ?\\^‘, FINGER_PRINT TERMINATED BY ?\\^‘, IMG_VERSION TERMINATED BY ?\\^‘, IMG_URL TERMINATED BY ?\\^‘, COMPANY_ID TERMINATED BY ?\\^‘, OFFLINE_DATE TERMINATED BY ?\\^‘
―to_number(:OFFLINE_DATE)/3600/24+to_date(‘1970-01-01 00:00:00′, ?yyyy-mm-dd hh24:mi:ss‘)‖,–这里时间数字转成日期格式 grade TERMINATED BY ?\\t‘ ―TO_NUMBER(:grade)‖
)
–加载数据
sqlldr userid=username/password@dbname direct=true control=ld_ws.ctl log=ld_ws.log bad=ld_ws.err 1
2
ld_ws.err保存不符合上面control文件格式的数据
3. 验证方案
a) 检查sqlldr的日志,确认是否报错,以及非法的数据。并在数据库上检查数据量和导入的数据量是否一致。
比如上面的数据迁移,检查数据量跟日志显示是否一致。 select count(*) from zzzzzz.x_table_name;
b) 检查是否有处于unusable状态的索引及索引分区,如果有,rebuild该索引。 SELECT INDEX_NAME, STATUS FROM USER_INDEXES WHERE TABLE_NAME = ?tablename‘ and status<>?VALID‘;
SELECT INDEX_NAME, PARTITION_NAME, STATUS FROM USER_IND_PARTITIONS
WHERE STATUS <> ?VALID‘;
c) 检查是否存在disable状态约束和触发器,如果存在手工enable select trigger_name, status from user_triggers where table_name = ?tablename‘ and status <> ?ENABLED‘;
select constraint_name, status from user_constraints where table_name = ?tablename‘ and status <> ?ENABLED‘;
五、 核心对象风险
由于核心表访问、变更频繁,不宜直接使用sqlldr对核心表大量导入数据。需要先导入一个同构的中间表,再把数据分批insert到正式表。
六、 回退方案
sqlldr加载后可能数据有误,需要进行回退操作。
如果目标表本来就是空表,跟应用确认后,直接清空即可。
如果目标表原有数据,跟应用确认是否使用原有备份数据进行恢复。
20-固定执行计划-baseline
一、 目的
在遭遇执行计划不稳定或者执行计划错误的情况下,通过baseline来固定SQL执行计划以确保执行计划稳定性、提高性能。baseline是oracle 11G提供的稳固sql执行计划的功能,是spm功能的一部分。本人更建议通过10G的sql profile来实现baseline的这些功能,因为baseline用起来稍微繁琐点,sql profile的使用规范请参照我写的其他文档。
二、 适用范围
l 执行计划走错,导致查询性能降低,数据库压力飙升 l 执行计划不稳定,有走错的风险。
l 执行计划错误,需要增加hint,应用来不及修正发布,临时用baseline固定。
l 数据库升级,可以在源库生成baseline,然后把baseline迁移至新库,这样能确保升级前后执行计划性能不变。详情参阅ORACLE 11G SPM部分。
三、 风险评估
l outline、sql profile、baseline这三种固定执行计划的方式都依赖于SQL的文本,如果SQL文本变了,就失去了固定的作用。因此对于并发量非常大、应用修改代码容易的SQL,应该确保通过添加hint的方式来矫正执行计划,以免通过baseline方式修正执行计划的SQL文本变化,导致baseline失效,查询计划走错,导致数据库压力飙升。
l 在做数据迁移过程中,如果原系统中存在已经建立过的baseline,请不要在数据迁移过程中忘记在新系统中安装他们。
l 需要注意,表对象被删除时,baseline并不会被删除,当然这个应该也不是很严重的问题。如果想要删除baseline,必须采取显式的用命令删除。
l baseline是依赖sql文本来进行匹配的,这意味着一份SQL计划基线可能同时被用于两张有相同名称但分属于不同schema下的表。
四、 操作流程
1)FUNCTION LOAD_PLANS_FROM_CURSOR_CACHE RETURNS BINARY_INTEGER Argument Name Type In/Out Default? —————————— ———————– —— ——–
SQL_ID VARCHAR2 IN
PLAN_HASH_VALUE NUMBER IN DEFAULT FIXED VARCHAR2 IN DEFAULT ENABLED VARCHAR2 IN DEFAULT 2)FUNCTION LOAD_PLANS_FROM_CURSOR_CACHE RETURNS BINARY_INTEGER Argument Name Type In/Out Default?

