从PHP运行长Oracle存储过程

时间:2017-11-10 13:29:24

标签: php oracle stored-procedures

我有一个存储过程,我使用以下命令从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}
}

问题是我在存储过程中有数百万行和复杂的逻辑。当我通过SQL开发人员执行SP_GET_MY_DATA时,完成它需要大约2个小时。

当我这样做时,PHP会超时。我也不能在PHP中增加max_execution_time。

如何在Oracle上运行此程序或在没有超时的情况下使用PHP?请帮忙。

2 个答案:

答案 0 :(得分:3)

我回答了如何使用Oracle Scheduler在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

答案 1 :(得分:-2)

不要增加max_execution_time,将其设置为0,允许它无限期运行。如果要返回大量行,请确保增加内存(ini_set)或允许立即缓冲区刷新,以便它可以直接输出到客户端。

后者还会阻止客户过早断开连接,因为他们没有获得任何数据。 (ob_implicit_flush(true);