कैसे बरकरार डेटा को अलग करके ORA-01410 से छुटकारा पाएं

एक समय में, मैंने इस कार्य पर गंभीरता से अपना हाथ पकड़ा - कई तालिकाओं के लिए, संपीड़न और ओरेकल बग के परिणामस्वरूप, कई लाइनें टूट गईं। परिणामस्वरूप, ऐसी तालिकाओं के लिए फुलस्कैन का उपयोग करने वाले उपयोगकर्ताओं को ORA-01410 प्राप्त हुआ।
सबसे कठिन मामले पर विचार करें - जब कोई बैकअप या इंडेक्स नहीं हैं (इस मामले में, अनुक्रमित कॉलम को इंडेक्स द्वारा स्कैन करके प्राप्त किया जा सकता है)। इस मामले में, एकमात्र विकल्प समस्याग्रस्त ROWID को ढूंढना है और इसे दो पक्षों से "चारों ओर जाना" है, जो अखंड डेटा को अलग करता है।

स्रोत डेटा प्राप्त करने के लिए सबसे पहले, हम समस्याग्रस्त अनुरोध के ट्रेस को हटा देंगे:
alter session set db_file_multiblock_read_count=1; alter session set events 'immediate trace name trace_buffer_on level 1048576'; alter session set events '10200 trace name context forever, level 1'; alter session set events '1410 trace name errorstack forever, level 10'; alter session set tracefile_identifier='ORA1410'; 


और समस्या अनुरोध चलाएँ
 select count(1) from test.testtable; 

हम इस तरह से ट्रेस में एक रिकॉर्ड पाते हैं:
 ktrget2(): started for block <0x0645 : 0x3ce2c85b> objd: 0x00f842bb env: (scn: 0x0a21.9a61c1d8 xid: 0x0000.000.00000000 uba: 0x00000000.0000.00 statement num=0 parent xid: xid: 0x0000.000.00000000 scn: 0x0000.00000000 96sch: scn: 0x0000.00000000 mascn: (scn: 0x0a1f.ccec0b27) OBJD MISMATCH typ=6, seg.obj=16270011, diskobj=16268354, dsflg=100001, dsobj=16270011, tid=16270011, cls=1 


प्राप्त मूल्य के आधार पर, हमें Block_number और Relative_fno मिलता है:
 select dbms_utility.data_block_address_file(to_number('3ce2c85b', 'xxxxxxxx')) file#, dbms_utility.data_block_address_block(to_number('3ce2c85b', 'xxxxxxxx')) block# from dual; FILE# BLOCK# 243 2279515 


इसके अतिरिक्त, हम समस्या के data_object_id को पाते हैं:
 select data_object_id from dba_objects where owner = 'test' and object_name = 'testtable'; data_object_id ---------------------- 16402245 


प्राप्त मूल्यों के आधार पर, हम एक ROWID बनाते हैं:
 select dbms_rowid.rowid_create(rowid_type => 1,object_number => 16402245,relative_fno => 243,block_number => 2279515,row_number => 0) from dual; ROWID=AA+kdFADzAAIshbAAA 

ठीक है, वास्तव में, मैंने शुरुआत में क्या उल्लेख किया है - हम सभी तरफ से समस्या रेखा के चारों ओर जाते हैं:
 insert into test.testtable_nocorrupt select /*parallel(8)*/ * from test.testtable where rowid<'AA+EK7ADzAAIshbAAA'; insert into test.testtable_nocorrupt select /*parallel(8)*/ * from test.testtable where rowid>='AA+EK7ADzAAIshcAAA'; 


मैं यह नोट करना चाहूंगा कि db_block_checking / db_block_checksum = 'Full' या db_ultra_safe = 'data_and_index_ DB पैरामीटर सेट, जो प्रोसेसर को कुछ हद तक लोड करेगा (~ 5%, हालांकि इस पर चर्चा की जाती है), लेकिन ऐसी समस्याओं से बचा जा सकता है। अतिरिक्त विश्वसनीयता होगी।

Metalink के इस्तेमाल किए गए नोट:
Oracle8 में ROWID रेंज स्कैन्स का उपयोग करके एक भ्रष्ट तालिका से डेटा निकालना और उच्चतर [आईडी 61685.1]
OERR: ORA-8103 "वस्तु अब मौजूद नहीं है" / समस्या निवारण, निदान और समाधान [आईडी 8103.1]

Source: https://habr.com/ru/post/In155075/


All Articles