exp的consistent=Y的用途

最近客户提到关于exp出来的sequence小于表中数据的问题,研究了一下,解决了。
具体问题是这样的:表的主键是用sequence来生成的。在exp按user导出时,是先导出sequence然后再导出表,这就有可能发生这样的情况,
在sequence导出以后,在对应的表导出之前,有新的数据insert这张表,并且及时提交了,这使导出表的时候表中主键的值已经大于之前导出的seqence值。
如果把这个dmp文件导入到别的用户或是数据库中,对这个表进行插入,就会遇到主键冲突的错误。
这个问题的解决办法是在exp时加上consistent=y的参数,其作用是exp对所有要导出表的查询都是发生在同一时间的,也就是第一个表导出的那个时间,这样即使在sequence导出
之后有新的数据insert,exp也不会导出这些数据。
下面作实验验证。

 


--情况一:5个表,每个表有sequence,sequence是nocache的。在表导出过程中,不断插入数据。之后再imp,然后再插入数据,出现主键冲突错误。
SQL> create table t1 (a int);

表已创建。

SQL> create table t2 (a int);

表已创建。

SQL> create table t3 (a int);

表已创建。

SQL> create table t4 (a int);

表已创建。

SQL> create table t5 (a int);

表已创建。

SQL> create sequence seq_t1 increment by 1 start with 1 nocache;

序列已创建。

SQL> create sequence seq_T2 INCREMENT BY 1 START with 1 nocache;

序列已创建。

SQL> create sequence seq_t3 INCREMENT BY 1 START with 1 nocache;

序列已创建。

SQL> create sequence seq_t4 INCREMENT BY 1 START with 1 nocache;

序列已创建。

SQL> create sequence seq_t5 INCREMENT BY 1 START with 1 nocache;

序列已创建。

--循环100000次,每次向5个表插入数据。与此同时,对5个表进行导出。
SQL> begin
2 for i in 1..100000 loop
3 insert into t1 values (seq_t1.nextval);
4 insert into t2 values (seq_t2.nextval);
5 insert into t3 values (seq_t3.nextval);
6 insert into t4 values (seq_t4.nextval);
7 insert into t5 values (seq_t5.nextval);
8 commit;
9 end loop;
10 end;
11 /

PL/SQL 过程已成功完成。


D:oracleora92bin>exp test/test@test9 owner=test file=c:test.dmp

Export: Release 9.2.0.1.0 - Production on 星期三 10月 11 10:05:03 2006

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.


连接到: Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production
已导出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集
服务器使用 ZHS16CGB231280 字符集 (可能的字符集转换)

即将导出指定的用户...
. 正在导出 pre-schema 过程对象和操作
. 正在导出用户 TEST 的外部函数库名称
. 导出 PUBLIC 类型同义词
. 导出私有类型同义词
. 正在导出用户 TEST 的对象类型定义
即将导出 TEST 的对象 ...
. 正在导出数据库链接
. 正在导出序号
. 正在导出群集定义
. 即将导出 TEST 的表通过常规路径 ...
. . 正在导出表 T1 15271 行被导出
. . 正在导出表 T2 15272 行被导出
. . 正在导出表 T3 15390 行被导出
. . 正在导出表 T4 15463 行被导出
. . 正在导出表 T5 15602 行被导出
. 正在导出同义词
. 正在导出视图
. 正在导出存储的过程
. 正在导出运算符
. 正在导出引用完整性约束条件
. 正在导出触发器
. 正在导出索引类型
. 正在导出位图, 功能性索引和可扩展索引
. 正在导出后期表活动
. 正在导出实体化视图
. 正在导出快照日志
. 正在导出作业队列
. 正在导出刷新组和子组
. 正在导出维
. 正在导出 post-schema 过程对象和操作
. 正在导出统计
在没有警告的情况下成功终止导出。

--可以看到导出的数据量是不一样的。而且是sequence先导出,表后导出。

--重建用户,导入数据。

D:oracleora92bin>imp test/test@test9 full=y file=c:test.dmp

Import: Release 9.2.0.1.0 - Production on 星期三 10月 11 10:21:01 2006

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.


连接到: Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production

经由常规路径导出由EXPORT:V09.02.00创建的文件
已经完成ZHS16GBK字符集和AL16UTF16 NCHAR 字符集中的导入
导入服务器使用ZHS16CGB231280字符集 (可能的字符集转换)
. 正在将TEST的对象导入到 TEST
. . 正在导入表 "T1" 15271行被导入
. . 正在导入表 "T2" 15272行被导入
. . 正在导入表 "T3" 15390行被导入
. . 正在导入表 "T4" 15463行被导入
. . 正在导入表 "T5" 15602行被导入
成功终止导入,但出现警告。

