PHP 10000 个并发调用和 MYSQL 查询等待时间和缓慢

PHP 10000 concurrent calls and MYSQL query wait time and slow

我有一个非常简单的查询,它插入对 messageRequest table 的每个 api 调用。它每秒最多可以处理 1000 个请求或更多。

例如,http://myapplication.com/sendMessage.php?phone=123&gsm=mobitel&message=helloworld

假设,在移动设备上使用我们应用程序的任何人都会调用此 URL。当我通过

拨打 1000 次电话时

ab -n 1000 -c 10 "http://myapplication.com/sendMessage.php?phone=123&gsm=mobitel&message=helloworld"

查询是insert into messageRequest values(null, phone, gsm, message);

它工作正常,但问题是当我尝试在这个 URL http://myapplication.com/apiLogs.php 中使用我的 activity 日志页面来查看有多少并发调用时过去 30 分钟收到 SMS api 来电。

它只是查询 SELECT count(*) from messageRequest where created_at > '2016-10-01 12:01:00'

return 结果大约需要 100 秒。当我停止通过 ab -n command 进行并发调用时,它工作正常。所以我假设当发生 1000 个并发调用并且为每个调用插入一条记录时,MYSQL table messageRequest 被锁定。

为了避免这个问题,

我将其更改为多个会话,例如 sendMessage.php 我用 user1 做到了 运行,而 apiLogs.php 我用 user2 做到了。所以 2 个差异会话可以访问相同的 table 以同时读取和写入,但这也没有帮助。

sendMessage.php

define('DB_HOST', 'localhost');
define('DB_USER', 'user1');
define('DB_PASS', ''); 

apiLogs.php

define('DB_HOST', 'localhost');
define('DB_USER', 'user2');
define('DB_PASS', '');

我很困惑如何在这么多并发调用的情况下让它在没有任何等待时间的情况下工作?

更新

sendMessage.php代码

define('DB_HOST', 'localhost');
define('DB_USER', 'user1');
define('DB_PASS', 'user1');

 mysql_connect(DB_HOST, DB_USER, DB_PASS);
 mysql_select_db('smsApp');


     mysql_query(
        "insert into messageRequest values (
            NULL,
            '{$_REQUEST['phone']}',
            '{$_REQUEST['gsm']}',
            '{$_REQUEST['message']}',
            '{$_REQUEST['text']}',
            now()
            );
        "
    );

我正在用这个命令发出并发请求

ab -n 1000 -c 10 "http://myapplication.com/sendMessage.php?phone=123&gsm=mobitel&message=helloworld&text=123"

在 运行ning 期间,我正在尝试查看此页面 apiLogs.php(源代码在下方)

  define('DB_HOST', 'localhost');
    define('DB_USER', 'user2');
    define('DB_PASS', 'user2');

     mysql_connect(DB_HOST, DB_USER, DB_PASS);
     mysql_select_db('smsApp');

m_ago = new DateTime("30 minutes ago");
$s = m_ago->format("Y-m-d H:i:s");
$result = mysql_query("SELECT count(*) from messageRequest where created_at > '$s'");

$response['last_30_min_sms_count'] = current(mysql_fetch_row($result));

echo json_encode($response)."\n";

使用 InnoDB,而不是 MyISAM。这样,table 就不会被锁定。

不要使用已弃用的 mysql_* API,请使用 mysqli_*PDO

"Don't queue it, just do it." 也就是说,简单地执行任务可能比通过队列快得多。

代码段受制于 "SQL Injection"。

INDEX(created_at)SELECT 可以 运行 完全在索引中。

而不是 DateTime 包,您可以简单地说 SELECT ... WHERE created_at > NOW() - INTERVAL 30 MINUTE

更多

使用 InnoDB,我建议 innodb_flush_log_at_trx_commit = 2 显着减少每秒 1000 个单独 INSERTs 造成的 I/O。