我会尽量详细。
到目前为止,我只使用堆栈溢出和其他类似的网站,但从未张贴。我总能找到我问题的答案。但这次不行。

我有一个mu在线游戏服务器的设置和运行良好。这个服务器的一部分是一个叫做"joinserver"的程序。当我使用非md5版本时,这是可以的,但我想使用该文件的md5版本。

对于MD5版本,我有以下问题:
服务器启动,运行,一切正常,直到有人连接到游戏(这里正在创建查询,MSSQL开始加载)。在这一点上,apache的查询速度非常快,没有延迟,一切都运行得很好。但是当有人连接时(当joinserver开始运行时),锁就开始发生了。这只有在md5版本的joinserver中才是持久的。

我提到了md5,但没有给出细节,因为我想我应该说,是否有一点点的可能性md5涉及到整个情况。

游戏运行良好,但是当我通过apache调用超过5-6个查询时,apache进程将被锁定并具有状态 SUSPENDED 在MSSQL资源监视器内。

这里的问题是:如何防止apache暂停?
-是否可以在mssql服务器中对进程(apache)进行优先级排序?
-是否可以防止一个进程锁定另一个进程(防止joinserver锁定/挂起apache的进程)?
-有没有可能我的web查询写得不好,它们会产生太多的负载,而mssql会让它们挂起?从主观上讲,它们并不太多,也不会在SQL Server上产生很大的负载。当游戏服务器离线时,它们会在瞬间运行。
-无法更改游戏服务器(joinserver)查询,我无法访问其源代码

使用的软件
-Windows Server 2012 R2(在Windows 7 Pro上试用-相同)
-Microsoft SQL Server 2008(已试用2012-相同)
-通过xampp 7.3.10的php7.3
-ubuntu上的php 7.3和apache(相同)
-用于PHP7.3的PDO官方Microsoft驱动程序

以下是我如何建立数据库连接:

$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()));
}

(我正在使用两个数据库)。

以下是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][''];

编辑:我发现这个查询被锁定了,好像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将自行管理,并会很好。

我的努力:
-在Windows中禁用IPv6
-在SQL Server上禁用命名管道
-并行播放-没有运气
-在Windows7上试过了,其他的都一样-不走运
-尝试在ubuntu上运行apache而不是在windows上-运气不好
-尝试使用MSSQL 2012代替2008-相同

下面是一些我能找到锁的细节:
-任务状态: SUSPENDED
-命令: SELECT -应用程序: Apache HTTP Server
-等待时间(ms): 115163 (和增加)
-等待类型: LCK_M_S (我在谷歌上搜索了这个,没有帮助)
-等待资源: keylock hobtid=*** dbid=* id=** and so on
-被id:204锁定(这是joinserver的id)

还能怎么办?有什么建议吗?

最佳回复

尝试 prepare("SELECT count(memb___id) FROM MEMB_STAT with (nolock) WHERE ConnectStat='1'"); 但是在nolock上查找文档是有缺点的,但是我想这是可以接受的。 https://stackoverflow.com/questions/686724/what-is-with-nolock-in-sql-server