3

5.1 版本中增加了多种数据库协程客户端的支持,并且全部以 PDO 接口的方式提供,旧的业务代码无需做任何更改即可一键切换为协程模式,异步非阻塞地并发执行。

包括:

  1. pdo_pgsql
  2. pdo_odbc
  3. pdo_sqlite
  4. pdo_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_PGSQL
  • SWOOLE_HOOK_PDO_ODBC
  • SWOOLE_HOOK_PDO_SQLITE
  • SWOOLE_HOOK_PDO_ORACLE

这些选项已包含在 SWOOLE_HOOK_ALL 中,也可单独启用其中一个客户端。

PDO_PGSQL

在之前的版本中,提供了 Swoole\Coroutine\PostgreSQL 客户,由于是全新的 API,用户需要兼容 PHP-FPMSwoole,使用并不广泛。

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

ODBCOpen Database Connectivity)是一种为多种数据库管理系统提供统一接口的标准化技术。它是由微软公司提出的,目的是为了实现异构性,使得应用程序能够访问多种不同类型的数据源。 ODBC 的标准定义了应用程序发出请求的 API,以及由驱动程序提供的响应请求的 APIODBC 是一种开放的、跨平台的技术,可以在多种操作系统和编程语言中使用。

绝大多数关系型数据库都支持 ODBC 驱动,其中包括:

  1. Microsoft SQL Server
  2. Oracle
  3. IBM DB2
  4. MySQL
  5. PostgreSQL
  6. SQLite
  7. Teradata
  8. Microsoft Access
  9. SAP Sybase Adaptive Server Enterprise (ASE)
  10. 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.iniDriver=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的一些优点:

  1. 占用资源少:SQLite是一款嵌入式数据库,不需要安装或维护,以一个文件的形式存放在本地操作系统文件系统上,不需要独立运行一个数据库服务器进程。因此,其占用资源非常少,可以在资源受限的嵌入式设备、移动设备上运行。
  2. 速度快:SQLite是一款非常快速的关系型数据库,能够轻松处理中小型数据集。相比于其他传统的关系型数据库,它的读写速度相对较快。
  3. 对事务的支持:与其他轻量级数据库相比,SQLite对事务的支持非常好,并支持Acid属性,可以防止数据丢失或损坏。
  4. 可移植性:SQLite的文件格式是独立于操作系统的,这使得用户能够将其数据库文件从一个操作系统迁移到另一个操作系统。

在以下情况下可以考虑使用 SQLite

  1. 本地数据存储:SQLite 适合在应用程序中存储本地数据,如移动应用程序中的用户个人数据、本地设置和缓存等。
  2. 中小型数据量存储:SQLite 适合存储中小型数据集,例如小型企业或单个用户的数据,而不是应用场景复杂或数据集非常大的情况。
  3. 需要进行离线数据读写操作:由于SQLite 的文件格式独立于操作系统,因此可以将数据存储为文件,并在离线情况下进行读写操作。
  4. 快速原型开发:由于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数据库的一些特点和功能:

  1. 高性能: Oracle 数据库能够处理大量的并发用户请求,并快速的处理大规模的数据。
  2. 规模性: Oracle 数据库支持大规模的数据库集群和复杂的汇聚操作,使得它在大型企业中和关键业务应用中非常受欢迎。
  3. 冗余备份: Oracle 数据库提供强大的冗余备份和恢复功能,支持在线备份和恢复、增量备份和恢复、点时间恢复等。
  4. 安全性: Oracle 数据库提供用于对数据库进行加密、数据脱敏、访问控制和身份验证的功能。
  5. 灵活性: Oracle 数据库支持多种数据类型和编程语言,并提供了强大的存储、索引和查询功能。
  6. 高可用性: Oracle 数据库具有高可用性,支持主从同步、自动故障转移和容错功能,这些功能可以确保系统的连续性和稳定性。
  7. 性能优化: 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

这样的方式更加安全健壮,可直接用于生产环境。


韩天峰
7.9k 声望11.1k 粉丝

Swoole 开源项目创始人