数据库:入门

简介

Swoft DB 操作高度兼容 Laravel 能使用 原生的 SQL、流畅的查询构造器,和 Eloquent ORM 在从此与 DB 交互变得简单,去掉了复杂的对象关联模型。采用原生 PDO 方式连接数据库。

说下为什么这次要采用PDO 的原生方式

使用mysqlnd模式的pdo、mysqli扩展会加入Hook监听,如果未启用mysqlnd将不支持协程化

也即使说 IO 操作会被自动转换和 swooleMySQL 协程客户端一样。让开发变得简单,更贴近传统框架。

基础配置

数据库的配置放置在 app\bean.php文件中,去掉了繁琐的.env文件配置,你可以认为配置的 db 是一个 bean 对象。

return [
    'db'         => [
       'class'     => Database::class,
       'dsn'       => 'mysql:dbname=test;host=127.0.0.1',
       'username'  => 'root',
       'password'  => '123456',
       'charset'   => 'utf8mb4',
    ],
];

配置方式类似 yii2 对象属性注入的方式的配置,可以通过 \bean('db') 来获取当前配置的Database对象

  • class 指定当前 bean容器使用哪个一个类 当然你也可以指定自己实现的database
  • dsn PDO需要使用的连接配置信息
  • username 数据登录用户名
  • password 数据库登录密码
  • charset 数据库字符集

属性配置详解

详细配置例子 :


'db'  => [
    'class'    => Database::class,
    'dsn'      => 'mysql:dbname=swoft;host=127.0.0.1',
    'username' => 'root',
    'password' => '123456',
    'charset'  => 'utf8mb4',
    'prefix'   => 't_',
    'options'  => [
        \PDO::ATTR_CASE => \PDO::CASE_NATURAL,
    ],
    'config'   => [
        'collation' => 'utf8mb4_general_ci',
        'strict'    => false,
        'timezone'  => '+8:00',
        'modes'     => 'NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES',
        'fetchMode' => PDO::FETCH_ASSOC,
    ],
],
  • prefix 表名的公共前缀或后缀。
  • options PDO属性选项
    /**
     * 默认的PDO连接选项。当然你可以选择替换它 
     *
     * @var array
     */
    $options = [
        \PDO::ATTR_CASE              => \PDO::CASE_NATURAL,
        \PDO::ATTR_ERRMODE           => \PDO::ERRMODE_EXCEPTION,
        \PDO::ATTR_ORACLE_NULLS      => \PDO::NULL_NATURAL,
        \PDO::ATTR_STRINGIFY_FETCHES => false,
        \PDO::ATTR_EMULATE_PREPARES  => false,
        \PDO::ATTR_ERRMODE           => \PDO::ERRMODE_EXCEPTION,
    ];
  • config MySQL的其他配置, 默认驱动仅实现了 MySQL 如果需要其他数据库启动请参考Connector & Connection
    • collation 设置指定数据集如何排序。
    • timezone 设置时区设置
    • modes 设置连接模式(可以是一维数组,也可以是英文逗号分割的 modes)
    • strict 设置获取查询以启用严格模式(实际上也是设置modes配置)
    • fetchMode 设置 pdo 返回的类型 默认的连接池返回的类型为 FETCH_ASSOC 也就是数组方式, 其他类型参考官方手册

默认的db.pool连接池的DB类查询查询操作,返回的是数组。自定义的db连接池如果也需要返回数组,需要设置fetchMode参数 为 PDO::FETCH_ASSOC,否则返回是的 stdClass 对象。

读写&连接

