Swoole 協程 MySQL 客戶端與非同步回撥 MySQL 客戶端的對比

yxhsea發表於2019-06-13

為什麼要對比這兩種不同模式的客戶端?

非同步 MySQL 回撥客戶端是雖然在 Swoole 1.8.6 版本就已經發布了,
但是非同步回撥的層層巢狀,讓編碼變得很彆扭。
如今 Swoole 4.3 版本都已經發布了,並且已經支援協程化的 MySQL 客戶端,
這意味著可以完全採用同步編碼的模式,來進行程式開發了,
對於開發者來說這是一個大好的訊息。
而且在 Swoole 4.3 版本之後,就已經移出了非同步回撥客戶端,
官方也一直推薦使用協程客戶端進行編碼。

一、Swoole 協程 MySQL 客戶端

從 Swoole 4.0 版本開始提供了完整的協程,
應用層可以使用完全的同步模式的程式設計方式,底層自動實現非同步 IO。
Swoole 的 MySQL 協程客戶端需要在協程的上下文環境下執行。
具體的使用方法直接看下面的示例即可。

1. 連線 MySQL 資料庫

<?php

co::create(function() {
    $swoole_mysql = new Swoole\Coroutine\MySQL();
    $swoole_mysql->connect([
        'host' => 'mysql',
        'port' => 3306,
        'user' => 'root',
        'password' => 'root',
        'database' => 'fastadmin',
    ]);
    $res = $swoole_mysql->query('select sleep(1)');

    // 新增
    // 更新
    // 查詢
    // 刪除
    // 事務操作
    // ......
});

2. 新增操作

<?php

co::create(function() {
    $stmt = $db->prepare('INSERT INTO runoob_tbl (runoob_title, runoob_author, submission_date) VALUES (?, ?, ?');
    if ($stmt == false){
        var_dump($db->errno, $db->error);
    } else {
        $ret2 = $stmt->execute(['學習 PHP', '學習 PHP', date("Y-m-d")]);
        var_dump($ret2);
    }
});

3. 查詢操作

<?php

co::create(function() {
   $res = $swoole_mysql->query('SELECT * FROM runoob_tbl WHERE runoob_id=1');
    if($res === false) {
        return;
    }
    foreach ($res as $value) {
        echo $value['runoob_title'];
    } 
});

4. 更新操作

<?php

co::create(function() {
    $stmt = $db->prepare('UPDATE runoob_tbl SET runoob_title=? WHERE runoob_id=?');
    if ($stmt == false){
        var_dump($db->errno, $db->error);
    } else {
        $ret2 = $stmt->execute(['學習 C++', 1]);
        var_dump($ret2);
    }
});

5. 刪除操作

<?php

co::create(function() {
    $stmt = $db->prepare('DELETE FROM runoob_tbl WHERE runoob_id=1');
    if ($stmt == false){
        var_dump($db->errno, $db->error);
    } else {
        $ret2 = $stmt->execute(['學習 C++', 1]);
        var_dump($ret2);
    }
});

6. 事務操作

<?php

co::create(function() {
    $db->begin();

    $stmt = $db->prepare('INSERT INTO runoob_tbl (runoob_title, runoob_author, submission_date) VALUES (?, ?, ?');
    if ($stmt == false){
        var_dump($db->errno, $db->error);
    } else {
        $ret2 = $stmt->execute(['學習 PHP', '學習 PHP', date("Y-m-d")]);
        var_dump($ret2);
    }

    $stmt = $db->prepare('UPDATE runoob_tbl SET runoob_title=? WHERE runoob_id=?');
    if ($stmt == false){
        var_dump($db->errno, $db->error);
        $db->rollback();
    } else {
        $ret2 = $stmt->execute(['學習 C++', 1]);
        var_dump($ret2);
    }

    $db->commit();  
});

三、Swoole 非同步回撥 MySQL 客戶端

Swoole 在 1.8.6 版本提供了全新的非同步 MySQL 客戶端,底層實現了 MySQL 通訊協議。
無需依賴其他第三方庫,如 libmysqlclient, mysqlnd, mysqli 等。
無需通過 --enable-async-mysql 編譯引數開啟。
Swoole 的 MySQL 非同步回撥客戶端的使用示例直接看下文即可。

