Запустите длительную хранимую процедуру Oracle из PHP


У меня есть хранимая процедура, которую я запускаю с PHP, используя:

//Request does not change
$sql = 'BEGIN SP_GET_MY_DATA(:POP, :SEG, :DUR, :VIEW, :PAGE, :OUTPUT_CUR); END;';            

//Statement does not change
$stmt = oci_parse($conn,$sql);                     
oci_bind_by_name($stmt,':POP',$pop);           
oci_bind_by_name($stmt,':SEG',$seg);           
oci_bind_by_name($stmt,':DUR',$dur);           
oci_bind_by_name($stmt,':VIEW',$view);           
oci_bind_by_name($stmt,':PAGE',$page);    

//But BEFORE statement, Create your cursor
$cursor = oci_new_cursor($conn)

// On your code add the latest parameter to bind the cursor resource to the Oracle argument
oci_bind_by_name($stmt,":OUTPUT_CUR", $cursor,-1,OCI_B_CURSOR);

// Execute the statement as in your first try
oci_execute($stmt);

// and now, execute the cursor
oci_execute($cursor);

// Use OCIFetchinto in the same way as you would with SELECT
while ($data = oci_fetch_assoc($cursor, OCI_RETURN_LOBS )) {
    print_r($data}
}

Проблема в том, что у меня миллионы строк и сложная логика в хранимой процедуре. Когда я выполняю SP_GET_MY_DATA через разработчика SQL, для его завершения требуется около 2 часов.

PHP отключается, когда я это делаю. Я также не могу увеличить max_execution_time в PHP.

Как я могу запустить это на Oracle или с помощью PHP без тайм-аута? Пожалуйста, помогите.

Author: dang, 2017-11-10

2 answers

Я довольно подробно ответил, как использовать планировщик Oracle для асинхронного выполнения длительной процедуры, в этом ответе на обмен стеками DBA. См. https://dba.stackexchange.com/a/67913/38772

TL;DR - это

-- submit this as a background job
BEGIN
  dbms_scheduler.create_job ( 
      job_name => 'MY_BACKGROUND_JOB'
    , job_type => 'STORED_PROCEDURE'    
    , job_action => 'SP_GET_MY_DATA'
    , enabled => TRUE
    , auto_drop => TRUE
  );
END;

Вам придется проделать немного больше работы, если вы хотите передать параметры процедуре. Вы можете найти этот ответ полезным https://dba.stackexchange.com/q/42119/38772/

Для дополнительной справки со всеми кровавыми подробности, соответствующая глава из документации Oracle находится по адресу https://docs.oracle.com/database/121/ADMIN/scheduse.htm

 3
Author: Joshua Huber, 2017-11-13 15:53:45

Не увеличивайте max_execution_time, установите его равным 0, позвольте ему работать бесконечно. Если вы собираетесь возвращать множество строк, убедитесь, что либо увеличили объем памяти (ini_set), либо разрешили немедленную очистку буфера, чтобы он мог выводиться непосредственно клиенту.

Последнее также предотвратит преждевременное отключение клиентов из-за того, что они не получили никаких данных. (ob_implicit_flush(true);)

 -2
Author: DevionNL, 2017-11-13 15:05:44