2016-03-31 66 views
0

我似乎在處理運行多個數據庫調用時遇到了一些困難,特別是在返回大數據集時。 似乎PHP只允許您在每個會話中一次運行一個數據庫調用。這通常不是問題,因爲數據庫調用通常非常小,不會鎖定任何東西,但大數據庫會導致此等待問題。每個會話在PHP中運行併發數據庫查詢?

我在修復一個不相關的問題時發現了這個問題,並發現如果你點擊一個按鈕來通過AJAX調用來查詢數據庫,然後嘗試刷新網站,直到該數據庫纔會開始加載網站調用完成,因爲該頁面具有內部函數來進行數據庫調用。相反,如果我要開始數據庫查詢,然後加載一個純html網頁,指出「Hello World」,它會立即加載。 基於此,Apache不存在服務問題,這與數據庫連接有關。

要指出,我已經隔離可能相關的代碼,因爲我無法弄清楚爲什麼我一次只能有一個活動呼叫。 總之,有沒有辦法讓每個用戶一次運​​行多個數據庫調用,或者用戶不得不等待?

db_connect.php:

<?php 
    $user = 'TEST'; 
    include_once 'config.php'; //Intialize constants for the connection 
    $conn = oci_connect(USER, PASSWORD, '//'.HOST.':1630/'.DATABASE); 
    oci_set_client_identifier($conn, $user); //Identify who's making these calls. 
?> 

events.php。(如果我刷新此點擊阿賈克斯按鈕做同樣取後,也不會直到AJAX調用完成加載隱而不宣」牛逼的問題,如果我有代碼中止調用,數據庫仍然運行數據庫查詢)

<?php 
    session_start(); 
    include 'db_connect.php'; 
    include 'database/event_defs.php'; 
?> 
<html> 
    <!-- boilerplate nonsense --> 
    <body> 
    <table> 
    <?php 
    $dataset = get_event_list($conn, $_SESSION['username']); //Returns 1000 records, could take a while to fully retrieve it. 
    foreach($dataset as $key => $val) { 
     //Make multiple rows happen here. 
    } 
    ?> 
    </table> 
    <button onclick="do_ajax_call('get_event_list');">Make DB Call</button> 
    </body> 
</html> 

數據庫/ event_defs.php:(可能是最有用的部分)。

<?php 
    function get_event_list($conn, $user) { 
    $l_result = array(); 
    $sql = 'BEGIN ...(:c_usr, :c_rslt); END'; //name is irrelevant. 
    if($stmt = oci_parse($conn, $sql)) { 
     $l_results = oci_new_cursor($conn); 
     oci_bind_by_name($stmt,':c_usr',$user); 
     oci_bind_by_name($stmt,':c_rslt',$lresults,-1,OCI_B_CURSOR); 
     if(oci_execute($conn)) { 
     oci_execute($l_results); //Problem line, seems to stall out here for a while and won't let the user query again until this call finishes. 
     while($r = oci_fetch_array($l_results, OCI_ASSOC) { 
      $l_result[] = $r; 
     } 
     } else { 
     return 'bad statement'; 
     } 
    } else { 
     return 'unable to connect'; 
    } 

    return $l_result; 
    } 
?> 

版本信息:

PHP 5.4.45
的Oracle 11g
的Apache 2.2.15

+3

併發的AJAX請求問題不是由數據庫引起的。您遇到會話鎖定。 – MonkeyZeus

+1

嘗試'session_write_close(); get_event_list($ myConn,'Orpheus');'。這隻有在調用'get_event_list($ myConn,'Orpheus')後不需要修改會話時纔有效;' – MonkeyZeus

回答

1

正如在評論你的問題MonkeyZeus猴子已經指出的那樣,第二個請求是很可能只會被會話機制阻止。
因爲它看起來像你不需要任何東西,但會話的用戶名,只需抓住該值並完成會話機制。

<?php 
session_start(); 
// check $_SESSION['username'] here if necessary 
$username = $_SESSION['username']; 
// no need to keep the session mecahnism "alive" 
session_abort(); // and since nothing has been written to _SESSION, abort() should do. 

require 'db_connect.php'; 
require 'database/event_defs.php'; 
?> 
<html> 
    <!-- boilerplate nonsense --> 
    <body> 
    <table> 
    <?php 
    $dataset = get_event_list($conn, $username); //Returns 1000 records, could take a while to fully retrieve it. 
    foreach($dataset as $key => $val) { 
     //Make multiple rows happen here. 
    } 
    ?> 
+0

'session_abort()'僅在PHP 5.6或更高版本中使用。不幸的是,讓基礎設施更新它是一件令人頭疼的事 否則,這在某些情況下確實有效。我真的需要將他們直接更新... – Orpheus

+1

直到那時你被'session_write_close()'卡住了;同樣的效果。 – VolkerK

1

這是PHP會話阻止機制。

當您不再需要會話時,您需要調用session_write_close()。 可能是這串後:

$dataset = get_event_list($conn, $_SESSION['username']); 

調用session_write_close()後,您不能使用$ _SESSION。

+0

「可能在這個字符串之後:」 - 這太晚了;-) – VolkerK

相關問題