2016-03-31 3 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

Смежные вопросы