實驗:Oracle數據泵導出導入之序列問題


今天同事提出了一個問題:
使用數據泵expdp導出1個schema,有個表主鍵是觸發器自增的id,導入測試庫測試時,發現表里的數據比自增序列的值要大。導致插入數據報錯。
最終結論是:
由於數據庫先進行序列導出,然后再進行表數據導出。然后在導出的過程中,該表一直有插入操作,最終導致了這種差異。
解決方法:
重建觸發器中的序列,讓序列的開始值為表主鍵最大值+1。

下面我構造實驗完整演示下這種場景。

1.准備測試環境

需要建立測試表,序列,觸發器和模擬業務插入數據的存儲過程。 以下是實際的創建語句:
--在測試用戶jingyu下創建測試表book2
drop table book2 purge;
create table book2(       
   bookId number(10) primary key,   
   name varchar2(20)         
); 

--創建序列  
drop sequence book2_seq;    
create sequence book2_seq start with 1 increment by 1;    
  
--創建觸發器      
create or replace trigger book2_trigger       
before insert on book2     
for each row       
begin       
select book2_seq.nextval into :new.bookId from dual;      
end ;  
/ 

--創建實現循環添加數據的存儲過程

/*
--存儲過程中使用需要顯示賦權
grant execute on dbms_lock to jingyu;
*/

create or replace procedure proc_insert_book2 is
begin
  loop
    insert into book2(name) values ('xx');
    commit;
    dbms_lock.sleep(1);
  end loop;
end;
/

2.開始模擬該表不斷插入

由於我這里實際使用的是死循環,所以只要開始執行存儲過程,每秒都會向測試表插入1條測試數據,直到手工停止。

--執行該存儲過程
exec proc_insert_book2;

--查詢表的數量,確認是每秒多一條數據
select count(*) from book2;

3.進行數據泵導出操作

確認導出目錄,編寫expdp導出語句,最終將jingyu這個schema導出。實際命令如下:
--expdp 導出
create or replace directory jy as '/opt/app/orabak/';
expdp jingyu/jingyu directory=jy dumpfile=jingyu.dmp schemas=jingyu

實際執行導出的輸出如下:

[oracle@jyrac1 orabak]$ expdp jingyu/jingyu directory=jy dumpfile=jingyu.dmp schemas=jingyu

