node.js之類的語言可以實現非同步的資料庫查詢功能,執行SQL語句之後不必等待資料庫回傳結果。繼續去執行其他的程式碼,當資料庫回傳結果是再處理資料處理,例如渲染頁面,並將HTML頁面傳送給客戶端。這樣應用程式完全不需要阻塞等待。這種方式運作效率非常高。
PHP中是否可以實現類似的非同步非阻塞MySQL查詢呢?使用github搜尋發現一個項目看起來是做此功能的,https://github.com/kaja47/async-mysql,查看程式碼是基於React.PHP.的。但並不是真正的非同步SQL。實現的原理是設定一個定時器,每0.02秒輪詢一次。雖然也可以用,但這樣很浪費CPU資源。不是真正的非同步MYSQL。
現在Swoole1.6.2提供了swoole_event_add和swoole_get_mysqli_sock 2個新的函數,使用它完全可以實現真正的PHP非同步MySQL。下面講一下具體的實作。
程式碼:
$db = new mysqli;
$db->connect('127.0.0.1', 'root', 'root', 'test');
$db->query("show tables , MYSQLI_ASYNC);
swoole_event_add(swoole_get_mysqli_sock($db), function($db_sock) {
global $db;
$res = $db->reap_async_MYd;
swoole_event_exit();
});
先連接mysql,連線成功後執行SQL語句,要在第二個參數指定MYSQLI_ASYNC。表示此查詢為異步。 query函數會立即傳回,這時候並沒有得到mysqli_result。
接著呼叫swoole_get_mysqli_sock函數取到mysql連接的socket,並且呼叫swoole_event_add將它加入到swoole的epoll事件循環中。當資料庫傳回結果是會回調我們剛才制定的函數。
這時候再來呼叫mysqli_reap_async_query得到result,呼叫fetch_all函數得到資料。
這個過程是完全非同步非阻塞的,不存在任何浪費CPU的程式碼。這個程式碼還可以用在伺服器端程式上,具體程式碼實作後續會再寫一篇文章詳細介紹。