2012-10-22 13 views
6

Mam dość standardowego zapytania SQL w następujący sposób:Dlaczego Oracle traci dane podczas zatwierdzania?

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'; 

Jeżeli uruchomić kwerendy SQL Developer, to działa dobrze z 1.8million funkcji wstawionych (select count(*) from TABLE_NAME ciągu sesja to potwierdza).

Ale po uruchomieniu zatwierdzenia dane znikają! select count(*) from TABLE_NAME teraz zwraca 0 wyników.

Robiliśmy wiele rzeczy, aby spróbować i zobaczyć, co się dzieje:

  • Podczas Truncate, tabel uwalnia się, a podczas jej wstawić ponownie napełniony. Podczas zatwierdzania nie ma żadnych zmian. Oznacza to, że dane znajdują się w bazie danych.

  • Jeśli wykonam dokładnie to samo zapytanie, ale z and rownum < 100 dołączonym do końca, zatwierdzenie działa. To samo z 1000.

  • Znalazłem to pytanie: oracle commit kills i nasz DBA wypróbował "SQL Trace". W ten sposób powstał plik o rozmiarze> 4 GB, który po przetworzeniu na TKPROF wygenerował 120-stronicowy raport, ale nie wiemy, jak go odczytać i nie ma w nim oczywiście nic złego.

  • Nasze dzienniki błędów nie mają w nich nic. I oczywiście nie ma błędu podczas samego zatwierdzania.

  • Istnieje spust/sekwencja, która zwiększa się o 1,8 miliona w trakcie procesu.

Powtórzyłem to około 4 razy, ale wynik jest zawsze taki sam.

Moje pytanie jest proste - co dzieje się z danymi podczas zatwierdzania? Jak możemy się dowiedzieć? Dzięki.

Uwaga: W przeszłości działało dobrze, więc nie uważam, że jest coś złego w SQL-ie.


Edit: Problem rozwiązanypoprzez odtworzenie tabelę od podstaw. Teraz, kiedy wstawiam, zajmuje to tylko 500 sekund w porównaniu z poprzednim 2000. I zaangażowanie jest natychmiastowe; kiedy zostało złamane, zatwierdzenie zajęło 4000 sekund! Nadal nie mam pojęcia, dlaczego tak się stało.


Dla tych, pytając, Create Table składnia:

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

: Sprawdź scenariusza stole, może być jego globalnej tabeli tymczasowej, która truncate dane dotyczące zatwierdzenia. "http: // www.oracle-base.com/articles/8i/temporary-tables.php' –

+4

Czy masz ograniczenia na stole (w szczególności ograniczenia odroczone)? Czy zdefiniowano zdefiniowany zmaterializowany widok? Są to jedyne rzeczy, o których mogę pomyśleć, które mogą spowodować, że zatwierdzenie nie powiedzie się (chociaż w każdym przypadku powinieneś otrzymać komunikat o błędzie). –

+0

@GauravSoni - Dzięki za sugestię. Został stworzony jako zwykła tabela z normalnym "tworzeniem" w SQL Developer. Składnia: 'CREATE TABLE TABLE_NAME (... niektóre kolumny ...)' –

Odpowiedz

0

Czy nadal utracić dane, jeśli owinąć transakcję w anonimowym bloku?

Domyślam się, że otwierasz dwa okna SQL w programie SQL Developer, a to oznacza dwie osobne sesje. tj. uruchamianie kodu SQL w oknie 1 i wykonywanie commit; w oknie 2 nie zostaną zatwierdzone zmiany wprowadzone w oknie 1.

Skrócona tabela wykonuje niejawne zatwierdzenie. Zatem tabela będzie pusta, dopóki nie zakończy się wstawianie + zatwierdzanie.

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; 

Należy użyć obciąć ze schowkiem ponownego użycia, tak, że baza danych nie wykracza darmowa wszystkie bloki po prostu nabyć taką samą liczbę bloków we wkładce.

Jeśli chcesz/trzeba mieć dane dostępne na wszystkich razy lepsze (ale dłużej) metoda jest

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; 
Powiązane problemy