Ger*_*ica 5 php mysqli asynchronous mysqlnd
我已经检查了,我不这么认为.关于异步mysql有很多问题,但我对一个特定的问题很感兴趣:
在这种情况下我正在使用php和mysql.
假设我有这样的mysqli连接:
$link = new mysqli('localhost', 'root', 'password', 'A_Database');
Run Code Online (Sandbox Code Playgroud)
我已经安装了mysqlnd来使用'MYSQL_ASYNC'参数执行异步mysql查询:
$link->query("INSERT INTO `A_Table` VALUES('stuff!')", MYSQLI_ASYNC);
Run Code Online (Sandbox Code Playgroud)
我只是想插入一条记录,我也不需要找回它,直到遥远的未来,所以我不担心需要多长时间异步查询完成了,我也不需要进行一些最后的当我知道查询完成时的操作.一旦我超出了插入查询发生的代码部分,我确实需要执行其他不相关的mysql查询.
执行这样的查询将阻止脚本中的其他查询出现不同步错误.为了解决这个问题,我必须在每次异步查询后添加类似下面的代码:
$links = $errors = $reject = array($link);
if ($link->poll($links, $errors, $reject, 1)) {
foreach ($links as $resultLink) {
if ($result = $resultLink->reap_async_query()) {
if (is_object($result)) {
$result->free();
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这有效地阻止了不同步错误,我的代码工作正常.
但有两件事情仍困扰着我:
1)我不想打扰这个,因为我只是执行插入查询,当我知道插入完成时,我不关心我的代码中有一些响应.
2)轮询代码在我的服务器上运行得非常慢; 远比执行常规查询慢,并同步获取结果.
我想运行带有两个要求的插入查询; 查询是非阻塞的(异步),我以后仍然可以执行其他mysql查询.我只想插入查询并"忘记它",然后继续我的代码.
有关最佳方法的建议是什么?
小智 8
如果您的目标是插入记录并继续执行代码而不必担心结果,则可以使用INSERT DELAYED语法而无需ASYNC标志:
$link->query("INSERT DELAYED INTO `A_Table` VALUES('stuff!')" );
Run Code Online (Sandbox Code Playgroud)
它立即返回,您可以继续在同一连接上执行新的查询.我们在日志系统中使用它.
如果您希望能够即发即忘查询,那么您当前的方法基本上是正确的,尽管我建议您遇到的缓慢可能是因为您将 '1' 设置为 中的 'secs' 参数$link->poll($links, $errors, $reject, 1)。这意味着轮询将等待最多 1 秒查询返回。如果您将其设置为“0”,那么它将不会等待,它将更快地返回查询是否完成的答案。
其次,如果您不需要此查询的答案,则可以在执行此查询时执行其他操作,如果您有其他操作,则不必坐在那里等待它在异步轮询循环中返回继续相处下去。这就是异步查询的设计目的。我建议您向查询执行方法添加检查,以检查是否已经执行了未完成的异步查询,因此每当您需要启动新查询时,只有这样它才会轮询服务器并等待任何先前的查询完成并变得可用。
或者,如果您想要运行多个彼此不产生任何影响或依赖的查询,则没有什么可以阻止您设置多个数据库连接并在所有这些连接上并行运行异步查询,或者设置新连接并执行当您需要时进行查询。
如果您想将 SQL 完全外包给另一个进程(没有 cron),一种方法是设置一个持久监控脚本,例如使用Supervisor / Gearman ,这样您就可以向它发送查询并让它处理进程中的查询(甚至服务器)与本地不同。这样做的好处是远程脚本作为 CLI 应用程序执行,因此具有更多使用分叉和多线程处理的能力,并且可以在暴露较少的环境中运行。
另一种方法(可选地使用 cron)是使用写入优化的(可能是内存中的)本地数据库表,快速执行对该表的插入,然后让另一个进程间歇性地读取该表(或者设置触发器来监视新的数据)条目),并让该进程从该表中获取新插入的行并将它们移动到速度较慢的主表中。
| 归档时间: |
|
| 查看次数: |
2194 次 |
| 最近记录: |