Gần đây tôi đang làm việc với một số lỗi khối dữ liệu và tôi cần phải kết xuất một số khối dữ liệu để xác minh nội dung của nó. Tôi đã phải phủi một tờ giấy mà tôi đã viết cách đây rất lâu chỉ dẫn cách thực hiện điều này. Sau đây là một phần của bài báo đó:
Để kết xuất một khối thuộc một bảng, bạn sẽ cần biết số tệp và số khối của khối đó. Nếu bạn đã biết số tệp và khối, thì bạn đã sẵn sàng. Nếu bạn không biết số tệp và khối, bạn có thể truy vấn DBA_EXTENTS để biết thông tin đó. Bây giờ chúng ta biết tệp và khối nào chứa bảng của chúng ta, hãy kết xuất một khối mẫu của bảng. Điều này được thực hiện như sau:
ORA9I SQL> thay đổi tệp dữ liệu kết xuất hệ thống 3 khối 10;
Hệ thống đã thay đổi.
Bạn có thể kết xuất một loạt các khối bằng lệnh sau:
ORA9I SQL> thay đổi tệp dữ liệu kết xuất hệ thống 3 khối tối thiểu 10 khối tối đa 12;
Hệ thống đã thay đổi.
Bây giờ chúng ta hãy xem xét nội dung của việc kết xuất một khối.
Bắt đầu kết xuất khối dữ liệu tsn:3 tệp #:3 minblk 10 maxblk 10
bộ đệm tsn:3 rdba:0x00c0000a (3/10)
scn:0x0000.00046911 seq:0x02 flg:0x04 tail :0x69110602
frmt:0x02 chkval:0x579d type:0x06 =trans data
Block header dump:0x00c0000a
Object id trên Block? Y
seg / obj:0x6d9c csc:0x00.46911 itc:2 flg:O typ:1 - DATA
fsl:0 fnx:0x0 ver:0x01
Itl Xid Uba Flag Lck Scn / Fsc
0x01 xid:0x0005.02f.0000010c uba:0x00806f10.00ca.28 C --- 0 scn 0x0000.00046900
0x02 xid:0x0003.01c. 00000101 uba:0x00800033.0099.04 C --- 0 scn 0x0000.00046906
Đây là phần khởi đầu của kết xuất khối dữ liệu. Dòng đầu tiên cho chúng ta biết rằng chúng ta đang kết xuất tệp số 3, bắt đầu từ khối # 10 (minblk) và kết thúc với khối # 10 (maxblk). Nếu chúng tôi kết xuất nhiều hơn một khối dữ liệu, các giá trị này sẽ đại diện cho một phạm vi. Địa chỉ khối dữ liệu tương đối (rdba) là 0x00c0000a. Để biết thêm thông tin về rdba, hãy tham khảo phần sau của bài báo này. Ở cuối dòng này, chúng ta có thể thấy trong ngoặc đơn rằng rdba tương ứng với tệp # 3, khối # 10 (3/10).
Dòng thứ ba mô tả SCN của khối dữ liệu. Trong trường hợp của chúng tôi, SCN là 0x0000.00046911. Phần đuôi của khối dữ liệu bao gồm hai byte cuối cùng của SCN (6911) được nối với kiểu (06) và chuỗi (02). Nếu sự phân rã của đuôi không khớp với ba giá trị này, thì hệ thống biết rằng khối đó không nhất quán và cần được khôi phục. Mặc dù giá trị đuôi này hiển thị ở đầu kết xuất khối, nhưng nó được lưu trữ vật lý ở cuối khối dữ liệu.
Loại khối hiển thị trên dòng thứ tư. Một số kiểu hợp lệ tương ứng với bảng sau:
Loại Ý nghĩa
0x02 khối hoàn tác
0x06 bảng hoặc khối dữ liệu chỉ mục
0x0e hoàn tác tiêu đề đoạn
0x10 khối tiêu đề đoạn dữ liệu
0x17 tiêu đề đoạn dữ liệu được ánh xạ bit
mã>
"Id đối tượng trên Block?" dòng cho chúng ta biết đối tượng này có nằm trong SYS.OBJ $ hay không. Kể từ Oracle 6, nó phải luôn là “Y”. Nếu bạn nhìn vào dòng tiếp theo, giá trị seg / obj cho chúng ta biết id đối tượng của phân đoạn (bằng hệ lục phân). Trong ví dụ của chúng tôi, đây là 0x6d9c. Hex ‘6D9C’ là ‘28060’ ở dạng thập phân. Chúng tôi có thể xác minh rằng đây là bảng của chúng tôi bằng truy vấn sau:
ORA9I SQL> chọn chủ sở hữu, object_name từ dba_objects
2 trong đó object_id =28060;
OWNER OBJECT_NAME
----------------------------------------------
PEASLAND EMP
Như chúng tôi đã hy vọng, đây là bàn của chúng tôi.
Giá trị csc là số Thay đổi Hệ thống Cleanout. Giá trị này cho chúng ta biết thời điểm thực hiện xóa khối trên khối này. Hy vọng rằng nó phù hợp với SCN của khối dữ liệu. Giá trị itc là Số lượng Danh sách Giao dịch Quan tâm. Trong trường hợp của chúng tôi, có hai giao dịch quan tâm đến khối này. Các giao dịch quan tâm đó xuất hiện ở cuối ví dụ của chúng tôi. Chúng ta có thể thấy id giao dịch (Xid) của hai giao dịch đó. Các id giao dịch đó tương ứng với các phân đoạn khôi phục được sử dụng để xử lý các giao dịch của chúng tôi.
Cờ (flg) là “-” hoặc “O”, được sử dụng để cho biết liệu khối này có thuộc về một người theo chủ nghĩa tự do hay không. Nếu khối thuộc về người theo chủ nghĩa tự do, cờ sẽ là “0”. Nếu nó không thuộc về người theo chủ nghĩa tự do, thì cờ sẽ là “-”. Khối của chúng tôi đang được đề cập là về người làm nghề tự do.
Chà, đó là khá nhiều thông tin và chúng tôi chưa thực sự xem xét quá nhiều về kết quả. Hãy xem phần tiếp theo của kết xuất khối dữ liệu.
data_block_dump
===============
tsiz:0x1fa0
hsiz:0x2e
pbl:0x024d015c
bdba:0x00c0000a
flag =-------------
ntab =1
nrow =14
frre =9
fsbo =0x2e
fseo =0x1b18
avsp =0x1d8a
tosp =0x1d8a
0xe:pti [0] nrow =14 off =0
0x12:pri [0] offs =0x1c30
0x14:pri [1] offs =0x1f4f
0x16:pri [2] offs =0x1f24
0x18:pri [3] offs =0x1efb
0x1a:pri [4] offs =0x1ece
0x1c:pri [5] offs =0x1ea5
0x1e:pri [6] offs =0x1e7c
0x20:pri [7] offs =0x1e54
0x22:pri [8] offs =0x1e2e
0x24:pri [9] sfll =13
0x26:pri [10] offs =0x1ca4
0x28:pri [11] offs =0x1cf1
0x2a:pri [12 ] off =0x1b18
0x2c:pri [13] sfll =-1
Giá trị tsiz cho chúng ta biết lượng chỗ trống trong khối cho dữ liệu. Ở đây, chúng tôi nhận được ‘1fa0’ có nghĩa là 8,096 byte phòng có thể sử dụng. Phần còn lại của khối 8,192 byte của chúng tôi được sử dụng cho chi phí như tiêu đề khối.
Giá trị ntab cho chúng ta biết có bao nhiêu bảng được lưu trữ trong khối này. Trừ khi khối này thuộc về một cụm, giá trị này sẽ là ‘1’. Giá trị nrow cho chúng ta biết có bao nhiêu hàng dữ liệu được lưu trữ trong khối này. Khối dữ liệu của chúng tôi có 14 hàng dữ liệu.
Bắt đầu từ địa chỉ ‘0xe’, chúng tôi nhận được một thư mục cho mỗi hàng. Chúng ta có thể thấy rằng hàng đầu tiên (mục nhập chỉ số không) bắt đầu tại địa chỉ bù đắp cho khối ‘0x1c30’. Mỗi hàng khối tiếp theo từ đây. Bằng cách này, một hàng có thể được tìm thấy thực sự nhanh chóng. Hãy nhớ rằng ROWID về cơ bản là một con trỏ đến một hàng duy nhất. Trong Oracle 8+, ROWID có dạng O.F.B.R (hoặc objectno, relativefno, blockno, rowno). Vì vậy, khi hệ thống nhanh chóng trỏ đến một khối cụ thể trong một tệp cụ thể, số hàng sẽ trỏ đến một vị trí trong thư mục này. Sau đó, thư mục trỏ đến một vị trí cụ thể trong khối. Đây là phần bắt đầu của hàng đó.
Bây giờ chúng ta đã có lộ trình cho khối dữ liệu của mình, hãy xem phần còn lại của tệp theo dõi để xem các hàng dữ liệu thực tế trong khối.
block_row_dump:
tab 0, row 0, @ 0x1c30
tl:39 fb:--H-FL-- lb:0x0 cc:8
col 0:[3] c2 4a 46
col 1:[5] 53 4d 49 54 48
col 2:[5] 43 4c 45 52 4b
col 3:[3] c2 50 03
col 4:[7] 77 b4 0c 11 01 01 01
col 5:[3] c2 09 19
col 6:* NULL *
col 7:[2] c1 15
>
Dữ liệu hàng thực tế bắt đầu bằng cụm từ “block_row_dump:”. Sau đó, một hàng dữ liệu được đưa ra. Tôi chỉ hiển thị một hàng dữ liệu ở đây, vì phần còn lại tương tự. Chúng ta có thể thấy rằng hàng này thuộc về bảng '0' (tab) trong cụm của chúng ta. Vì không có cụm trong ví dụ của chúng tôi, chúng tôi không có nhiều hơn một bảng nên giá trị này sẽ bằng không. Chúng ta cũng có thể thấy rằng đây là hàng ‘0’ và địa chỉ của hàng đó đã được cung cấp. Địa chỉ này phải tương ứng với lộ trình của chúng tôi đã nêu ở trên.
Giá trị ‘tl’ cung cấp cho chúng tôi tổng số byte cho hàng này, bao gồm mọi chi phí. Chúng ta có thể thấy rằng hàng này chiếm 39 byte. Giá trị ‘cc’ cho chúng ta số lượng cột. Chúng tôi có tám cột trong hàng này. Điều này có thể dễ dàng được xác minh bằng cách thực hiện MÔ TẢ trên bảng và đếm các cột hoặc bằng cách truy vấn USER_TAB_COLUMNS.
Giá trị ‘fb’ cung cấp cho chúng tôi các cờ về hàng. ‘H’ có nghĩa là chúng ta có người đứng đầu hàng. ‘F’ có nghĩa là chúng ta có mảnh đầu tiên của hàng. ‘L’ có nghĩa là chúng ta cũng có mảnh cuối cùng của hàng. Vì đây là mảnh đầu tiên và cuối cùng của hàng, nên hàng không được xâu chuỗi. Vì đây cũng là phần đầu của hàng, hàng chưa được di chuyển.
Phần còn lại của thông tin cho hàng là dữ liệu cho mỗi cột. Ví dụ, trong cột 1, chúng ta có các mã ký tự ASCII sau, “53 4d 49 54 48”. Nhìn nhanh vào biểu đồ chuyển đổi ASCII sẽ cho chúng ta biết rằng những ký tự này là “SMITH”. Nếu bạn đã quen thuộc với bảng EMP mẫu, bạn sẽ biết rằng SMITH là một trong những nhân viên của chúng tôi. Chú ý rằng cột 6 là NULL. Cột 4 là cột HIREDATE. Đây là kiểu dữ liệu DATE. Từ khối này, bạn có thể dễ dàng xác minh rằng kiểu dữ liệu DATE yêu cầu bảy byte bộ nhớ. Cột 0 chứa một số. Ba byte ở đây là đại diện của số đó.