SQL> conn test/test
已连接。
SQL> alter table t1 add primary key (a);

表已更改。

SQL> alter table t2 add primary key (a);

表已更改。

SQL> alter table t3 add primary key (a);

表已更改。

SQL> alter table t4 add primary key (a);

表已更改。

SQL> alter table t5 add primary key (a);

表已更改。

--可以看到,T2到T5这4个表主键的最大值都不小于对应sequence的LAST_NUMBER,这样再插入数据就会导致主键冲突。

SQL> select sequence_name,last_number from user_sequences;

SEQUENCE_NAME LAST_NUMBER
------------------------------------------------------------ -----------
SEQ_T1 15273
SEQ_T2 15272
SEQ_T3 15272
SEQ_T4 15272
SEQ_T5 15272

SQL> insert into t1 values (seq_t1.nextval);

已创建 1 行。

SQL> insert into t2 values (seq_t2.nextval);
insert into t2 values (seq_t2.nextval)
*
第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (TEST.SYS_C001579)


SQL> insert into t3 values (seq_t3.nextval);
insert into t3 values (seq_t3.nextval)
*
第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (TEST.SYS_C001580)


SQL> insert into t4 values (seq_t4.nextval);
insert into t4 values (seq_t4.nextval)
*
第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (TEST.SYS_C001581)


SQL>
SQL> insert into t5 values (seq_t5.nextval);
insert into t5 values (seq_t5.nextval)
*
第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (TEST.SYS_C001582)


SQL> commit;

提交完成。

 

--第2种情况,将sequence cache 1000。这样exp时,exp不会导出sequence的当前值,而是导出sequence cache的上限值,这会使报主键冲突的几率降低,但不能彻底解决这个问题。


SQL> conn test/test
已连接。
SQL> create table t1 (a int);

表已创建。

SQL> create table t2 (a int);

表已创建。

SQL> create table t3 (a int);

表已创建。

SQL> create table t4 (a int);

表已创建。

SQL> create table t5 (a int);

表已创建。

SQL> create sequence seq_t1 increment by 1 start with 1 cache 1000;

序列已创建。

SQL> create sequence seq_t2 increment by 1 start with 1 cache 1000;

序列已创建。

SQL> create sequence seq_t3 increment by 1 start with 1 cache 1000;

序列已创建。

SQL> create sequence seq_t4 increment by 1 start with 1 cache 1000;

序列已创建。

SQL> create sequence seq_t5 increment by 1 start with 1 cache 1000;

序列已创建。

SQL> begin
2 for i in 1..100000 loop
3 insert into t1 values (seq_t1.nextval);
4 insert into t2 values (seq_t2.nextval);
5 insert into t3 values (seq_t3.nextval);
6 insert into t4 values (seq_t4.nextval);
7 insert into t5 values (seq_t5.nextval);
8 commit;
9 end loop;
10 end;
11 /

PL/SQL 过程已成功完成。

--在上面插入数据的同时,导出5个表的数据。

D:oracleora92bin>exp test/test@test9 owner=test file=c:test.dmp

Export: Release 9.2.0.1.0 - Production on 星期三 10月 11 10:46:58 2006

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.


连接到: Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production
已导出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集
服务器使用 ZHS16CGB231280 字符集 (可能的字符集转换)

即将导出指定的用户...
. 正在导出 pre-schema 过程对象和操作
. 正在导出用户 TEST 的外部函数库名称
. 导出 PUBLIC 类型同义词
. 导出私有类型同义词
. 正在导出用户 TEST 的对象类型定义
即将导出 TEST 的对象 ...
. 正在导出数据库链接
. 正在导出序号
. 正在导出群集定义
. 即将导出 TEST 的表通过常规路径 ...
. . 正在导出表 T1 38858 行被导出
. . 正在导出表 T2 38859 行被导出
. . 正在导出表 T3 38906 行被导出
. . 正在导出表 T4 38937 行被导出
. . 正在导出表 T5 39089 行被导出
. 正在导出同义词
. 正在导出视图
. 正在导出存储的过程
. 正在导出运算符
. 正在导出引用完整性约束条件
. 正在导出触发器
. 正在导出索引类型
. 正在导出位图, 功能性索引和可扩展索引
. 正在导出后期表活动
. 正在导出实体化视图
. 正在导出快照日志
. 正在导出作业队列
. 正在导出刷新组和子组
. 正在导出维
. 正在导出 post-schema 过程对象和操作
. 正在导出统计
在没有警告的情况下成功终止导出。

 

