在 5.1 版本中增加了多種數據庫協程客户端的支持,並且全部以 PDO 接口的方式提供,舊的業務代碼無需做任何更改即可一鍵切換為協程模式,異步非阻塞地併發執行。
包括:
pdo_pgsqlpdo_odbcpdo_sqlitepdo_oci(Oracle數據庫)
開啓方法
增加了 4 個編譯參數和 Runtime Hook 選項,開啓這些協程客户端。
編譯選項
--with-swoole-odbc,依賴unixodbc-dev--with-swoole-pgsql,依賴libpq-dev--with-swoole-sqlite,依賴libsqlite3-dev--with-swoole-oracle,依賴oracle-instantclient
Runtime Hook 選項
SWOOLE_HOOK_PDO_PGSQLSWOOLE_HOOK_PDO_ODBCSWOOLE_HOOK_PDO_SQLITESWOOLE_HOOK_PDO_ORACLE
這些選項已包含在 SWOOLE_HOOK_ALL 中,也可單獨啓用其中一個客户端。
PDO_PGSQL
在之前的版本中,提供了 Swoole\Coroutine\PostgreSQL 客户,由於是全新的 API,用户需要兼容 PHP-FPM 和 Swoole,使用並不廣泛。
go(function () {
$pg = new Swoole\Coroutine\PostgreSql();
$conn = $pg->connect("host=127.0.0.1 port=5432 dbname=test user=test password=");
$result = $pg->query($conn, 'SELECT * FROM test;');
$arr = $pg->fetchAll($result);
var_dump($arr);
});
5.1 版本中增加了 Runtime Hook PDO_PGSQL,可以直接使用 FPM 下的歷史代碼。
go(function () {
$pdo = new PDO("pgsql:host={$host};port={$port};dbname={$dbname}", $user, $password);
$statement = $pdo->query('select * from user where id =1 limit 1');
var_dump($statement->fetch(PDO::FETCH_ASSOC));
});
PDO_ODBC
ODBC(Open Database Connectivity)是一種為多種數據庫管理系統提供統一接口的標準化技術。它是由微軟公司提出的,目的是為了實現異構性,使得應用程序能夠訪問多種不同類型的數據源。 ODBC 的標準定義了應用程序發出請求的 API,以及由驅動程序提供的響應請求的 API。ODBC 是一種開放的、跨平台的技術,可以在多種操作系統和編程語言中使用。
絕大多數關係型數據庫都支持 ODBC 驅動,其中包括:
Microsoft SQL ServerOracleIBM DB2MySQLPostgreSQLSQLiteTeradataMicrosoft AccessSAP Sybase Adaptive Server Enterprise (ASE)Informix
這些數據庫使用 ODBC 驅動程序來提供訪問接口,從而使開發人員可以在使用不同的數據庫時使用相同的代碼訪問數據。
5.1 版本支持了 PDO_ODBC 的協程化支持,藉助 ODBC 幾乎可以支持所有數據庫,使得這些數據庫也可以運行在 Swoole 協程模式下。
在 Linux 下需要安裝 unixodbc 庫來支持 odbc
sudo apt install unixodbc-dev
與其他數據庫驅動不同,odbc需要先使用 odbcinst 工具註冊數據庫。在 Linux 下要配置 /etc/odbcinst.ini 文件實現。
odbcinst.ini
[mysql]
Driver=libmaodbc.so
Description=MariaDB Connector/ODBC(Unicode)
Threading=0
UsageCount=1
配置文件放置於 /etc/odbcinst.ini,Driver=libmaodbc.so就是告訴 odbc 使用這個動態鏈接庫作為驅動層。
若要支持其他更多數據庫類型,就需要安裝該數據庫的 ODBC 驅動。例如 MySQL ODBC 驅動可以使用 odbc-mariadb
sudo apt install odbc-mariadb
執行成功後,就會安裝 libmaodbc.so 到系統庫目錄中。
mysql_odbc.ini
註冊數據庫到 ODBC ,需要編寫一份配置文件,包含數據庫的主機地址、用户名、密碼等信息
[mysql-test]
Description = MySQL test database
Trace = On
TraceFile = stderr
Driver = mysql
SERVER = 127.0.0.1
USER = root
PASSWORD = root
PORT = 3306
DATABASE = test
然後使用 odbcinst 工具註冊數據庫:
odbcinst -i -d -f ~/mysql-odbc.ini
可以使用 isql 工具執行 SQL
htf@swoole-12:/etc$ isql mysql-test
+---------------------------------------+
| Connected! |
| |
| sql-statement |
| help [tablename] |
| quit |
| |
+---------------------------------------+
SQL> show tables
+-----------------------------------------------------------------+
| Tables_in_test |
+-----------------------------------------------------------------+
| ckl |
| custom |
| firmware |
| numbers |
| userinfo |
+-----------------------------------------------------------------+
SQLRowCount returns 5
5 rows fetched
SQL>
代碼
Co\run(function () {
$pdo = new PDO('odbc:mysql-test');
$statement = $pdo->prepare('show tables');
$statement->execute();
var_dump(count($statement->fetchAll(PDO::FETCH_COLUMN)), 1);
});
PDO_SQLITE
SQLite一款輕量級的、開源的、嵌入式關係型數據庫管理系統。其最主要的優勢是小巧、快速,具有對事務的支持,並且具有可移植性。以下是SQLite的一些優點:
- 佔用資源少:
SQLite是一款嵌入式數據庫,不需要安裝或維護,以一個文件的形式存放在本地操作系統文件系統上,不需要獨立運行一個數據庫服務器進程。因此,其佔用資源非常少,可以在資源受限的嵌入式設備、移動設備上運行。 - 速度快:
SQLite是一款非常快速的關係型數據庫,能夠輕鬆處理中小型數據集。相比於其他傳統的關係型數據庫,它的讀寫速度相對較快。 - 對事務的支持:與其他輕量級數據庫相比,
SQLite對事務的支持非常好,並支持Acid屬性,可以防止數據丟失或損壞。 - 可移植性:SQLite的文件格式是獨立於操作系統的,這使得用户能夠將其數據庫文件從一個操作系統遷移到另一個操作系統。
在以下情況下可以考慮使用 SQLite:
- 本地數據存儲:
SQLite適合在應用程序中存儲本地數據,如移動應用程序中的用户個人數據、本地設置和緩存等。 - 中小型數據量存儲:
SQLite適合存儲中小型數據集,例如小型企業或單個用户的數據,而不是應用場景複雜或數據集非常大的情況。 - 需要進行離線數據讀寫操作:由於
SQLite的文件格式獨立於操作系統,因此可以將數據存儲為文件,並在離線情況下進行讀寫操作。 - 快速原型開發:由於
SQLite易於使用和管理,因此適合進行快速原型開發,以便在真正的生產中測試和優化應用程序。
5.1 版本提供了 sqlite 嵌入式數據庫的協程客户端支持,同樣也是使用 PDO 作為接口層。
編譯選項
./configure --enable-swoole-sqlite
需要依賴 libsqlite3-dev
代碼實例
go(function() {
$db = new PDO('sqlite::memory:');
$db->exec('create table test (id int)');
$stmt = $db->prepare('insert into test values(?)');
$i = 2024;
$stmt->execute([$i]);
$stmt = $db->prepare('select id from test where id = ?');
$stmt->execute([$i]);
var_dump($stmt->fetch(PDO::FETCH_ASSOC)['id'] == $i);
});
PDO_OCI
Oracle 數據庫是美國甲骨文公司研發的大型關係型數據庫,在全球範圍內有很多大型企業使用 Oracle 數據庫。電商平台、銀行、金融、電信等很多商業項目核心系統使用了 Oracle 數據庫。
以下是Oracle數據庫的一些特點和功能:
- 高性能:
Oracle數據庫能夠處理大量的併發用户請求,並快速的處理大規模的數據。 - 規模性:
Oracle數據庫支持大規模的數據庫集羣和複雜的匯聚操作,使得它在大型企業中和關鍵業務應用中非常受歡迎。 - 冗餘備份:
Oracle數據庫提供強大的冗餘備份和恢復功能,支持在線備份和恢復、增量備份和恢復、點時間恢復等。 - 安全性:
Oracle數據庫提供用於對數據庫進行加密、數據脱敏、訪問控制和身份驗證的功能。 - 靈活性:
Oracle數據庫支持多種數據類型和編程語言,並提供了強大的存儲、索引和查詢功能。 - 高可用性:
Oracle數據庫具有高可用性,支持主從同步、自動故障轉移和容錯功能,這些功能可以確保系統的連續性和穩定性。 - 性能優化:
Oracle數據庫提供了豐富的性能優化功能,並支持各種調優技術,以確保數據庫在高負載下穩定運行。
5.1版本提供了原生的 pdo_oci 協程客户端實現。可在協程環境下併發連接操作 Oracle 數據庫。
編譯選項
需要增加 --with-swoole-oracle=instantclient,/path/to/instant/client/lib 參數來啓用 PDO_OCI 協程客户端。
可在 Oracle 官網下載客户端驅動
apt install -y libaio-dev
apt install -y libaio1
wget -nv https://download.oracle.com/otn_software/linux/instantclient/instantclient-basiclite-linuxx64.zip
unzip instantclient-basiclite-linuxx64.zip && rm instantclient-basiclite-linuxx64.zip
wget -nv https://download.oracle.com/otn_software/linux/instantclient/instantclient-sdk-linuxx64.zip
unzip instantclient-sdk-linuxx64.zip && rm instantclient-sdk-linuxx64.zip
mv instantclient_*_* ./instantclient
rm ./instantclient/sdk/include/ldap.h
# fix debug build warning: zend_signal: handler was replaced for signal (2) after startup
echo DISABLE_INTERRUPT=on > ./instantclient/network/admin/sqlnet.ora
mv ./instantclient /usr/local/
echo '/usr/local/instantclient' > /etc/ld.so.conf.d/oracle-instantclient.conf
ldconfig
代碼實例
Co\run(function () {
$db = new PDO('oci:dbname=127.0.0.1:'.$ORACLE_PORT.'/'.$ORACLE_SERVICE_NAME.';charset=AL32UTF8', $ORACLE_USER, $ORACLE_PASSWORD);
$db->setAttribute(PDO::ATTR_CASE, PDO::CASE_LOWER);
$db->exec("create table test (id int)");
for($i = 0; $i < 10; $i++) {
go(function () use($db, $i){
$stmt = $db->prepare("insert into test values (?)");
$stmt->execute([$i]);
$stmt = $db->prepare("select id from test where id = ?");
$stmt->execute([$i]);
var_dump($stmt->fetch(PDO::FETCH_ASSOC)['id'] == $i);
});
}
});
結語
在 5.1 版本中增加了更多數據庫協程客户端的支持,使得 Swoole 協程模式下可以支持多種數據庫。
接口上選擇了使用 PDO API,保持了與 PHP-FPM 的兼容性。無需修改代碼,也沒有額外的學習成本。
在實現上使用了原生 API + swoole::coroutine::async,基於可伸縮的 AIO 線程池和協程調度 API 。
這樣的方式更加安全健壯,可直接用於生產環境。