PHP异步并发访问mysql简单实现。
在实际的开发过程中,我们常常会遇到需要操作多张表,多个库的情况。有时因为一些限制我们不能进行连表(例如,异地数据库),所以只能用php串行访问后再在php里进行合并,有时还需要模拟mysql对合并后的结果进行排序、归并等。
这里产生的一个问题就是串行带来的访问时间问题。由于传统的串行访问方式,我们只能等到一条sql执行完毕后才可以执行下一条,所以执行时间是累加的。PHP官方手册提供了一种可以异步并发访问mysql的方式,详见:http://php.net/manual/zh/mysqli.poll.php,参考资料:https://svn.osgeo.org/mapguide/sandbox/rfc94/Oem/php/ext/mysqli/tests/mysqli_poll.phpt,使用此种方式,我们可以对Mysql进行异步并发访问,访问时间不再是串行累加,而是取决于执行时间最长的sql。
项目地址:https://github.com/huyanping/async-mysql-php
代码示例:
try{ $async_mysql=new\Jenner\Mysql\Async(); $async_mysql->attach( ['host'=>'127.0.0.1','user'=>'root','password'=>'','database'=>'test'], 'select * from stu' ); $async_mysql->attach( ['host'=>'127.0.0.1','user'=>'root','password'=>'','database'=>'test'], 'select * from stu limit 0, 3' ); $result=$async_mysql->execute(); print_r($result); }catch(Exception$e){ echo$e->getMessage(); }
async_mysql对象对mysql进行异步并发访问,attach方法接收每个请求必须的配置信息,execute方法为执行入口,其返回值是每条sql执行结果的数组,顺序与attach调用顺序一致。
当任何一个连接mysql出错或执行任何一条sql出错,都会引起异常抛出。这样设计主要是基于完整性的考虑,我们把所有需要执行的sql看做是一个整体事务,任何一个执行失败,则认为该事务失败。
composer信息:
"require":{ "jenner/async-mysql-php":"v0.1" }
或者直接引入/path/to/async-mysql-php/autoload.php文件
最后在阿里云上做了一个简单的测试,测试结果如下:
# 同步 [root@iZ942077c78Z async-mysql-php]# php tests/performance_sync.php ------------------------------------------ mark:[totaldiff] time:4.2648551464081s memory_real:18944KB memory_emalloc:18377.171875KB memory_peak_real:28416KB memory_peak_emalloc:27560.3828125KB [root@iZ942077c78Z async-mysql-php]# php tests/performance_sync.php ------------------------------------------ mark:[totaldiff] time:4.2285549640656s memory_real:18944KB memory_emalloc:18377.171875KB memory_peak_real:28416KB memory_peak_emalloc:27560.3828125KB [root@iZ942077c78Z async-mysql-php]# php tests/performance_async.php ------------------------------------------ mark:[totaldiff] time:1.455677986145s memory_real:38144KB memory_emalloc:32574.015625KB memory_peak_real:66816KB memory_peak_emalloc:65709.7734375KB # 异步 [root@iZ942077c78Z async-mysql-php]# php tests/performance_async.php ------------------------------------------ mark:[totaldiff] time:1.8936941623688s memory_real:38144KB memory_emalloc:32574.015625KB memory_peak_real:66816KB memory_peak_emalloc:65709.7734375KB [root@iZ942077c78Z async-mysql-php]# php tests/performance_async.php ------------------------------------------ mark:[totaldiff] time:1.5208158493042s memory_real:38144KB memory_emalloc:32574.015625KB memory_peak_real:66816KB memory_peak_emalloc:65709.7734375KB
实际上以上测试结果并没有太大意义。因为理论上这种异步并发的访问方式会绝对优于传统的串行访问方式,再次需要说明的是,访问数据库的时间接近执行时间最长的SQL。
到了这一步,我们已经可以实现对mysql进行异步并发访问了。如果我们还需要做多个数组的归并,可以使用《PHP模拟SQL的GROUP BY算法》中介绍的方法。其中提供的归并方式非常灵活,更胜mysql原生的group by。
如果还需要对合并后的结果做排序,可以使用https://github.com/huyanping/Zebra-Tools/blob/master/src/Jenner/Zebra/Tools/CommonArray.php#L90这段代码实现,非常方便。改函数来源于php手册http://php.net/manual/zh/function.array-multisort.php
原文地址:PHP异步并发访问mysql简单实现
async-mysql-php 引入 composer require jenner/async-mysql-php Or require /path/to/async-mysql-php/autoload.php 细节 基于mysqli::poll简单封装 当链接mysql出现错误或SQL执行出错时,会抛出异常 返回结果的顺序与attach顺序一致 接口 attach(),递交异步mysql任务
例如,mysql里有两个表: tb_user: userId, userName tb_userBook: userId, bookId, bookName 想通过检索最终得到这样的结果: [ { "userId": 1, "userName": "张三", "userBook": [ { "bookId": 1, "bookname": "书名1" }, { "bookId": 2, "book
本文实例讲述了PHP MySQL之Insert Into数据插入用法。 INSERT INTO 语句用于向数据库表中插入新纪录。 向数据库表插入数据 语法1:插入全部列 INSERT INTO table_name VALUES (value1, value2, ....) 语法2:插入部分列 INSERT INTO table_name (column1, column2, ...) VALUE
SOOWLE 版本:4.3.3 及以下 (笔者测试这里只有4.3.3 和4.2.1) swoole 中在task进程里是无法使用协程相关,以下代码运行会报错。 worker 进程里就没问这个问题,可以放心使用。 原因: RFC-1014提案使TaskWorker内可以使用异步和协程API。由于Task设计之初未考虑支持异步和协程。(4.2.12之后修改了) 文档地址:https://wiki.sw
I am using an application where i just need to download a pair of coordinates for google maps from a mysql server. I can do this successfully using php and a normal httpost but my app freezes for a fe
一直以来,php一直没有mysql连接池的概念,而在开发中大多数框架也是直接使用了长连接的方式。如Thinkphp就是使用的长连接。对于并发较小的项目来说,长连接确实可以提高查询效率,php不用每次去与mysql服务器建立连接,只要某个php-cgi连接过mysql,那么本次访问结束后,php不会释放与mysql的连接。当下次请求过来的时候,php就可以复用之前的连接,从而消除了建立连接是的额外损
对于大多数用 PHP 编写的程序,它的唯一目的是执行由多个任务组成的简单进程,其中任务必须按顺序执行,如数据处理。我们总是不得不忍受同步编程的停止和等待。代码执行的同步风格被称为阻塞,这意味着任务将一个接一个地执行。那么,如果我们想要运行任务而不让它们相互阻塞,这意味着我们需要一个非阻塞进程,那该怎么办呢?这种方法需要在 PHP 中应用异步编程方法,这里的任务将在不相互依赖的情况下执行。 在 PH
async-http-php 是个异步 HTTP 客户端,机遇 crul_mulit*,系统很简单,速度非常快。 如果你想使用 ssl 或者其他来请求一个网站,你可以实现一个 task 类和 TaskInterface 接口: date_default_timezone_set("PRC");require dirname(dirname(__FILE__)) . DIRECTORY_SEPARA
异步Mysql客户端 AsyncMysql::query($sql, $usePool = true) 第二个参数设为false将不会使用连接池中的资源,默认都会从连接池中取,配置连接池数量 => config/database.php 具体使用 use AsyncMysql; //设置超时时间 AsyncMysql::setTimeout(2); $res = (
mysql-async 是基于 swoole 开发的 PHP 异步 MySQL 客户端,内置连接池和任务排队机制。基于 mysql-async 可以编写出纯异步、支持超高并发的 PHP 应用。 $config = array( 'host' => '127.0.0.1', 'user' => 'root', 'password' => 'root', 'database'
(要求Workerman版本>=3.3.6) 注意: 此组件是第三方组件,可能会有潜在的bug,建议使用WorkermanMySQL组件。 安装: composer require react/mysql 示例: <?php require_once __DIR__ . '/vendor/autoload.php'; use WorkermanWorker; $worker = new Worke
异步Redis客户端 连接池(连接池默认开启) use AsyncRedis; //关闭连接池 AsyncRedis::enablePool(false); //开启连接池 AsyncRedis::enablePool(true); 使用AsyncRedis use AsyncRedis; //设置超时时间 AsyncRedis::s
异步Http客户端 Get方式 1.使用域名形式 use AsyncHttp; //直接使用域名, get方式 $http = new AsyncHttp('http://groupco.com'); //设置2s超时 $http->setTimeout(2); //$http->setCookies(['token' => 'xxxx']);
异步Tcp客户端 串行发包 use AsyncTcp; $tcp = new AsyncTcp('127.0.0.1', 9501); $tcp->setTimeout(2); //串行发送 $res = (yield $tcp->call('hello server!')); $res = (yield $tcp->call('hello serv