数据库:入门

简介

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

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

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

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

基础配置

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

  1. return [
  2. 'db' => [
  3. 'class' => Database::class,
  4. 'dsn' => 'MySQL:dbname=test;host=127.0.0.1',
  5. 'username' => 'root',
  6. 'password' => '123456',
  7. 'charset' => 'utf8mb4',
  8. ],
  9. ];

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

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

属性配置详解

详细配置例子 :

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

      读写&连接

  1. 'db2' => [
  2. 'class' => Database::class,
  3. 'charset' => 'utf8mb4',
  4. 'prefix' => 't_',
  5. 'options' => [],
  6. 'config' => [
  7. 'collation' => 'utf8mb4_general_ci',
  8. 'strict' => false,
  9. 'timezone' => '+8:00',
  10. 'modes' => 'NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES',
  11. ],
  12. 'writes' => [
  13. [
  14. 'dsn' => 'MySQL:dbname=swoft;host=127.0.0.1',
  15. 'username' => 'root',
  16. 'password' => '123456',
  17. ],
  18. ],
  19. 'reads' => [
  20. [
  21. 'dsn' => 'MySQL:dbname=swoft;host=127.0.0.1',
  22. 'username' => 'root',
  23. 'password' => '123456',
  24. ],
  25. ],
  26. ],
  • 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 个数衡量。

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

  1. 'db.pool2' => [
  2. 'class' => Pool::class,
  3. 'database' => \bean('db2'),
  4. 'minActive' => 10,
  5. 'maxActive' => 20,
  6. 'maxWait' => 0,
  7. 'maxWaitTime' => 0,
  8. 'maxIdleTime' => 60,
  9. ]
  • 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 来提供获取连接地址接口