现在的位置: 首页 > 综合 > 正文

昨天做了次大表切换工作—失败了

2012年10月23日 ⁄ 综合 ⁄ 共 3579字 ⁄ 字号 评论关闭



<!--
/* Font Definitions */
@font-face
{font-family:宋体;
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-alt:SimSun;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
@font-face
{font-family:"/@宋体";
panose-1:2 1 6 0 3 1 1 1 1 1;
mso-font-charset:134;
mso-generic-font-family:auto;
mso-font-pitch:variable;
mso-font-signature:3 135135232 16 0 262145 0;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{mso-style-parent:"";
margin:0cm;
margin-bottom:.0001pt;
text-align:justify;
text-justify:inter-ideograph;
mso-pagination:none;
font-size:10.5pt;
mso-bidi-font-size:12.0pt;
font-family:"Times New Roman";
mso-fareast-font-family:宋体;
mso-font-kerning:1.0pt;}
span.javascript
{mso-style-name:javascript;}
/* Page Definitions */
@page
{mso-page-border-surround-header:no;
mso-page-border-surround-footer:no;}
@page Section1
{size:595.3pt 841.9pt;
margin:1.0cm 1.0cm 1.0cm 1.0cm;
mso-header-margin:42.55pt;
mso-footer-margin:49.6pt;
mso-paper-source:0;
layout-grid:15.6pt;}
div.Section1
{page:Section1;}
-->


1
有两个表想改成按某个时间的分区存储,原来是按另个时间来分区存储的。A
表有21G
11786
万行 分区未压缩。B
表有9.5G
 
16442

万条 分区压缩

2
另外建立了两个目的表 分区压缩,增加两个新字段。各有16
个存储过程向两个表MERGE
数据。运行了很长时间,大约2-3
周吧。在昨天周一上午对照两个表的上周的成功销售数据条数和金额,结果是一致的。心情很愉快!就通知其他同事要更改表结构。

3
两套表和存储过程 分别有两个JOB
调度。原来的存储过程JOB
是在0
点运行的。目的JOB
是在10
点运行的。

4
在下午的时候,目的JOB
已经运行完了16
个存储过程,当它还在运行另外5
个额外的过程,所以还得等待。不过这时候我把原来16
个存储过程从库中删除了,在删除的时候多想了下,就保存在本地磁盘上并名字尾部追加001

5
然后在目的表生产索引,AB
表上的索引和关键字的代码合在一起。然后放在LINUX
下用SH
脚本自动跑。原本想是很顺利的事情,可跑了1
个多小时候,A
表的跑完了,B
表的索引也建完了,可B
表的关键字去报错,有重复数据!

6
郁闷啊,纠结啊!随后查下是什么样的数据重复了,看组成关键字那两个字段的值

select

/*+parallel(t,12)*/

F_ID,F_LOTID,f_projid
count
(*) 

from
T_B_TARGET T

group

by
 
F_ID,F_LOTID, f_projid

having

count
(*)>
1

发现是那16
个过程中其中一个过程里的一部分,特殊处理部分。该部分是把有些行数据F_Id
前置成负数,以便与其他数据不发生关键字冲突。找到该过程,感觉原来已经处理过啊!这种感觉不是那种忽然间似曾面熟,似曾来过,似曾以前经历过。而确实真实修改过的。
不过今天想想,会不会上个月做数据库迁移时候,两边的库同时修改,同时运行,而对这不重要的过程,只修改了那边的而未修改这边的。

其实上面的代码在原来B
表上并没有关键字,而是在B
表的继承表才有关键字。从业务上来说只需要F_ID,F_LOTID
两个字段做关键字,而F_PROJID
A
表的一个关键字中字段。

因此采用以下语句删除重复字段

DELETE FROM

T_B_TARGET
E


WHERE E.ROWID > (SELECT MIN(X.ROWID)

FROM

T_B_TARGET
X


WHERE X.

F_ID
= E.

F_ID

And x. F_LOTID=e. F_LOTID
);

跑了近一个小时后,这是在数据库所在机器上的SQLPLUS
上跑的,与我的电脑很远,中间通过防火墙连接,防火墙监听进程如果有多少分钟没操作就给断了!不过我这边通过SECURECRT
连接的,其中设置了空闲发生某某去服务器。

结果 所删除的行数大于上面查询出来的数量。这就让我郁闷呢!再查下两边总数据量,发现原来B
表有1.7
亿条,而B
目的表有1.55
亿。怎么会这样呢?记得原来库上做这个目的表时候,是从原来表全导过来的,时间也没差多久啊!DBA
做数据库迁移时候,已经把它迁移过来了。

怎么会差2
千万条呢? 而且只能多不能少数据的,毕竟有个过程,也就是上面提到那个特殊处理部分,其实就是把A
表的某些记录复制到B
表中,并且F_ID
置成负值。

7

到目前只好重新做过B
目的表了。在sqlplus
TRUNCATE
该表,
然后删除了索引,再把表置NOLOGGING
状态。记得DBA
说过如果整个表导过去的话,会要很长的时间。如果按分区导的话会很快的。不是EXPIMP
方式。是INSERT INTO SELECT
方式。

先找到B
表的分区名称

select
PARTITION_NAME
from

dba_tab_partitions

where
table_owner=
''

and
table_name=
''

再用工具 前插入

insert
/*+append*/


into
T_B_TARGET

select
*
from
T_B
partition
(

后插入
);

本来每条后面追加 commit;

不过以前有过教训 LINUX VI
下它不能认COMMIT;

set
oracle_sid=FUKBA

date;

 
sqlplus fuk/fuk2012@fukba <<EOF

insert
/*+append*/


into
T_B_TARGET

select
*
from
T_B
partition
(
P_0701);COMMIT;

EOF

Date;

NOHUP
SH SQL.SH &

后它 cat nohup
报 并行模式下不能修改对象

8
都晚上10
点了  
把原来的过程编译进数据库里,还好保存下来了。把表名称改回来,把过程编译下,有个表没改名,继续改,继续编译。总于恢复到原来的样子

9
SQLPLUS
试了下 insert into
一个大分区 需要3
分钟 几千万条数据就进去了。然后在SH
脚本里手工加入COMMIT
46
行啊!

跑完后 花费了46
分钟。

10
接着在B
目的表上先上关键字。没多久报错
还是有重复数据!查下数据量 共有2.2
亿条! 我的天啊,不想让我回窝睡了吗?

11
10:30

了 再次清空表 一次行插入全部数据
insert
/*+append*/


into
T_B_TARGET

select
/*+parallel(b,12)*/*
from
T_B
b

12
全插了1
个小时结束了!建关键字 。都11:30
了 再耗下去 就不能回郊区窝里了!怎么办? 先查下数据量,嗯1.7
亿条。

应该不会有重复数据的,因为在原B
表上核对过没有重复数据的。应该放心的。好吧!把关键字语句放到SQLPLUS
上跑。另外两个索引放到SH
脚本里跑。

 

13
今天早上过来 看到关键字建立起来了,花费了51
分。索引也建好了,从11:27
分到12:59
分。我考!还是英明的回窝睡了!

 

最后总结下 总的来说《实践是检验真理的唯一标准》 不动手亲子做,原来认为,原来以为,原来应该,原来大脑觉得事。到了实践一切皆有可能变得糟糕!
VI
下面的SH
脚本里运行SQL
语句,估计要分行确认COMMIT
; 也就是说两个语句不能同在一行。SQLPLUS
里还遇到了个问题,执行了两个语句后,再执行第三个语句,它报错了。从错误上看第二条和第三条语句连在一起,也就是第二条语句没执行过。

复制过去的第三条语句被追加到了第二条语句尾部。 不知道是什么原因!
当它给我错误的认识,让我感到第二条语句已经执行完了,让我错误地执行了其他工作!

 

其实说白了 在LINUX
下很多细节要注意的,这些细节影响了你的工作效率,并且制造了麻烦!

 

抱歉!评论已关闭.