2012-10-22 21 views
6

Tôi có một truy vấn SQL khá chuẩn như sau:Tại sao Oracle mất dữ liệu trong quá trình cam kết?

TRUNCATE TABLE TABLE_NAME; 
INSERT INTO TABLE_NAME 
(
UPRN, 
SAO_START_NUMBER, 
SAO_START_SUFFIX, 
SAO_END_NUMBER, 
SAO_END_SUFFIX, 
SAO_TEXT, 
PAO_START_NUMBER, 
PAO_START_SUFFIX, 
PAO_END_NUMBER, 
PAO_END_SUFFIX, 
PAO_TEXT, 
STREET_DESCRIPTOR, 
TOWN_NAME, 
POSTCODE, 
XY_COORD, 
EASTING, 
NORTHING, 
ADDRESS 
) 
SELECT 
BASIC_LAND_AND_PROPERTY_UNIT.UPRN, 
LAND_AND_PROPERTY_IDENTIFIER.SAO_START_NUMBER AS SAO_START_NUMBER, 
LAND_AND_PROPERTY_IDENTIFIER.SAO_START_SUFFIX AS SAO_START_SUFFIX, 
LAND_AND_PROPERTY_IDENTIFIER.SAO_END_NUMBER AS SAO_END_NUMBER, 
LAND_AND_PROPERTY_IDENTIFIER.SAO_END_SUFFIX AS SAO_END_SUFFIX, 
LAND_AND_PROPERTY_IDENTIFIER.SAO_TEXT AS SAO_TEXT, 
LAND_AND_PROPERTY_IDENTIFIER.PAO_START_NUMBER AS PAO_START_NUMBER, 
LAND_AND_PROPERTY_IDENTIFIER.PAO_START_SUFFIX AS PAO_START_SUFFIX, 
LAND_AND_PROPERTY_IDENTIFIER.PAO_END_NUMBER AS PAO_END_NUMBER, 
LAND_AND_PROPERTY_IDENTIFIER.PAO_END_SUFFIX AS PAO_END_SUFFIX, 
LAND_AND_PROPERTY_IDENTIFIER.PAO_TEXT AS PAO_TEXT, 
STREET_DESCRIPTOR.STREET_DESCRIPTOR AS STREET_DESCRIPTOR, 
STREET_DESCRIPTOR.TOWN_NAME AS TOWN_NAME, 
LAND_AND_PROPERTY_IDENTIFIER.POSTCODE AS POSTCODE, 
BASIC_LAND_AND_PROPERTY_UNIT.GEOMETRY AS XY_COORD, 
BASIC_LAND_AND_PROPERTY_UNIT.X_COORDINATE AS EASTING, 
BASIC_LAND_AND_PROPERTY_UNIT.Y_COORDINATE AS NORTHING, 
decode(SAO_START_NUMBER,null,null,SAO_START_NUMBER||SAO_START_SUFFIX||' ') 
||decode(SAO_END_NUMBER,null,null,SAO_END_NUMBER||SAO_END_SUFFIX||' ') 
||decode(SAO_TEXT,null,null,SAO_TEXT||' ') 
||decode(PAO_START_NUMBER,null,null,PAO_START_NUMBER||PAO_START_SUFFIX||' ') 
||decode(PAO_END_NUMBER,null,null,PAO_END_NUMBER||PAO_END_SUFFIX||' ') 
||decode(PAO_TEXT,null,null,'STREET RECORD',null,PAO_TEXT||' ') 
||decode(STREET_DESCRIPTOR,null,null,STREET_DESCRIPTOR||' ') 
||decode(POST_TOWN,null,null,POST_TOWN||' ') 
||Decode(Postcode,Null,Null,Postcode) As Address 
From (Land_And_Property_Identifier 
     Inner Join Basic_Land_And_Property_Unit 
     On Land_And_Property_Identifier.Uprn = Basic_Land_And_Property_Unit.Uprn) 
Inner Join Street_Descriptor 
    On Land_And_Property_Identifier.Usrn = Street_Descriptor.Usrn 
Where Land_And_Property_Identifier.Postally_Addressable='Y'; 

Nếu tôi chạy truy vấn này trong SQL Developer, nó chạy tốt với 1.8million tính năng chèn (select count(*) from TABLE_NAME trong phiên xác nhận điều này).

Nhưng khi tôi chạy cam kết, dữ liệu sẽ biến mất! select count(*) from TABLE_NAME hiện trả về 0 kết quả.

Chúng tôi đã thực hiện một số điều để thử và xem những gì đang xảy ra:

  • Trong Truncate, tablespace được giải phóng, và trong suốt chèn điền của nó một lần nữa. Không có thay đổi trong thời gian cam kết. Điều này ngụ ý dữ liệu nằm trong cơ sở dữ liệu.

  • Nếu tôi thực hiện cùng một truy vấn chính xác nhưng với and rownum < 100 được nối vào cuối, cam kết hoạt động. Tương tự với 1000.

  • Tôi đã tìm thấy câu hỏi này: oracle commit kills và có DBA của chúng tôi thử "Dấu vết SQL". Điều này tạo ra một tập tin 4GB mà khi phân tích cú pháp với TKPROF sản xuất một báo cáo 120 trang nhưng chúng tôi không biết làm thế nào để đọc nó và không có gì rõ ràng là sai trong đó.

  • Nhật ký lỗi của chúng tôi không có gì trong đó. Và rõ ràng là không có lỗi trong quá trình cam kết.

  • Có trình kích hoạt/chuỗi làm tăng 1,8 triệu trong quá trình xử lý.