SQL> conn / as sysdba
已连接。
SQL> drop user test cascade;

用户已删除。

SQL> grant dba to test identified by test;

授权成功。

--导入数据,略。

--由于sequence都设置了cache 1000,所以导出的sequence都是取的当时的cache的上限值(最大值)。

SQL> select sequence_name,last_number from user_sequences;

SEQUENCE_NAME LAST_NUMBER
------------------------------------------------------------ -----------
SEQ_T1 39001
SEQ_T2 39001
SEQ_T3 39001
SEQ_T4 39001
SEQ_T5 39001

SQL> alter table t1 add primary key (a);

表已更改。

SQL> alter table t2 add primary key (a);

表已更改。

SQL> alter table t3 add primary key (a);

表已更改。

SQL> alter table t4 add primary key (a);

表已更改。

SQL> alter table t5 add primary key (a);

表已更改。

SQL> insert into t1 values (seq_t1.nextval);

已创建 1 行。

SQL> insert into t2 values (seq_t2.nextval);

已创建 1 行。

SQL> insert into t3 values (seq_t3.nextval);

已创建 1 行。

SQL> insert into t4 values (seq_t4.nextval);

已创建 1 行。

SQL> insert into t5 values (seq_t5.nextval);
insert into t5 values (seq_t5.nextval)
*
第 1 行出现错误:
ORA-00001: 违反唯一约束条件 (TEST.SYS_C001587)

--最后一个表导出时,数据已经到了39089条,大于最开始导出的sequence的值,这就导致了后来的主键冲突的发生。

SQL> commit;

提交完成。

 

--第3种情况,在exp时加上参数consistent=y,这样5个表导出的数据量是一样的,实际上exp在内部记录了第一个表导出时数据库的scn,然后以后每个表导出都是按照这个scn进行的查询。这就保证了一致性。这样exp过程中insert的数据自然就不会被导出。也就避免了后来的主键冲突。

 

SQL> create table t1 (a int);

表已创建。

SQL> create table t2 (a int);

表已创建。

SQL> create table t3 (a int);

表已创建。

SQL> create table t4 (a int);

表已创建。

SQL> create table t5 (a int);

表已创建。

SQL> create sequence seq_t1 increment by 1 start with 1 nocache;

序列已创建。

SQL> create sequence seq_t2 increment by 1 start with 1 nocache;

序列已创建。

SQL> create sequence seq_t3 increment by 1 start with 1 nocache;

序列已创建。

SQL> create sequence seq_t4 increment by 1 start with 1 nocache;

序列已创建。

SQL> create sequence seq_t5 increment by 1 start with 1 nocache;

序列已创建。

SQL> begin
2 for i in 1..50000 loop
3 insert into t1 values (seq_t1.nextval);
4 insert into t2 values (seq_t2.nextval);
5 insert into t3 values (seq_t3.nextval);
6 insert into t4 values (seq_t4.nextval);
7 insert into t5 values (seq_t5.nextval);
8 commit;
9 end loop;
10 end;
11 /

PL/SQL 过程已成功完成。

D:oracleora92bin>exp test/test@test9 owner=test file=c:test.dmp consistent=y

Export: Release 9.2.0.1.0 - Production on 星期三 10月 11 14:43:21 2006

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.


连接到: Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production
已导出 ZHS16GBK 字符集和 AL16UTF16 NCHAR 字符集
服务器使用 ZHS16CGB231280 字符集 (可能的字符集转换)

即将导出指定的用户...
. 正在导出 pre-schema 过程对象和操作
. 正在导出用户 TEST 的外部函数库名称
. 导出 PUBLIC 类型同义词
. 导出私有类型同义词
. 正在导出用户 TEST 的对象类型定义
即将导出 TEST 的对象 ...
. 正在导出数据库链接
. 正在导出序号
. 正在导出群集定义
. 即将导出 TEST 的表通过常规路径 ...
. . 正在导出表 T1 11305 行被导出
. . 正在导出表 T2 11305 行被导出
. . 正在导出表 T3 11305 行被导出
. . 正在导出表 T4 11305 行被导出
. . 正在导出表 T5 11305 行被导出
. 正在导出同义词
. 正在导出视图
. 正在导出存储的过程
. 正在导出运算符
. 正在导出引用完整性约束条件
. 正在导出触发器
. 正在导出索引类型
. 正在导出位图, 功能性索引和可扩展索引
. 正在导出后期表活动
. 正在导出实体化视图
. 正在导出快照日志
. 正在导出作业队列
. 正在导出刷新组和子组
. 正在导出维
. 正在导出 post-schema 过程对象和操作
. 正在导出统计
在没有警告的情况下成功终止导出。