注:非同步回撥客戶端在 Swoole 4.3 版本已經被移出了(標誌著已經過時了),建議使用協程客戶端。

1. 連線 MySQL 資料庫

<?php

$db = new swoole_mySQL();

$server = [
    'host' => 'mysql',
    'port' => 3306,
    'user' => 'root',
    'password' => 'root',
    'database' => 'fastadmin',
    'charset'  => 'utf8',
    'timeout'  => 2
];

$db->connect($server, function ($db, $r) {
    if ($r === false) {
        var_dump($db->connect_errno, $db->connect_errno);
        die();
    }

    // 新增
    // 更新
    // 查詢
    // 刪除
    // 事務操作
    // ......
)

2. 新增操作

<?php

// 新增
$sql = "INSERT INTO runoob_tbl (runoob_title, runoob_author, submission_date) VALUES (\"學習 PHP\", \"菜鳥教程\", NOW())";
$db->query($sql, function(swoole_mySQL $db, $r) {
    if ($r === false) {
        echo "新增資料失敗, 錯誤資訊: " . $db->error . ", 錯誤碼: " . $db->errno . "\n";
    } elseif ($r === true) {
        echo "新增資料成功, ID為:" . $db->insert_id, ", 影響行數: " . $db->affected_rows . "\n";
    }
    $db->close();
});

3. 更新操作

<?php

// 修改
$sql = "UPDATE runoob_tbl SET runoob_title='學習 C++' WHERE runoob_id=1";
$db->query($sql, function(swoole_mySQL $db, $r) {
    if ($r === false) {
        echo "新增資料失敗, 錯誤資訊: " . $db->error . ", 錯誤碼: " . $db->errno . "\n";
    } elseif ($r === true) {
        echo "新增資料成功, ID為:" . $db->insert_id, ", 影響行數: " . $db->affected_rows . "\n";
    }
    var_dump($r);
    $db->close();
});

4. 查詢操作

<?php

// 查詢
$sql = "SELECT * FROM runoob_tbl WHERE runoob_id=1";
$db->query($sql, function(swoole_mySQL $db, $r) {
    if ($r === false) {
        echo "新增資料失敗, 錯誤資訊: " . $db->error . ", 錯誤碼: " . $db->errno . "\n";
    }
    var_dump($r);
    $db->close();
});

5. 刪除操作

<?php

// 刪除
$sql = "DELETE FROM runoob_tbl WHERE runoob_id=1";
$db->query($sql, function(swoole_mySQL $db, $r) {
    if ($r === false) {
        echo "新增資料失敗, 錯誤資訊: " . $db->error . ", 錯誤碼: " . $db->errno . "\n";
    }
    var_dump($r);
    $db->close();
});

6. 事務操作

<?php

// 事務
$db->begin(function(swoole_mySQL $db, $r) {
    $sql = "INSERT INTO runoob_tbl (runoob_title, runoob_author, submission_date) VALUES (\"學習 PHP\", \"菜鳥教程\", NOW())";
    $db->query($sql, function(swoole_mySQL $db, $r) {
        if ($r === true) {
            $sql = "UPDATE runoob_tbl SET runoob_title1='學習 C++' WHERE runoob_id=5";
            $db->query($sql, function(swoole_mySQL $db, $r){
                if ($r === true) {
                    $db->commit(function(swoole_mySQL $db, $r) {
                        if ($r === true) {
                            echo "commit ok \n";
                        }
                    });
                }

                if ($r === false) {
                    $db->rollback(function(swoole_mySQL $db, $r) {
                        if ($r === true) {
                            echo "commit failed, rollback success \n";
                        }
                    });
                }
                $db->close();
            });
        }
    });
});

四、參考文件

五、總結

  • 在 Swoole 4.3 版本以後已經移出了非同步回撥模組了。
  • 以後的開發可以直接協程的客戶端進行編碼了。
  • 協程客戶端需要在協程的上下文環境中進行編碼。
  • 不建議再使用非同步回撥模組。

相關文章