MV i rozproszone transakcje

0

Hej,

Mam następujący problem -

Istnieje sobie na bazie widok materialized view fast on commit, coś w stylu

create or replace materialized view mv_test
refresh fast on commit
as
select ..
union all
select
union all
etc..

Problem: baza musi obsługiwać distributed transactions, a więc nie możemy posiadać widoku 'refresh on commit'. Kod korzystający z widoku jest dość zawiły i generalnie moja idea jest taka, że chciałbym jakoś wymusić jego odświeżanie ręcznie przy każdym zapytaniu (zrobić ON DEMAND).

Jak do tej pory miałem pomysły opakowania odwołań do widoku w funkcję i wywoływania DBMS_MVIEW.refresh(), po czym zwracania wyników ale wydajność tego raczej bym powiedział że średnia już przez samo przetwarzanie zapytania i tworzenia zwracanego zestawu wierszy. Drugim pomysłem było stworzenie funkcji z samym odświeżeniem widoku np. funkcja_odswiez i zrobienie zapytania w stylu:

select funkcja_odswiez(), null, null, null ... from dual
union
select * from mv_widok

Niestety, kiedy próbuje stworzyć funkcję:

create or replace function refresh_fn 
return number 
as
v_ret number;
begin

DBMS_MVIEW.refresh('mv_test');
select 1 into v_ret from dual;

end refresh_fn;

I ją wywołać:

select refresh_fn(), null, null, null, null, null, null from dual;

Otrzymuję błąd
ORA-14552: cannot perform a DDL, commit or rollback inside a query or DML
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 3014
ORA-06512: at "SYS.DBMS_SNAPSHOT", line 2994
ORA-06512: at "DEVCA.REFRESH_FN", line 7
14552. 00000 - "cannot perform a DDL, commit or rollback inside a query or DML "
*Cause: DDL operations like creation tables, views etc. and transaction
control statements such as commit/rollback cannot be performed
inside a query or a DML statement.
*Action: Ensure that the offending operation is not performed or
use autonomous transactions to perform the operation within
the query/DML operation.

Ostatecznością będzie wywołanie procedury DBMS_MVIEW.refresh('DKWTEST_MV'); przed każdym użyciem widoku ale wolałbym to jakoś ładnie zrobić w procedurze i np. dodać sprawdzanie czy w ogóle widok jest oznaczony jako STALE.

2

"chciałbym jakoś wymusić jego odświeżanie ręcznie przy każdym zapytaniu"

skoro przy każdym zapytaniu chcesz mieć świeże dane to zrób zwykły widok a nie zmaterializowany

0

Tak też chyba zrobię... Mogę zaindeksować parę kolumn i nie powinno być spadku wydajnościowo.

0

na moje oko pozostaje Ci opcja 3 - najpierw zawołać refresh_fn a potem zrobić select

1 użytkowników online, w tym zalogowanych: 0, gości: 1