SQL> drop user test cascade;

用户已删除。

SQL> grant dba to test identified by test;

授权成功。

D:oracleora92bin>imp test/test@test9 full=y file=c:test.dmp

Import: Release 9.2.0.1.0 - Production on 星期三 10月 11 14:46:50 2006

Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.


连接到: Oracle9i Enterprise Edition Release 9.2.0.1.0 - Production
With the Partitioning, OLAP and Oracle Data Mining options
JServer Release 9.2.0.1.0 - Production

经由常规路径导出由EXPORT:V09.02.00创建的文件
已经完成ZHS16GBK字符集和AL16UTF16 NCHAR 字符集中的导入
导入服务器使用ZHS16CGB231280字符集 (可能的字符集转换)
. 正在将TEST的对象导入到 TEST
. . 正在导入表 "T1" 11305行被导入
. . 正在导入表 "T2" 11305行被导入
. . 正在导入表 "T3" 11305行被导入
. . 正在导入表 "T4" 11305行被导入
. . 正在导入表 "T5" 11305行被导入
成功终止导入,但出现警告。


SQL> conn test/test
已连接。

SQL> select sequence_name,last_number from user_sequences;

SEQUENCE_NAME LAST_NUMBER
------------------------------------------------------------ -----------
SEQ_T1 11307
SEQ_T2 11306
SEQ_T3 11306
SEQ_T4 11306
SEQ_T5 11306


SQL> alter table t1 add primary key (a);

表已更改。

SQL> alter table t2 add primary key (a);

表已更改。

SQL> alter table t3 add primary key (a);

表已更改。

SQL> alter table t4 add primary key (a);

表已更改。

SQL> alter table t5 add primary key (a);

表已更改。

SQL> insert into t1 values (seq_t1.nextval);

已创建 1 行。

SQL> insert into t2 values (seq_t2.nextval);

已创建 1 行。

SQL> insert into t3 values (seq_t3.nextval);

已创建 1 行。

SQL> insert into t4 values (seq_t4.nextval);

已创建 1 行。

SQL> insert into t5 values (seq_t5.nextval);

已创建 1 行。

SQL> commit;

提交完成。

 

转载出处:http://haochunpeng.itpub.net/post/385/220381

在使用 `exp` 命令导出 Oracle 数据库时,如果存在 CLOB 类型的字段,可能会出现报错的情况。这是因为 `exp` 命令默认使用 `varchar2` 类型来处理 CLOB 字段,而 `varchar2` 类型的长度有限制,无法处理过长的 CLOB 字段。 解决这个问题有两种方法: 1. 使用 `expdp` 命令导出数据:`expdp` 命令是 Oracle 数据库的数据泵工具,它可以更好地处理 CLOB 类型的数据。使用 `expdp` 命令导出数据时,需要指定 `CLOB` 类型的列使用二进制格式导出,例如: ``` expdp user/password@database tables=table_name directory=dir dumpfile=file_name.dmp lob_as_segment=y ``` 其中,`lob_as_segment=y` 表示将 `CLOB` 类型的列以二进制格式导出。 2. 修改 `exp` 命令的参数:可以通过修改 `exp` 命令的参数来解决 CLOB 字段报错的问题。具体操作如下: 1. 在 `exp` 命令中添加 `-c` 参数,表示以字符格式导出数据。 2. 在 `exp` 命令中添加 `-lob` 参数,表示导出 CLOB 字段。 3. 修改 `NLS_LANG` 环境变量,将其设为 `AMERICAN_AMERICA.AL32UTF8`,表示使用 UTF-8 编码。 示例命令如下: ``` exp user/password@database tables=table_name file=file_name.dmp log=log_name.log rows=yes compress=no direct=no indexes=no triggers=no constraints=no grants=no feedback=1000000 buffer=1000000 consistent=y commit=y statistics=none object_consistent=y recordlength=65535 consistent=y full=y rows=y constraints=n indexes=n grants=n triggers=n feedback=1000000 buffer=1000000 file=file_name.dmp log=log_name.log compress=n consistent=y direct=n rows=y statistics=none file_size=unlimited consistent=y file_name_convert=old_dir:new_dir -c -lob -NLS_LANG=AMERICAN_AMERICA.AL32UTF8 ``` 注意,修改 `NLS_LANG` 环境变量可能会影响其他程序的运行,需要谨慎操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值