關於操作失誤的資料修復
在系統升級的過程中,準備了大量的指令碼,分成幾個視窗來分別執行。
在碰到問題的時候,一定要很細心和冷靜,不經意的錯誤可以需要幾倍,幾十倍的努力來挽回。
準生產環境中有一個表。TREATMENT_ACTIVITY,現在需要從另外一個臨時的schema中insert一部分資料。
Name Null? Type
----------------------------------------- -------- ----------------------------
ENTITY_KEY NOT NULL NUMBER(4)
ENTITY_ID NOT NULL NUMBER(9)
ENTITY_TYPE NOT NULL VARCHAR2(10)
ACTIVITY_CODE NOT NULL VARCHAR2(25)
ACTIVITY_DATE NOT NULL TIMESTAMP(6)
SYS_CREATION_DATE NOT NULL DATE
SYS_UPDATE_DATE DATE
OPERATOR_ID NUMBER(9)
APPLICATION_ID CHAR(6)
DL_SERVICE_CODE CHAR(5)
DL_UPDATE_STAMP NUMBER(4)
APPROVAL_INDICATOR CHAR(1)
MEMO_ID NOT NULL VARCHAR2(100)
REASON_CODE NOT NULL VARCHAR2(6)
STEP_ID VARCHAR2(31)
POLICY_CODE VARCHAR2(128)
PA_IND CHAR(1)
值得一提的是,這個表沒有主鍵,只建立了一些相關的索引,但是執行的時候發現資料有很大的偏差。
插入資料前,有500多萬,需要插入資料400多萬,預計資料應該是1千萬,但是實際卻是1千五百萬。
Initial data of this on before import : 5747945
Data imported from temp schema: 4662877
so we expected to see : 10410822
But the count of this table after imported is 15073699
最後經過測試發現,是在使用Nohup執行一個批次指令碼後,發現有一個表執行的很慢,就手動kill掉了session.手工插入,結果這個插入操作還在後臺執行,結果手工又執行了一遍,因為沒有主鍵,所以沒有發現任何異常,做最後的資料統計的時候才發現。
找到了問題的原因,想把多餘的資料刪除。
首先嚐試使用如下的方式來檢視資料條數。但是竟然給我返回了0條資料。
SQL> select count(*) from TREATMENT_ACTIVITY where (
ENTITY_KEY ,
ENTITY_ID ,
ENTITY_TYPE ,
ACTIVITY_CODE ,
ACTIVITY_DATE ,
SYS_CREATION_DATE ,
SYS_UPDATE_DATE ,
OPERATOR_ID ,
APPLICATION_ID ,
DL_SERVICE_CODE ,
DL_UPDATE_STAMP ,
APPROVAL_INDICATOR ,
MEMO_ID ,
REASON_CODE ,
STEP_ID ,
POLICY_CODE ,
PA_IND ) in (select
19 ENTITY_KEY ,
ENTITY_ID ,
ENTITY_TYPE ,
ACTIVITY_CODE ,
ACTIVITY_DATE ,
SYS_CREATION_DATE ,
SYS_UPDATE_DATE ,
OPERATOR_ID ,
APPLICATION_ID ,
DL_SERVICE_CODE ,
DL_UPDATE_STAMP ,
APPROVAL_INDICATOR ,
MEMO_ID ,
REASON_CODE ,
STEP_ID ,
POLICY_CODE ,
PA_IND from mig_tmp.TREATMENT_ACTIVITY_ext)
/
COUNT(*)
----------
0
我是明明知道資料有重複,但是檢視卻匹配不出來。那使用rowid來做一把測試。
select count(*) from dr_TREATMENT_ACTIVITY t1 where t1.rowid != (select max(rowid) from dr_TREATMENT_ACTIVITY t2
where t1.ENTITY_KEY = t2.ENTITY_KEY
and t1.ENTITY_ID = t2.ENTITY_ID
and t1.ENTITY_TYPE = t2.ENTITY_TYPE
and t1.ACTIVITY_CODE = t2.ACTIVITY_CODE
and t1.ACTIVITY_DATE = t2.ACTIVITY_DATE
and t1.SYS_CREATION_DATE = t2.SYS_CREATION_DATE
and t1.SYS_UPDATE_DATE = t2.SYS_UPDATE_DATE
and t1.OPERATOR_ID = t2.OPERATOR_ID
and t1.APPLICATION_ID = t2.APPLICATION_ID
and t1.DL_SERVICE_CODE = t2.DL_SERVICE_CODE
and t1.DL_UPDATE_STAMP = t2.DL_UPDATE_STAMP
and t1.APPROVAL_INDICATOR = t2.APPROVAL_INDICATOR
and t1.MEMO_ID = t2.MEMO_ID
and t1.REASON_CODE = t2.REASON_CODE
and t1.STEP_ID = t2.STEP_ID
and t1.POLICY_CODE = t2.POLICY_CODE
and t1.PA_IND = t2.PA_IND )
COUNT(*)
----------
0
最後靈機一動,拼成一個字串來。
SQL> select count(*) from TREATMENT_ACTIVITY where (
2 ENTITY_KEY ||
3 ENTITY_ID ||
ENTITY_TYPE ||
ACTIVITY_CODE ||
ACTIVITY_DATE ||
SYS_CREATION_DATE ||
SYS_UPDATE_DATE ||
OPERATOR_ID ||
APPLICATION_ID ||
DL_SERVICE_CODE ||
DL_UPDATE_STAMP ||
APPROVAL_INDICATOR ||
MEMO_ID ||
REASON_CODE ||
STEP_ID ||
POLICY_CODE ||
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 PA_IND ) in (select
19 ENTITY_KEY ||
ENTITY_ID ||
ENTITY_TYPE ||
ACTIVITY_CODE ||
ACTIVITY_DATE ||
SYS_CREATION_DATE ||
SYS_UPDATE_DATE ||
OPERATOR_ID ||
APPLICATION_ID ||
DL_SERVICE_CODE ||
DL_UPDATE_STAMP ||
APPROVAL_INDICATOR ||
MEMO_ID ||
REASON_CODE ||
20 21 22 23 24 25 26 27 28 29 30 31 32 33 STEP_ID ||
34 POLICY_CODE ||
PA_IND from mig_tmp.TREATMENT_ACTIVITY_ext) 35
36 /
COUNT(*)
----------
9325754
Elapsed: 00:01:41.22
這樣就可以直接使用delete來先刪除重複插入的資料。然後重新插入。
delete from TREATMENT_ACTIVITY where (
ENTITY_KEY ||
ENTITY_ID ||
ENTITY_TYPE ||
ACTIVITY_CODE ||
ACTIVITY_DATE ||
SYS_CREATION_DATE ||
SYS_UPDATE_DATE ||
OPERATOR_ID ||
APPLICATION_ID ||
DL_SERVICE_CODE ||
DL_UPDATE_STAMP ||
APPROVAL_INDICATOR ||
MEMO_ID ||
REASON_CODE ||
STEP_ID ||
POLICY_CODE ||
PA_IND ) in (select
ENTITY_KEY ||
ENTITY_ID ||
ENTITY_TYPE ||
ACTIVITY_CODE ||
ACTIVITY_DATE ||
SYS_CREATION_DATE ||
SYS_UPDATE_DATE ||
OPERATOR_ID ||
APPLICATION_ID ||
DL_SERVICE_CODE ||
DL_UPDATE_STAMP ||
APPROVAL_INDICATOR ||
MEMO_ID ||
REASON_CODE ||
STEP_ID ||
POLICY_CODE ||
PA_IND from mig_tmp.TREATMENT_ACTIVITY_ext)
9325754 rows deleted.
SQL> create table test(id number,name varchar2(10));
insert into test values(1,null);
insert into test values(2,1);
insert into test values(3,1)
create table test2 (id number,name varchar2(10));
insert into test values(1,null);
insert into test values(2,1);
insert into test values(3,1)
Table created.
SQL>
1 row created.
SQL>
1 row created.
SQL> 2 SQL>
Table created.
SQL>
1 row created.
SQL>
1 row created.
SQL>
現在我們來使用相同的方式來查詢。可以看到根本的原因就是null
SQL> select count(*)from test where (id,name) in (select id,name from test2)
2 /
COUNT(*)
----------
0
在碰到問題的時候,一定要很細心和冷靜,不經意的錯誤可以需要幾倍,幾十倍的努力來挽回。
準生產環境中有一個表。TREATMENT_ACTIVITY,現在需要從另外一個臨時的schema中insert一部分資料。
Name Null? Type
----------------------------------------- -------- ----------------------------
ENTITY_KEY NOT NULL NUMBER(4)
ENTITY_ID NOT NULL NUMBER(9)
ENTITY_TYPE NOT NULL VARCHAR2(10)
ACTIVITY_CODE NOT NULL VARCHAR2(25)
ACTIVITY_DATE NOT NULL TIMESTAMP(6)
SYS_CREATION_DATE NOT NULL DATE
SYS_UPDATE_DATE DATE
OPERATOR_ID NUMBER(9)
APPLICATION_ID CHAR(6)
DL_SERVICE_CODE CHAR(5)
DL_UPDATE_STAMP NUMBER(4)
APPROVAL_INDICATOR CHAR(1)
MEMO_ID NOT NULL VARCHAR2(100)
REASON_CODE NOT NULL VARCHAR2(6)
STEP_ID VARCHAR2(31)
POLICY_CODE VARCHAR2(128)
PA_IND CHAR(1)
值得一提的是,這個表沒有主鍵,只建立了一些相關的索引,但是執行的時候發現資料有很大的偏差。
插入資料前,有500多萬,需要插入資料400多萬,預計資料應該是1千萬,但是實際卻是1千五百萬。
Initial data of this on before import : 5747945
Data imported from temp schema: 4662877
so we expected to see : 10410822
But the count of this table after imported is 15073699
最後經過測試發現,是在使用Nohup執行一個批次指令碼後,發現有一個表執行的很慢,就手動kill掉了session.手工插入,結果這個插入操作還在後臺執行,結果手工又執行了一遍,因為沒有主鍵,所以沒有發現任何異常,做最後的資料統計的時候才發現。
找到了問題的原因,想把多餘的資料刪除。
首先嚐試使用如下的方式來檢視資料條數。但是竟然給我返回了0條資料。
SQL> select count(*) from TREATMENT_ACTIVITY where (
ENTITY_KEY ,
ENTITY_ID ,
ENTITY_TYPE ,
ACTIVITY_CODE ,
ACTIVITY_DATE ,
SYS_CREATION_DATE ,
SYS_UPDATE_DATE ,
OPERATOR_ID ,
APPLICATION_ID ,
DL_SERVICE_CODE ,
DL_UPDATE_STAMP ,
APPROVAL_INDICATOR ,
MEMO_ID ,
REASON_CODE ,
STEP_ID ,
POLICY_CODE ,
PA_IND ) in (select
19 ENTITY_KEY ,
ENTITY_ID ,
ENTITY_TYPE ,
ACTIVITY_CODE ,
ACTIVITY_DATE ,
SYS_CREATION_DATE ,
SYS_UPDATE_DATE ,
OPERATOR_ID ,
APPLICATION_ID ,
DL_SERVICE_CODE ,
DL_UPDATE_STAMP ,
APPROVAL_INDICATOR ,
MEMO_ID ,
REASON_CODE ,
STEP_ID ,
POLICY_CODE ,
PA_IND from mig_tmp.TREATMENT_ACTIVITY_ext)
/
COUNT(*)
----------
0
我是明明知道資料有重複,但是檢視卻匹配不出來。那使用rowid來做一把測試。
select count(*) from dr_TREATMENT_ACTIVITY t1 where t1.rowid != (select max(rowid) from dr_TREATMENT_ACTIVITY t2
where t1.ENTITY_KEY = t2.ENTITY_KEY
and t1.ENTITY_ID = t2.ENTITY_ID
and t1.ENTITY_TYPE = t2.ENTITY_TYPE
and t1.ACTIVITY_CODE = t2.ACTIVITY_CODE
and t1.ACTIVITY_DATE = t2.ACTIVITY_DATE
and t1.SYS_CREATION_DATE = t2.SYS_CREATION_DATE
and t1.SYS_UPDATE_DATE = t2.SYS_UPDATE_DATE
and t1.OPERATOR_ID = t2.OPERATOR_ID
and t1.APPLICATION_ID = t2.APPLICATION_ID
and t1.DL_SERVICE_CODE = t2.DL_SERVICE_CODE
and t1.DL_UPDATE_STAMP = t2.DL_UPDATE_STAMP
and t1.APPROVAL_INDICATOR = t2.APPROVAL_INDICATOR
and t1.MEMO_ID = t2.MEMO_ID
and t1.REASON_CODE = t2.REASON_CODE
and t1.STEP_ID = t2.STEP_ID
and t1.POLICY_CODE = t2.POLICY_CODE
and t1.PA_IND = t2.PA_IND )
COUNT(*)
----------
0
最後靈機一動,拼成一個字串來。
SQL> select count(*) from TREATMENT_ACTIVITY where (
2 ENTITY_KEY ||
3 ENTITY_ID ||
ENTITY_TYPE ||
ACTIVITY_CODE ||
ACTIVITY_DATE ||
SYS_CREATION_DATE ||
SYS_UPDATE_DATE ||
OPERATOR_ID ||
APPLICATION_ID ||
DL_SERVICE_CODE ||
DL_UPDATE_STAMP ||
APPROVAL_INDICATOR ||
MEMO_ID ||
REASON_CODE ||
STEP_ID ||
POLICY_CODE ||
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 PA_IND ) in (select
19 ENTITY_KEY ||
ENTITY_ID ||
ENTITY_TYPE ||
ACTIVITY_CODE ||
ACTIVITY_DATE ||
SYS_CREATION_DATE ||
SYS_UPDATE_DATE ||
OPERATOR_ID ||
APPLICATION_ID ||
DL_SERVICE_CODE ||
DL_UPDATE_STAMP ||
APPROVAL_INDICATOR ||
MEMO_ID ||
REASON_CODE ||
20 21 22 23 24 25 26 27 28 29 30 31 32 33 STEP_ID ||
34 POLICY_CODE ||
PA_IND from mig_tmp.TREATMENT_ACTIVITY_ext) 35
36 /
COUNT(*)
----------
9325754
Elapsed: 00:01:41.22
這樣就可以直接使用delete來先刪除重複插入的資料。然後重新插入。
delete from TREATMENT_ACTIVITY where (
ENTITY_KEY ||
ENTITY_ID ||
ENTITY_TYPE ||
ACTIVITY_CODE ||
ACTIVITY_DATE ||
SYS_CREATION_DATE ||
SYS_UPDATE_DATE ||
OPERATOR_ID ||
APPLICATION_ID ||
DL_SERVICE_CODE ||
DL_UPDATE_STAMP ||
APPROVAL_INDICATOR ||
MEMO_ID ||
REASON_CODE ||
STEP_ID ||
POLICY_CODE ||
PA_IND ) in (select
ENTITY_KEY ||
ENTITY_ID ||
ENTITY_TYPE ||
ACTIVITY_CODE ||
ACTIVITY_DATE ||
SYS_CREATION_DATE ||
SYS_UPDATE_DATE ||
OPERATOR_ID ||
APPLICATION_ID ||
DL_SERVICE_CODE ||
DL_UPDATE_STAMP ||
APPROVAL_INDICATOR ||
MEMO_ID ||
REASON_CODE ||
STEP_ID ||
POLICY_CODE ||
PA_IND from mig_tmp.TREATMENT_ACTIVITY_ext)
9325754 rows deleted.
Elapsed: 00:02:24.24
SQL> commit;
Commit complete.
SQL> insert into TREATMENT_ACTIVITY select *from mig_tmp.TREATMENT_ACTIVITY_ext;
4662877 rows created.
Elapsed: 00:00:18.44
SQL> commit;
Commit complete.
這樣資料就能完全對上了。這個問題根本原因就是null導致的。可以使用如下的例子來簡單演示一下。SQL> commit;
Commit complete.
SQL> insert into TREATMENT_ACTIVITY select *from mig_tmp.TREATMENT_ACTIVITY_ext;
4662877 rows created.
Elapsed: 00:00:18.44
SQL> commit;
Commit complete.
SQL> create table test(id number,name varchar2(10));
insert into test values(1,null);
insert into test values(2,1);
insert into test values(3,1)
create table test2 (id number,name varchar2(10));
insert into test values(1,null);
insert into test values(2,1);
insert into test values(3,1)
Table created.
SQL>
1 row created.
SQL>
1 row created.
SQL> 2 SQL>
Table created.
SQL>
1 row created.
SQL>
1 row created.
SQL>
現在我們來使用相同的方式來查詢。可以看到根本的原因就是null
SQL> select count(*)from test where (id,name) in (select id,name from test2)
2 /
COUNT(*)
----------
0
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8494287/viewspace-1347077/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 伺服器資料恢復-誤操作導致mysql資料庫資料丟失的資料恢復案例伺服器資料恢復MySql資料庫
- 【北亞資料庫資料恢復】誤操作導致資料丟失的華為雲mysql資料恢復案例資料庫資料恢復MySql
- 【北亞資料恢復】誤操作分割槽損壞導致SqlServer資料庫資料丟失的資料恢復資料恢復SQLServer資料庫
- TSPITR方式資料庫找回誤操作丟失的資料資料庫
- 【oracle資料庫資料恢復】誤操作導致的資料庫誤刪除的資料恢復案例Oracle資料庫資料恢復
- DG修復:異常關庫導致的資料庫啟動失敗ORA-01110及GAP修復資料庫
- 【資料庫資料恢復】LINUX EXT3檔案系統下ORACLE資料庫誤操作導致資料丟失的資料恢復案例資料庫資料恢復LinuxOracle
- 【儲存資料恢復案例】Netapp誤操作刪除lun的資料恢復資料恢復APP
- 【伺服器虛擬化資料恢復】ESXI虛擬機器誤操作還原快照導致資料丟失的資料恢復案例伺服器資料恢復虛擬機
- 基於GTID恢復誤篡改資料
- redis cluster 故障後,主從位於相同節點的修復(丟失了部分資料)Redis
- 達夢資料庫關於[-70028]:建立SOCKET連線失敗的錯誤原因資料庫
- 關於SqlServer資料表操作SQLServer
- 如何修復帶有問號錯誤的 Mac 資料夾Mac
- 資料庫修復資料恢復資料庫資料恢復
- 關於資料抓取很多新人的誤區
- 【北亞資料恢復】vmfs還原快照操作導致SqlServer資料庫資料丟失的資料恢復資料恢復SQLServer資料庫
- 伺服器資料恢復—NTFS誤操作刪除/格式化的資料恢復案例伺服器資料恢復
- 關於流資料上的事務操作
- .NET關於資料庫操作的類-囊括所有的操作資料庫
- 基於linux系統,fsck後資料丟失的資料恢復方案Linux資料恢復
- 修復由於主庫NOLOGGING操作引起的備庫ORA-01578和ORA-26040錯誤
- 【伺服器資料恢復】伺服器誤刪除導致郵件資料丟失的資料恢復案例伺服器資料恢復
- 誤操作還原VMware虛擬機器資料恢復虛擬機資料恢復
- 【伺服器資料恢復】XenServer虛擬機器被誤操作刪除的資料恢復案例伺服器資料恢復Server虛擬機
- 勒索病毒資料修復恢復
- 如何修復“包 ‘%@’ 丟失或無效”macOS Monterey 升級錯誤Mac
- Interbase資料庫修復資料庫
- Firebird資料庫修復資料庫
- 【北亞資料恢復】伺服器誤刪除卷導致raid5陣列資料丟失的資料恢復資料恢復伺服器AI陣列
- 【vsan資料恢復】vsan資料重構失敗的資料恢復案例資料恢復
- 【北亞資料恢復】誤操作導致雲伺服器表被truncate,表內資料被delete的資料恢復資料恢復伺服器delete
- 【資料庫資料恢復】透過恢復NDF檔案修復資料庫的資料恢復過程資料庫資料恢復
- win10更新失敗出現錯誤程式碼80070570修復方法Win10
- 【資料庫資料恢復】誤truncate table的Oracle資料庫資料恢復方案資料庫資料恢復Oracle
- 【資料庫資料恢復】Oracle資料庫誤truncate table的資料恢復案例資料庫資料恢復Oracle
- SQL Server誤區30日談-Day16-資料的損壞和修復SQLServer
- 如何修復mysql資料庫MySql資料庫
- 關於 iconv 轉碼導致資料丟失的問題