Export: Release 11.2.0.4.0 - Production on Thu Jun 8 17:08:29 2017

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
Starting "JINGYU"."SYS_EXPORT_SCHEMA_05":  jingyu/******** directory=jy dumpfile=jingyu.dmp schemas=jingyu 
Estimate in progress using BLOCKS method...
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
Total estimation using BLOCKS method: 10.12 MB
Processing object type SCHEMA_EXPORT/USER
Processing object type SCHEMA_EXPORT/SYSTEM_GRANT
Processing object type SCHEMA_EXPORT/ROLE_GRANT
Processing object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing object type SCHEMA_EXPORT/TABLESPACE_QUOTA
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/SEQUENCE/SEQUENCE
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/COMMENT
Processing object type SCHEMA_EXPORT/PROCEDURE/PROCEDURE
Processing object type SCHEMA_EXPORT/PROCEDURE/ALTER_PROCEDURE
Processing object type SCHEMA_EXPORT/TABLE/INDEX/INDEX
Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Processing object type SCHEMA_EXPORT/TABLE/TRIGGER
Processing object type SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
. . exported "JINGYU"."T2"                               6.649 MB  100000 rows
. . exported "JINGYU"."SYS_EXPORT_SCHEMA_01"             142.0 KB    1195 rows
. . exported "JINGYU"."SYS_EXPORT_SCHEMA_02"             142.2 KB    1196 rows
. . exported "JINGYU"."SYS_EXPORT_SCHEMA_03"             142.6 KB    1198 rows
. . exported "JINGYU"."SYS_EXPORT_SCHEMA_04"             149.7 KB    1201 rows
. . exported "JINGYU"."T_OLD"                            160.8 KB   20000 rows
. . exported "JINGYU"."T"                                82.94 KB   10000 rows
. . exported "JINGYU"."T_NOLOG"                          51.53 KB    5998 rows
. . exported "JINGYU"."BOOK"                             5.421 KB       2 rows
. . exported "JINGYU"."BOOK2"                            6.734 KB     123 rows
. . exported "JINGYU"."EMP"                              8.562 KB      14 rows
. . exported "JINGYU"."T1"                               11.75 KB     100 rows
Master table "JINGYU"."SYS_EXPORT_SCHEMA_05" successfully loaded/unloaded
******************************************************************************
Dump file set for JINGYU.SYS_EXPORT_SCHEMA_05 is:
  /opt/app/orabak/jingyu.dmp
Job "JINGYU"."SYS_EXPORT_SCHEMA_05" successfully completed at Thu Jun 8 17:10:26 2017 elapsed 0 00:01:36

4.進行數據泵導入操作

將上一步的導出文件,導入到另一個新建的測試用戶jingyu2下。實際命令如下:
--創建測試用戶並賦予一定的權限
create user jingyu2 identified by jingyu2 default tablespace dbs_d_jingyu;
grant connect, resource to jingyu2;

--impdp 導入到用戶jingyu2
impdp jingyu/jingyu directory=jy dumpfile=jingyu.dmp REMAP_SCHEMA=jingyu:jingyu2

實際執行導入的輸出如下:

[oracle@jyrac1 orabak]$ impdp jingyu/jingyu directory=jy dumpfile=jingyu.dmp REMAP_SCHEMA=jingyu:jingyu2

Import: Release 11.2.0.4.0 - Production on Thu Jun 8 17:11:21 2017

Copyright (c) 1982, 2011, Oracle and/or its affiliates.  All rights reserved.

Connected to: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 - 64bit Production
With the Partitioning, Real Application Clusters, Automatic Storage Management, OLAP,
Data Mining and Real Application Testing options
Master table "JINGYU"."SYS_IMPORT_FULL_01" successfully loaded/unloaded
Starting "JINGYU"."SYS_IMPORT_FULL_01":  jingyu/******** directory=jy dumpfile=jingyu.dmp REMAP_SCHEMA=jingyu:jingyu2 
Processing object type SCHEMA_EXPORT/USER
ORA-31684: Object type USER:"JINGYU2" already exists
Processing object type SCHEMA_EXPORT/SYSTEM_GRANT
Processing object type SCHEMA_EXPORT/ROLE_GRANT
Processing object type SCHEMA_EXPORT/DEFAULT_ROLE
Processing object type SCHEMA_EXPORT/TABLESPACE_QUOTA
Processing object type SCHEMA_EXPORT/PRE_SCHEMA/PROCACT_SCHEMA
Processing object type SCHEMA_EXPORT/SEQUENCE/SEQUENCE
Processing object type SCHEMA_EXPORT/TABLE/TABLE
Processing object type SCHEMA_EXPORT/TABLE/TABLE_DATA
. . imported "JINGYU2"."T2"                              6.649 MB  100000 rows
. . imported "JINGYU2"."SYS_EXPORT_SCHEMA_01"            142.0 KB    1195 rows
. . imported "JINGYU2"."SYS_EXPORT_SCHEMA_02"            142.2 KB    1196 rows
. . imported "JINGYU2"."SYS_EXPORT_SCHEMA_03"            142.6 KB    1198 rows
. . imported "JINGYU2"."SYS_EXPORT_SCHEMA_04"            149.7 KB    1201 rows
. . imported "JINGYU2"."T_OLD"                           160.8 KB   20000 rows
. . imported "JINGYU2"."T"                               82.94 KB   10000 rows
. . imported "JINGYU2"."T_NOLOG"                         51.53 KB    5998 rows
. . imported "JINGYU2"."BOOK"                            5.421 KB       2 rows
. . imported "JINGYU2"."BOOK2"                           6.734 KB     123 rows
. . imported "JINGYU2"."EMP"                             8.562 KB      14 rows
. . imported "JINGYU2"."T1"                              11.75 KB     100 rows
Processing object type SCHEMA_EXPORT/TABLE/COMMENT
Processing object type SCHEMA_EXPORT/PROCEDURE/PROCEDURE
Processing object type SCHEMA_EXPORT/PROCEDURE/ALTER_PROCEDURE
ORA-39082: Object type ALTER_PROCEDURE:"JINGYU2"."PRO_SELECT" created with compilation warnings
ORA-39082: Object type ALTER_PROCEDURE:"JINGYU2"."PROC_INSERT_BOOK2" created with compilation warnings
Processing object type SCHEMA_EXPORT/TABLE/INDEX/INDEX
Processing object type SCHEMA_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
Processing object type SCHEMA_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
Processing object type SCHEMA_EXPORT/TABLE/TRIGGER
Processing object type SCHEMA_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
Job "JINGYU"."SYS_IMPORT_FULL_01" completed with 3 error(s) at Thu Jun 8 17:11:52 2017 elapsed 0 00:00:26

導入完成,但存在一些警告,與本實驗有關的只有"JINGYU2"."PROC_INSERT_BOOK2" 編輯警告需要處理,在下面的步驟中詳細說明。

5.問題現象重現並解決

**問題現象重現:** 查詢到表最大的BOOKID大於序列的當前值,具體情況如下:
SQL> select max(BOOKID) from book2;

MAX(BOOKID)
-----------
        505

SQL> select book2_seq.currval from dual;
select book2_seq.currval from dual
                              *
ERROR at line 1:
ORA-08002: sequence BOOK2_SEQ.CURRVAL is not yet defined in this session


SQL> select book2_seq.nextval from dual;

   NEXTVAL
----------
       341

導入的存儲過程存在編譯警告的問題,排查原因是權限問題,需要先處理下:

--執行存儲過程報錯對象無效
SQL> exec proc_insert_book2
BEGIN proc_insert_book2; END;

      *
ERROR at line 1:
ORA-06550: line 1, column 7:
PLS-00905: object JINGYU2.PROC_INSERT_BOOK2 is invalid
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

--重新編譯存儲過程依然有錯誤
SQL> alter procedure proc_insert_book2 compile;

Warning: Procedure altered with compilation errors.

--顯示具體的錯誤
SQL> show errors
Errors for PROCEDURE PROC_INSERT_BOOK2:

LINE/COL ERROR
-------- -----------------------------------------------------------------
6/5      PL/SQL: Statement ignored
6/5      PLS-00201: identifier 'DBMS_LOCK' must be declared

--根據錯誤提示,賦權解決
SQL> show user
USER is "SYS"
SQL> grant execute on dbms_lock to jingyu2;

Grant succeeded.

--再次編譯成功
SQL> alter procedure proc_insert_book2 compile;

Procedure altered.

編譯存儲過程成功后,執行它模擬插入數據,意料之中的會報錯:

SQL> exec proc_insert_book2
BEGIN proc_insert_book2; END;

*
ERROR at line 1:
ORA-00001: unique constraint (JINGYU2.SYS_C0011351) violated
ORA-06512: at "JINGYU2.PROC_INSERT_BOOK2", line 4
ORA-06512: at line 1

--查詢測試表主鍵bookid的最大值
SQL> select max(bookid) from book2;

MAX(BOOKID)
-----------
        505

重新創建序列,序列開始值設置為MAX(BOOKID)+1,再次執行就可以正常插入了。
重新創建序列的語句如下:

--重新創建序列  
drop sequence book2_seq;    
create sequence book2_seq start with 506 increment by 1;    

至此,整個實驗完成。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM