× 警告!旧版文档已经暂停维护,请查看新版文档。点击前往新版文档

swoole_mysql_query

异步地执行一条SQL语言,需要依赖MySQLi和mysqlnd扩展。此函数是swoole底层提供的真异步函数。解决了PHP官方mysqli->reap_async_query方法存在的2个严重问题。

  1. mysqli->reap_async_query的recv缓冲区设置过小,在读取较大的RecordSet时会浪费大量read系统调用,性能不佳
  2. MySQL服务器的RecordSet可能会分段发送,mysqli->reap_async_query方法会阻塞。导致程序退化为同步阻塞模式。并发能力大大降低

swoole_mysql_query底层使用64K内存缓冲区,即使读取很大的RecordSet也仅需少量的read系统调用。另外swoole_mysql_query借助swoole提供的Epoll接口异步读取MySQL服务器的RecordSet,整个过程没有任何阻塞。

函数原型

function swoole_mysql_query(mysqli $link, string $sql, callable $callback);
  • $link为已连接的mysqli对象
  • $sql为要执行的SQL语句
  • $callback执行成功后会回调此函数
  • 每个MySQLi连接只能同时执行一条SQL,必须等待返回结果后才能执行下一条SQL

swoole_mysql_query需要swoole-1.8.0或更高版本,并且仅可用于CLI命令行环境
1.8.6或更高版本已移除

回调函数

function onSQLReady(mysqli $link, mixed $result);
  • 执行失败,$resultfalse,读取$link对象的_error属性获得错误信息,_errno属性获得错误码
  • 执行成功,SQL为非查询语句,$resulttrue,读取$link对象的_affected_rows属性获得影响的行数,_insert_id属性获得Insert操作的自增ID
  • 执行成功,SQL为查询语句,$result为结果数组

使用示例

$db = new mysqli;

$db->connect('127.0.0.1', 'root', 'root', 'test');
$sql = "SELECT * FROM  `userinfo` LIMIT 0, 10000";
$s = microtime(true);

swoole_mysql_query($db, $sql, function(mysqli $db, $r) {
    global $s;
    //SQL执行失败了
    if ($r == false)
    {
        var_dump($db->_error, $db->_errno);
    }
    //执行成功,update/delete/insert语句,没有结果集
    elseif ($r == true)
    {
        var_dump($db->_affected_rows, $db->_insert_id);
    }
    //执行成功,$r是结果集数组
    else
    {
        echo "count=".count($r).", time=".(microtime(true) - $s), "\n";
        var_dump($r);

        swoole_mysql_query($db, "show tables", function ($db, $r) {
            var_dump($r);
        });
    }
});

  • Mok

    非常有用,解决了不少问题。多谢峰哥!

  • ttt

    $mysqli->prepare() 怎么实现呢 如此重要的东西

  • 新风宇宙

    执行存储过程, 结果集那边会出问题, 要怎么处理啊