Oracle (11.2.0.1): Как определить строку, которая в данный момент обновляется оператором UPDATE

not необходимо поместить реализацию в файл заголовка, см. альтернативное решение в конце этого ответа.

В любом случае причина, по которой ваш код не работает, что при создании экземпляра шаблона компилятор создает новый класс с заданным аргументом шаблона. Например:

template
struct Foo
{
    T bar;
    void doSomething(T param) {/* do stuff using T */}
};

// somewhere in a .cpp
Foo f; 

При чтении этой строки компилятор создаст новый класс (назовем его FooInt), что эквивалентно следующему:

struct FooInt
{
    int bar;
    void doSomething(int param) {/* do stuff using int */}
}

Следовательно, компилятор должен иметь доступ к реализации методов, чтобы создать экземпляр с аргументом шаблона (в данном случае int). Если эти реализации не были в заголовке, они не были бы доступны, поэтому компилятор не смог бы создать экземпляр шаблона.

Общим решением для этого является запись объявления шаблона в заголовок файла, затем реализовать класс в файле реализации (например, .tpp) и включить этот файл реализации в конец заголовка.

// Foo.h
template 
struct Foo
{
    void doSomething(T param);
};

#include "Foo.tpp"

// Foo.tpp
template 
void Foo::doSomething(T param)
{
    //implementation
}

Таким образом, реализация по-прежнему отделена от объявления, но доступен компилятору.

Другое решение состоит в том, чтобы сохранить реализацию отдельно и явно создать все экземпляры шаблона, которые вам понадобятся:

// Foo.h

// no implementation
template  struct Foo { ... };

//----------------------------------------    
// Foo.cpp

// implementation of Foo's methods

// explicit instantiations
template class Foo;
template class Foo;
// You will only be able to use Foo with int or float

Если мое объяснение isn ' t достаточно ясно, вы можете взглянуть на C ++ Super-FAQ по этому вопросу .

2
задан Roman Pokrovskij 17 January 2019 в 00:55
поделиться

2 ответа

Вы можете использовать запрос для мониторинга длительных операций DML и отката. Если поле обновления не включено в индекс, то значение поля used_urec из представления v$transaction будет очень близко к числу строк. Когда выполняется операция обновления, эти значения увеличиваются, если выполняется откат, значения уменьшаются до нуля.

V$TRANSACTION lists the active transactions in the system.
    USED_UREC Number of undo records used
    USED_UBLK Number of undo blocks used
select
   substr(s.username,1,28) username,
   substr(s.program,1,25) program,
   s.command,
   t.used_urec,
   t.used_ublk,
   decode(s.command,
     0,'No Command',
     1,'Create Table',
     2,'Insert',
     3,'Select',
     6,'Update',
     7,'Delete',
     9,'Create Index',
     15,'Alter Table',
     21,'Create View',
     23,'Validate Index',
     35,'Alter Database',
     39,'Create Tablespace',
     41,'Drop Tablespace',
     40,'Alter Tablespace',
     53,'Drop User',
     62,'Analyze Table',
     63,'Analyze Index',
     s.command||': Other') command
from 
   v$session     s,
   v$process     p,
   v$transaction t
where s.paddr = p.addr
and s.taddr = t.addr 
order by 1

Например, 1. Если вы обновляете столбец, который не проиндексирован, то количество строк 39915830 и USED_UREC 40000562 примерно совпадают.

create table test_update(p1,p2,p3,p4 )
  PCTFREE     1
  INITRANS    1
  MAXTRANS    255
  TABLESPACE  arhiv_data
as 
SELECT a.n_p_u, a.id_reg, a.id_vag, a.vrsvop
  FROM a_vag_atr a;

SELECT count(*)
          FROM test_update a
==>
COUNT(*)                                     
-------------------------------------------- 
                                    39915830 

Сессия 1

update test_update 
set p2=1234567890
==>
39915830 row(s) updated
[ 1119] Сеанс 2 запускает обновление

USERNAME       PROGRAM         COMMAND  USED_UREC   USED_UBLK   COMMAND_1                                             
---------------- ---------------------- ------------------- --------------------
ASUDS          sqlnavigator.exe      6  4181959    62690           Update       

прекращает обновление

USERNAME       PROGRAM         COMMAND  USED_UREC   USED_UBLK   COMMAND_1                                             
---------------- ---------------------- ------------------- --------------------
ASUDS          sqlnavigator.exe      6   40000562   601871       Update       

Например, 2. если вы обновляете индексированное поле, то число строк * 3 приблизительно равно USED_UREC. 39915830 * 3 = ~ 116705429

create table test_update(p1,p2,p3,p4 )
  PCTFREE     1
  INITRANS    1
  MAXTRANS    255
  TABLESPACE  arhiv_data
as 
SELECT a.n_p_u, a.id_reg, a.id_vag, a.vrsvop
  FROM a_vag_atr a;

SELECT count(*) FROM test_update a
==>
COUNT(*)                                     
-------------------------------------------- 
                                    39915830 

CREATE INDEX test_ind ON test_update
  (
    p1                              ASC
  )

Сессия 1

update test_update 
set p1=12
==>
39915830 row(s) updated

Сессия 2 прекратит обновление

USERNAME       PROGRAM         COMMAND  USED_UREC   USED_UBLK   COMMAND_1                                             
---------------- ---------------------- ------------------- --------------------
ASUDS          sqlnavigator.exe      6  116705429   1392538        Update       

Например 3. если вы вставите в таблицу не проиндексирован тогда количество строк точно соответствует USED_UREC.

create table test_update(p1,p2,p3,p4 )
      PCTFREE     1
      INITRANS    1
      MAXTRANS    255
      TABLESPACE  arhiv_data

 SELECT count(*)
              FROM test_update a
==>
    COUNT(*)                                     
    -------- 
          0

Сессия 1

declare
 i pls_integer:=1;
begin
for i in 1..500000 loop
insert into test_update(p1,p2,p3,p4)
values(1,2,3,sysdate); 
end loop;
end;

select count(*) from  test_update
==>
COUNT(*)                                     
----------- 
     500000

Сессия 2

USERNAME       PROGRAM         COMMAND  USED_UREC   USED_UBLK   COMMAND_1                                             

    ASUDS          sqlnavigator.exe      2     500000    5815    Insert

Например 4. Если вы удалите из таблицы не проиндексированы, то количество строк это точно USED_UREC.

Сессия 1

 SELECT count(*) FROM test_update a
    ==>
        COUNT(*)                                     
        -------- 
         500000
delete from  test_update
==>
500000 row(s) deleted

Сессия 2

    USERNAME       PROGRAM         COMMAND  USED_UREC   USED_UBLK   COMMAND_1                                             
---------------- ---------------------- ------------------- --------------------
        ASUDS      sqlnavigator.exe   7      500000      9616         Delete  
0
ответ дан Dmitry Demin 17 January 2019 в 00:55
поделиться

Вы хотите сказать, что хотите отслеживать ход выполнения долгосрочного заявления UPDATE? Нет, я не знаю простого способа сделать это. Ни один сеанс за пределами сеанса, в котором выполняется оператор обновления, не сможет увидеть изменения в таблице, пока вы не подтвердите их.

То, что вы могли бы сделать, - это написать программу на PL / SQL, которая делает это порционно и между ними выдает оператор COMMIT. Таким образом, другой сеанс может наблюдать за таблицей и видеть ее как обновленную часть.

0
ответ дан eaolson 17 January 2019 в 00:55
поделиться
Другие вопросы по тегам:

Похожие вопросы: