Apache ПРИОСТАНОВЛЯЕТСЯ в MSSQL другим процессом при выполнении более 5-6 запросов через PHP PDO, что приводит к тайм-ауту

Я постараюсь быть максимально подробным.
До сих пор я использовал только Stack Overflow и другие подобные сайты, но никогда не публиковал сообщения. Я всегда находил ответ на свой вопрос. Но не в этот раз.

У меня есть игровой сервер Mu Online, настроенный и работающий нормально. Частью этого сервера является программа под названием «JoinServer». Когда я использую версию, отличную от md5, это нормально, но я хочу использовать версию файла md5.

С версией md5 у меня возникла следующая проблема:
Сервер запускается, работает и все в порядке, пока кто-то не подключится к игре (здесь создаются запросы и начинает загружаться MSSQL). До этого момента Apache выполнял запросы очень быстро, без задержек и все работало идеально. Но когда кто-то подключается (когда JoinServer начинает работу), блокировки начинают происходить. Это постоянно только с md5-версией JoinServer.

Я упоминаю md5, но не сообщаю подробностей, потому что думаю, что должен сказать, есть ли хотя бы небольшой шанс, что md5 участвует во всей ситуации.

Игра работает нормально, но когда я вызываю более 5-6 запросов от Apache , Процесс Apache блокируется и имеет статус SUSPENDED внутри монитора ресурсов MSSQL.

Здесь возникает вопрос: как предотвратить приостановку работы Apache?
- можно ли установить приоритет процесса (Apache) на сервере MSSQL?
- можно ли предотвратить блокировку одним процессом других процессов (запретить JoinServer блокировать / приостанавливать процесс Apache)?
- возможно ли, что мои веб-запросы написаны не очень хорошо, создают слишком большую нагрузку, а MSSQL приостанавливает их выполнение? Субъективно их не слишком много и они не создают большой нагрузки на SQL-сервер. Когда игровой сервер отключен, они запускаются мгновенно.
- НЕЛЬЗЯ изменять запросы игрового сервера (JoinServer), у меня нет доступа к его исходному коду

Используемое программное обеспечение
- Windows Server 2012 R2 (пробовал на Windows 7 Pro - то же самое)
- Microsoft SQL Server 2008 (пробовал с 2012 - то же)
- PHP 7.3 через xampp 7.3.10
- PHP 7.3 и Apache в Ubuntu (то же самое)
- Официальный драйвер Microsoft PDO для PHP 7.3

Вот как я подключаюсь к базе данных:

$dsn = 'sqlsrv:server='.Config::DB_SERVER.';Database='.Config::DB_NAME;
$dsn_web = 'sqlsrv:server='.Config::DB_SERVER.';Database=ANHIWEB';
$options = [
                PDO::ATTR_EMULATE_PREPARES   => false,
                PDO::ATTR_ERRMODE            => PDO::ERRMODE_WARNING,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'
                ];

try {

    $db = new PDO($dsn, Config::DB_USER, Config::DB_PASS, $options);
    $webdb = new PDO($dsn_web, Config::DB_USER, Config::DB_PASS, $options);

}

catch (PDOException $e) {
    die(print_r($e->getMessage()));
}

(я использую 2 базы данных).

Вот пример запросов, выполняемых PHP через PDO:

//Get online players count
$exec = $db->prepare("SELECT count(memb___id) FROM MEMB_STAT WHERE ConnectStat='1'");
    $exec->execute();
    $result = $exec->fetchAll();
    return @$result[0][''];
//Some rankings
    $exec = $db->prepare("SELECT
    RowNum
      ,C.[AccountID]
      ,[CharacterName]
      ,C.[Class]
      ,C.[cLevel]
      ,C.[Resets]
      ,[Point]
FROM    ( SELECT    ROW_NUMBER() OVER ( ORDER BY C.Class DESC ) AS RowNum, *
          FROM      [EVENT_INFO] as E
          WHERE C.ctlCode=0
        ) AS RowConstrainedResult
         left join Character as C ON CharacterName = Name

WHERE   RowNum >= $start
    AND RowNum < $limit
ORDER BY RowNum");

    $exec->execute();
    $result = $exec->fetchAll();
//Get total accounts
    $exec = $db->prepare("SELECT count(memb_guid) FROM MEMB_INFO");
    $exec->execute();
    $result = $exec->fetchAll();
    return @$result[0][''];

EDIT: я обнаружил, что этот запрос блокируется, похоже, что JoinServer использует таблицу MEMB_STAT.
Возможно, это единственный запрос, который блокирует.

//Get online players
global $db;
    $exec = $db->prepare("SELECT count(memb___id) FROM MEMB_STAT WHERE ConnectStat='1'");
    $exec->execute();
    $result = $exec->fetchAll();
    return @$result[0][''];

Теперь вопрос: как выбрать этот счетчик, не вызывая блокировку?

Я ничего не делаю, чтобы закрыть / очистить соединение, поскольку я прочитал в Интернете, что в этом нет необходимости, и PHP / PDO будет управлять самим собой и будет хорошо.

Мои усилия:
- Отключен IPv6 в Windows
- Отключены именованные каналы на сервере SQL
. - Играли с параллелизмом - не повезло
- Пробовал с Windows 7, все остальное тоже - не повезло
- Пытался запустить Apache на Ubuntu вместо Windows - не повезло
- Пробовал MSSQL 2012 вместо 2008 - тот же

Вот некоторые подробности, которые я могу получить при блокировке:
- Состояние задачи: ПРИОСТАНОВЛЕНА
- Команда: SELECT - Приложение: HTTP-сервер Apache
- Время ожидания (мс): 115163 (и увеличивается)
- Тип ожидания: LCK_M_S (я погуглил, не помогло)
- Ожидание ресурса: keylock hobtid = *** dbid = * id = ** и так далее
- Заблокировано идентификатором: 204 (это идентификатор JoinServer)

Что еще делать? Есть предложения?

0
задан 12 October 2019 в 15:16
1 ответ

Попробуйте приготовить ("ВЫБРАТЬ Счетчик (член ___ id) ИЗ MEMB_STAT с (nolock) WHERE ConnectStat = '1'"); Но посмотрите документы на nolock, он недостатки, но, думаю, для этой цели они приемлемы. https://stackoverflow.com/questions/686724/what-is-with-nolock-in-sql-server

0
ответ дан 5 December 2019 в 00:27

Теги

Похожие вопросы