php线程出现oracle错误:两个任务存储区溢出


php threads with oracle error: two-task save area overflow

我在php中启用了Threads,这样我就可以同时执行多个任务,目标是将数据从Oracle服务器(12C)提取到本地。

为什么在线程上??因为在某个时候,我们希望在几个表之间处理大约5亿条记录,所以我想同时提取数据,以尽量减少处理时间。

这是我的php代码:

<?php
//*************Thread 1
class table1Class extends Thread{
  public $bdconn;
  public function __construct($bdconn) {
    $this->bdconn = $bdconn;
  }
  public function run(){
    $stTable1 = oci_parse($this->bdconn, 'INSERT INTO TABLE_1 
      SELECT * FROM TABLE_1@DBLINK');
    oci_execute($stTable1); //******* LINE 13
  }
}
//***********Thread 2
class table2Class extends Thread{
  public $bdconn;
  public function __construct($bdconn) {
    $this->bdconn = $bdconn;
  }
  public function run(){
    $stTable2 = oci_parse($this->bdconn, 'INSERT INTO TABLE_2
      SELECT * FROM TABLE_2@DBLINK');
    oci_execute($stTable2); //****** LINE 27
  }
}

function pad($val) {
  return ($val > 9) ? $val : "0".$val;
}

$start= microtime(true); //time
require_once '../../lib/bd_con.php';
$bdconn=  conBd(); //open connection
/**********TRUNCATE LOCAL TABLES*/
$trunPref=  oci_parse($bdconn, 'TRUNCATE TABLE TABLE_1');
oci_execute($trunPref);
$trunCruz=  oci_parse($bdconn, 'TRUNCATE TABLE TABLE_2');
oci_execute($trunCruz);
/************END*/

//***********BEGIN THREADS
$table1 = new table1Class($bdconn);
$table1->start();
$table2 = new table2Class($bdconn);
$table2->start();

//*********WAINT FOR THREADS TO END
$table1->join();
$table2->join();

oci_close($bdconn); //close connection
//PRINT TIME INFORMATION
$end= microtime(true); //al final del archivo
$tiempo_segundos = number_format($end-$start,4);
echo pad(((Int)($tiempo_segundos/60))).":".pad(((Int)($tiempo_segundos%60)))." minutes";

这就是我在执行时遇到的错误:

警告:oci_execute():ORA-01013:用户请求取消当前C:''examplep''htdocs中的操作。。。''第13行的file.php

警告:oci_execute():ORA-03117:中的两个任务存储区溢出C: ''axamp''htdocs。。。''第27行的file.php

关于代码的用途,一个小的解释是:截断我的本地表,并执行两个线程,使用dblink再次从oracle服务器插入数据。

如果有人能告诉我如何解决这个问题,我将不胜感激。

我在python中也遇到了同样的错误。显然,它是在两个不同的线程共享同一个oracle连接时产生的。

我所说的"相同"指的是完全相同的连接对象:如果你打开两个不同的连接(尽管它们有相同的用户和密码),就不会有任何问题。

为了避免这个问题每个线程只使用一个连接对象:您也可以使用连接池来实现这一点。