Tôi đã lặp lại điều này khoảng 4 lần, nhưng kết quả luôn như cũ.

Vì vậy, câu hỏi của tôi rất đơn giản - điều gì đang xảy ra với dữ liệu trong quá trình cam kết? Làm thế nào chúng ta có thể tìm ra? Cảm ơn.

Lưu ý: Điều này đã chạy tốt trong quá khứ vì vậy tôi không tin rằng có bất kỳ điều gì sai với SQL.


Edit: Vấn đề giải quyết bằng cách tái tạo bàn từ đầu. Bây giờ khi tôi chèn nó chỉ mất 500 giây so với năm 2000 trước đó. Và cam kết là tức thời; khi nó bị hỏng, cam kết mất 4000 giây! Tôi vẫn không biết tại sao nó lại xảy ra.


Đối với những câu hỏi, Create Table cú pháp:

CREATE TABLE TABLE_NAME 
(
ADDRESS           VARCHAR2(4000), 
UPRN            NUMBER(12), 
SAO_START_NUMBER         NUMBER(4), 
SAO_START_SUFFIX         VARCHAR2(1), 
SAO_END_NUMBER          NUMBER(4), 
SAO_END_SUFFIX          VARCHAR2(1), 
SAO_TEXT           VARCHAR2(90), 
PAO_START_NUMBER         NUMBER(4), 
PAO_START_SUFFIX         VARCHAR2(1), 
PAO_END_NUMBER          NUMBER(4), 
PAO_END_SUFFIX          VARCHAR2(1), 
PAO_TEXT           VARCHAR2(90), 
STREET_DESCRIPTOR         VARCHAR2(100), 
TOWN_NAME           VARCHAR2(30), 
POSTCODE           VARCHAR2(8), 
XY_COORD           MDSYS.SDO_GEOMETRY, 
EASTING           NUMBER(7), 
NORTHING           NUMBER(7) 
) 

CREATE INDEX TABLE_NAME_ADD_IDX ON TABLE_NAME (ADDRESS); 
+11

: Kiểm tra các kịch bản của bảng của bạn, có thể là một bảng tạm thời toàn cầu của nó, mà cắt ngắn dữ liệu trên cam kết .'http: // www.oracle-base.com/articles/8i/temporary-tables.php' –

+4

Bạn có những ràng buộc nào trên bảng (đặc biệt là các ràng buộc bị trì hoãn)? Bạn có xác định chế độ xem hiện thực hóa không? Đây là điều duy nhất tôi có thể nghĩ rằng có thể làm cho một cam kết thất bại (mặc dù trong mọi trường hợp bạn sẽ nhận được một thông báo lỗi). –

+0

@GauravSoni - Cảm ơn bạn đã đề xuất. Nó được tạo ra như một bảng thông thường với một "tạo" bình thường trong SQL Developer. Cú pháp: 'CREATE TABLE TABLE_NAME (... một số cột ...)' –

Trả lời

-1

Có lẽ bạn có một nguyên nhân mà bạn không để ý. Bạn có thể kiểm tra bảng recyclebin của oracle mà có thể lưu trữ lịch sử của bảng và trình kích hoạt đã bị hủy của bạn không?

Select * from recyclebin; 

Tài liệu tham khảo: http://www.oraclebin.com/2012/12/recyclebinflashback.html

0

Bạn vẫn mất dữ liệu nếu bạn quấn giao dịch trong một khối vô danh?

Tôi đoán là bạn đang mở hai cửa sổ SQL trong SQL Developer và điều đó có nghĩa là hai phiên riêng biệt. tức là Chạy mã SQL trong cửa sổ 1 và thực hiện cam kết; trong cửa sổ 2 sẽ không thực hiện các thay đổi trong cửa sổ 1.

Bàn cắt ngắn thực hiện một cam kết ngầm định. Vì vậy, bảng sẽ được để trống cho đến khi chèn + cam kết kết thúc.

begin 
    execute immediate 'truncate table table_name reuse storage'; --use "reuse" if you know the data will be of similar size 
    -- implicit commit has occured and the table is empty for all sessions 
    insert into table_name (lots) 
    select lots from table2; 
    commit; 
end; 

Bạn nên sử dụng cắt ngắn với bộ nhớ sử dụng lại, để cơ sở dữ liệu không đi miễn phí tất cả các khối chỉ để có cùng số khối trong chèn.

Nếu bạn muốn/cần phải có các dữ liệu có sẵn tại mọi thời điểm một phương pháp tốt hơn (nhưng dài hơn) là

begin 
    savepoint letsgo; 
    delete from table_name; 
    insert into table_name (lots) 
    select lots from table2; 
    commit; 
exception 
    when others then 
     rollback to letsgo; 
end; 
Các vấn đề liên quan