'db2'  => [
    'class'  => Database::class,
    'charset'  => 'utf8mb4',
    'prefix'   => 't_',
    'options'  => [],
    'config'   => [
       'collation' => 'utf8mb4_general_ci',
       'strict'    => false,
       'timezone'  => '+8:00',
       'modes'     => 'NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES',
    ],
    'writes' => [
        [
            'dsn'      => 'mysql:dbname=swoft;host=127.0.0.1',
            'username' => 'root',
            'password' => '123456',
        ],
    ],
    'reads'  => [
        [
            'dsn'      => 'mysql:dbname=swoft;host=127.0.0.1',
            'username' => 'root',
            'password' => '123456',
        ],
    ],
],
  • writes 主库配置 执行Create Update Delete 操作的时候会从连接池 随机选择主库节点执行

  • reads 从库配置 Read 操作使用默认会从连接池 随机选择一个从库节点执行 如果想强制查询的主库,那么请在链式操作中使用 useWritePdo() 方法即可

如果你想公用配置请参考基础配置。 默认会覆盖合并dsn' , 'username' ,'password','charset' ,'prefix' ,'options', 'config这些选项配置公用,所以在writes/reads中配置变化的值就可以了,你也可以覆盖上层配置。

连接池配置

想必用的 1.0 的小伙伴对连接池并不陌生 2.x 对它进行了简化配置 连接池的好处也不用多说 更好的管理 资源,对数据库的保护

db 的连接是通过 连接池创建和释放的,通过ConnectionManager类来管理连接,创建的为短链接 操作执行失败会重试一次。

每当调用 toSql() 方法或者执行完操作的时候 都会归还连接到连接池中, 默认是连接池 名称是 db.pool 使用的 database\bean('db') 也就是基础配置配置的, 连接池配置放置在 app\bean.php文件中。

每一个 `worker` 都会创建一个同样的连接池。并不是越多越好,参数配置要根据,机器配置和 和`worker` 个数衡量。

下面我们看看连接池如何自定义一个连接池

'db.pool2' => [
    'class'       => \Swoft\Db\Pool::class,
    'database'    => \bean('db2'),
    'minActive'   => 10,
    'maxActive'   => 20,
    'maxWait'     => 0,
    'maxWaitTime' => 0,
    'maxIdleTime' => 60,
 ]
  • class 是默认的 Pool 对象 你可以更具官方的自己继承实现,然后换成自己 的 Pool 类名就可以了
  • database 驱动的数据库对象 是读 & 写连接配置的
  • minActive 连接池需要维持的连接数
  • maxActive 连接池最大保持的连接数
  • maxWait 连接池最多等待连接数, 如果没有限制为0(默认)
  • maxWaitTime 连接最大等待时间,单位秒,如果没有限制为0(默认)
  • maxIdleTime 连接最大空闲时间,单位秒

Connector&Connection

连接器和连接 的关系是创建连接必备的

Connector

Connector 主要是用于,根据配置创建真实的 PDO 创建连接

Connection

Connection主要用于,数据库的语法解析,设置表前缀,获取默认查询语法实例,重连错误判断

Swoft 默认仅提供的 MySQL 的Connector&Connection 为什么呢。 因为swoole暂且将 pdo_pgsql,pdo_ori,pdo_odbc,pdo_firebird 这些 PDO扩展加入 底层 Hook

也就是说使用 pdo_pgsql,pdo_ori,pdo_odbc,pdo_firebird 执行的 IO 操作不会让出 CPU 资源同步执行的,执行期间协程不会上下文切换

如果想要使用 pgsql(你可以用 Swoole协程 PgSQL 客户端)也是可以的 只需实现ConnectorConnection参照 MySQL 的实现方式即可

关于分库分表的一些见解

Swoft DB 暂未提供分库和分表 的方案 后续会提供dbSelect interface 实现接口来选择不同的database, 目前暂时可以通过配置db.pool 连接池db 连接来选择不同数据库。切换连接池详见:选择连接池

关于去掉DB服务化的见解

Swoft 2.x去掉了 服务发现相关的东西,融入框架显得笨重,后续会提供 dbProvide interface 来提供获取连接地址接口

/docs/2.x/zh-CN/db/setting.html
progress-bar